Veda/BaseContext.h

Go to the documentation of this file.
00001 /*! \file 
00002     \author victorien ferry & www.m4nkind.com
00003     \brief This file applies the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 , read file COPYING.
00004 */
00005 #ifndef COM_M4NKIND_BaseContext_H
00006 #define COM_M4NKIND_BaseContext_H
00007 
00008 #include "BaseObject.h"
00009 #include "ClassNode.h"
00010 #include "PackList.h"
00011 
00012 class PackObjectReference;
00013 class PackResource;
00014 class VirtualMachine;
00015 /*!
00016     \class BaseContextTool
00017     \brief base model for extending more Tool Methods to BaseContext.
00018 */
00019 class BaseContextTool {};
00020 
00021 /*!
00022     \class  BaseContext
00023     \ingroup BaseContextDocGroup
00024     \brief  \ref BaseContextDocGroup "You may also browse the BaseContext Related Documentations page sorted by theme."\n
00025             Class that manages a whole database as a set of Objects inheriting class BaseObject.\n 
00026             BaseContext::Serialize_Out() and BaseContext::Serialize_In() will provide a quick and full
00027             persistent serialization of all features of a whole azurveda Context. When reading the context,
00028             the objects references will be resolved.
00029             In editable compilation mode you can use:
00030                 - Hook notifications for all events, useful for Graphical Interfaces: see AddGUIUpdateFunction()
00031                 - Merge serialization: simply melt as many context objects you want with MergeSerialize_In()
00032                 - Hability to destroy all objects that are useless to a given object with DestroyAllIndependantObjects().
00033                     Together with the merge method, it gives a complete control for large and complex contexts.
00034                 - automatic Undo/Redo stack functionnalities with Undo(), Redo(), SetMaximumNumberOfUndoableEvents().
00035                     This undoes affect the modification of any editable object members in the context.
00036                     (BETA: currently,undo stack is flushed when an element is destroyed in a list.)
00037                 - Thread management withAddOneLockForThreadUse(),RemoveOneLockForThreadUse().\n
00038             \n
00039             To use a context object, you first init a context by registering possible extended classes
00040             or packages, derived from BaseObject, with RegisterClassList().
00041             In editable mode, you can create new BaseObjects using the BaseContext::NewObject(), and destroy them with
00042             BaseContext::DestroyObject(). Then you can initialize each objects using BaseObject::Create(), and close
00043             them with BaseObject::Close(). See BaseObject for more informations on Object Creation.\n
00044             After the context is created, you can provide a VirtualMachine with SetMachine(),
00045             it stands for the hardware-abstracted machine its objects will use.\n
00046 
00047             Low Level internal notes:
00048             - Internally, and transparently for the user, BaseContext manage a tree of the known classes with ClassNode.
00049             - BaseContext is derived from ClassNode, it Manages the virtual 'BaseObject', as a ClassNode.
00050             - It is possible to get the serialized size of the whole context at any moment with GetSerializedSize()
00051 */
00052 class BaseContext : public ClassNode
00053 {
00054 /*==================================================================
00055                                 PUBLIC
00056 ==================================================================*/
00057 public:
00058     friend class BaseObject;
00059     friend class BaseContextTool;
00060     friend class PackResource;
00061     friend class PackObjectReference;
00062     /*!
00063         \ingroup BaseContextDocGroup_InitMethods
00064         \brief  Constructor. 
00065     */
00066     BaseContext(void);
00067 #ifdef _ENGINE_EDITABLE_
00068     /*!
00069         \ingroup BaseContextDocGroup_InitMethods
00070         \brief  Destructor. 
00071     */
00072     virtual ~BaseContext(void);
00073 #endif
00074 #ifdef _ENGINE_EDITABLE_
00075     /*!
00076         \ingroup    BaseContextDocGroup_ObjectEditionMethods
00077         \brief  Faktory Method to create a new Object in the context. All object members
00078                 should be inited to default, then use BaseObject's Set methods in editable mode to modify them.
00079                 You must pass a valid Class descriptor and an _ObjectName, or nothing, in which case
00080                 a name will be computed according to the class. If an object with the same name
00081                 exists, then a new name is computed. get the final name with BaseObject::GetName();
00082                 This method is only compiled in editable mode, in non-editable, Serialize_In() should construct everything.
00083         \param _classDescription the description struct of a class, like BaseObject::m_Description
00084         \param _ObjectName. the objectName then used to reference it can be NULL, then a new name is computed.
00085         \return The Object Created. 0L if class unknown or anywhat.
00086     */
00087     BaseObject *NewObject(  const BaseObject::ClassDescription & _classDescription ,char *  _ObjectName=0L );
00088 #endif
00089 #ifdef _ENGINE_EDITABLE_
00090     /*!
00091         \ingroup    BaseContextDocGroup_ObjectEditionMethods
00092         \brief  In editable mode, it is possible to destroy an object from the context base:
00093                 You got to use this method, not "delete".
00094         \param _objectToDelete The object to delete.
00095     */
00096     void    DestroyObject( BaseObject * _objectToDelete );
00097 #endif
00098 #ifdef _ENGINE_EDITABLE_
00099     /*!
00100         \ingroup    BaseContextDocGroup_ObjectEditionMethods
00101         \brief  Really destroy all object from the context. It should result a clean
00102             context like it it was just constructed empty.
00103     */
00104     void    DestroyAllObjects( );
00105 #endif
00106 #ifdef _ENGINE_EDITABLE_
00107     /*!
00108         \ingroup    BaseContextDocGroup_ObjectEditionMethods
00109         \brief  All File Resources used by objects in the context will be set
00110             as binaries Linked within the context, or not according to parameter.
00111         \param  _isLink true: is linked, false, is in file.
00112     */
00113     void    Resources_SetLinkModeToAll(bool _isLink );
00114 #endif
00115     /*!
00116         \ingroup    BaseContextDocGroup_InputOutputMethods
00117         \brief  Read the object description from a byte chunk. Could crash if chunk not valid.
00118                 It serializes first the class name, the number of object instancied, then
00119                 the number of sub-classnodes instancied, then all object instancied, then
00120                 all subclasses recursively.
00121     */
00122     virtual  const unsigned char * Serialize_In( const unsigned char * _pDescriptionChunk);
00123 #ifdef _ENGINE_EDITABLE_
00124     /*!
00125         \ingroup    BaseContextDocGroup_InputOutputMethods
00126         \brief  get the size of the whole byte chunk that will be written by Serialize_Out().
00127         \return byte size of the serialisation to do.
00128     */
00129     virtual unsigned int  GetSerializedDescriptionSize(void);
00130 #endif
00131 #ifdef _ENGINE_EDITABLE_
00132     /*!
00133         \ingroup    BaseContextDocGroup_InputOutputMethods
00134         \brief  write the Current object definition to a Chunk using private packed types, recursively.
00135         \param  _pDescriptionChunkToFill the chunk where to write the objet description chunk. 
00136         \return the end of the chunk written, possibly unlocated. Don't use this if you don't need it.
00137     */
00138     virtual unsigned char * Serialize_Out(unsigned char * _pDescriptionChunkToFill);
00139 #endif
00140     /*!
00141         \ingroup BaseContextDocGroup_InitMethods
00142         \brief  Link a VirtualMachine object to the Context, to provide
00143                 a hardware/API abstraction that objects will use. 
00144                 You must use this after the constructor and before serialization 
00145                 or any edition. the context DOES NOT manage machine object destruction.
00146                 so don't destroy it 'till context is destroyed.
00147         \param  _pMachine  the machine then used by the context
00148     */
00149     virtual void SetMachine( VirtualMachine *_pMachine ){ m_pMachine =_pMachine;  };
00150     /*!
00151         \ingroup BaseContextDocGroup_InitMethods
00152         \brief  return the machine currently linked to the context.
00153         \param  _pMachine  the machine then used by the context
00154     */
00155     inline VirtualMachine *GetMachine(){ return m_pMachine; };
00156 
00157 #ifdef _ENGINE_EDITABLE_
00158     /*!
00159         \brief  Each BaseType's inherited classes must explicit an ID for their
00160                 class, or let use one of the super class at least through this virtual method.
00161                 This is needed by GUIs to detect the types of each sub-members, and shape
00162                 an interface for each Object according to their member list.
00163         \return a const character string, that must be unique and unchanged for all serializable base type.
00164     */
00165     virtual const char *GetClassID() const { return "BaseContext"; };
00166 #endif
00167 #ifdef _ENGINE_EDITABLE_
00168 
00169     /*!
00170         \ingroup BaseContextDocGroup_EventManagement
00171         \brief Used by BaseObjects "%Set()" member methods to notify what happened when one of 
00172                 the member was edited, to change its value. It is used to manage the Undo/Redo capability.
00173                 You should not use this method unless you create a PackSerializable base type and code it's Set() accessor.
00174         \param _UpDateType eVedaUpdate enum that identify the update info type.
00175         \param _pObjectEdited   BaseObject if _UpDateType is about an object or member.
00176         \param _ObjectMember    BaseType if _UpDateType is about a member.
00177         \param _PreviousShapeChunk  optionnal serialization of the previous state or 0L.
00178         \param _PreviousShapeChunkLength optionnal serialization of the previous state or 0L.
00179         \param _NewShapeChunk optionnal serialization of the new state or 0L.
00180         \param _NewShapeChunkLength optionnal serialization of the new state or 0L.
00181     */
00182     void NotifyObjectChange( eVedaUpdate _UpDateType, BaseObject *_pObjectEdited, BaseType *_ObjectMember,
00183                                 const unsigned char *_PreviousShapeChunk=0L,
00184                                 unsigned int         _PreviousShapeChunkLength=0L,
00185                                 const unsigned char *_NewShapeChunk=0L,
00186                                 unsigned int         _NewShapeChunkLength=0L
00187                                 );
00188 #endif
00189     /*!
00190         \brief used to scan the list of all object-to-object reference in this context.
00191                 you can scan the list by then using PackObjectReference::GetPointerOnNextObjectReferenceInContextList()
00192         \return the first PackObjectReference.
00193     */
00194     inline PackObjectReference      *GetFirstObjectReferenceInContextList(){ return m_pFirstObjectReferenceInContextList; };
00195 
00196 #ifdef _ENGINE_EDITABLE_
00197     /*!
00198         \ingroup BaseContextDocGroup_Undoing
00199         \brief  test if an Undo() is currently possible. Useful to enable or disable an
00200                 Undo Function in an interface.
00201         \return true if it is.
00202     */
00203     virtual bool CanUndo();
00204 #endif
00205 #ifdef _ENGINE_EDITABLE_
00206     /*!
00207         \ingroup BaseContextDocGroup_Undoing
00208         \brief  Undo the last modification done on any object of the base, using a private "action history stack".
00209         \return true if the undo was "undone", false if no more undo available.
00210     */
00211     virtual bool Undo();
00212 #endif
00213 #ifdef _ENGINE_EDITABLE_
00214     /*!
00215         \ingroup BaseContextDocGroup_Undoing
00216         \brief  test if an Redo() is currently possible. Useful to enable or disable a
00217                 Redo Function in an interface.
00218         \return true if it is.
00219     */
00220     virtual bool CanRedo();
00221 #endif
00222 #ifdef _ENGINE_EDITABLE_
00223     /*!
00224         \ingroup BaseContextDocGroup_Undoing
00225         \brief  Redo the last undo on any object of the base, using a private "action history stack".       
00226         \return true if the last undo was "redone", false if no more redo available.
00227     */
00228     virtual bool Redo();
00229 #endif
00230 #ifdef _ENGINE_EDITABLE_
00231     /*!
00232         \ingroup BaseContextDocGroup_Undoing
00233         \brief  Flush the Undo Stack: no undo or redo possible until next modification.
00234                 Some edition events (object destruction) on the context need to completely 
00235         erase the Undo stack, because the event stack coherence is broken.
00236     */
00237     void FlushUndoStack();
00238 #endif
00239 #ifdef _ENGINE_EDITABLE_
00240     /*!
00241         \ingroup BaseContextDocGroup_Undoing
00242         \brief  The undo stack history can be less or more large. Default max is 0: no undo management.
00243         \param _maxnumber maximum number of undoable event.
00244     */
00245     void SetMaximumNumberOfUndoableEvents( unsigned int _maxNumber );
00246 #endif
00247 #ifdef _ENGINE_EDITABLE_
00248     /*!
00249         \ingroup BaseContextDocGroup_EventManagement
00250         \brief  You can specify one or more abstract GUI Views to update, by
00251         registering a function or a static method, that will be executed
00252         after each set() done on a member of a managed object, when editing, 
00253         and even for a undo/redoes. This function will receive a const description of what 
00254         was changed: the context concerned, the object concerned, and the object member concerned. 
00255         \param _func You must pass a function pointer on a static method pointer.
00256         \param _GUIObjectToUpdate a user object of your choice that will be returned for this function, or NULL.
00257     */
00258     void AddGUIUpdateFunction(  void (*_func)(void *_GUIObjectToUpdateReturned,eVedaUpdate _updateType,BaseContext *_ContextUpdated,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated) ,
00259                                 void *_GUIObjectToUpdate
00260                                 );
00261 #endif
00262 #ifdef _ENGINE_EDITABLE_
00263     /*!
00264         \ingroup BaseContextDocGroup_EventManagement
00265         \brief  Remove an update function set by AddGUIUpdateFunction()
00266         \param _func the func pointer to remove.
00267         \return true if removed, false if unknown.
00268     */
00269     bool RemoveGUIUpdateFunction(   void (*_func)(void *_GUIObjectToUpdateReturned,eVedaUpdate _updateType,BaseContext *_ContextUpdated,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated)) ;
00270 #endif
00271 #ifdef _ENGINE_EDITABLE_
00272     /*!
00273         \ingroup BaseContextDocGroup_EventManagement
00274         \brief  send an update function to all registered GUIs.
00275         \param the update case.
00276         \param _ObjectUpdated the object updated in this context.
00277         \param _MemberUpdated the member of the object updated.
00278     */
00279     void UpdateAllGUI( eVedaUpdate _updateType,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated);
00280 #endif
00281 
00282 #ifdef _ENGINE_EDITABLE_
00283     /*!
00284         \ingroup    BaseContextDocGroup_ObjectEditionMethods
00285         \brief  Remove all objects that are not refered directly or indirectly by the object passed.
00286         \param  _pObjectWhichAllOtherShouldDependOn Object Which All Other Should Depend On.
00287     */
00288     void DestroyAllIndependantObjects( BaseObject *_pObjectWhichAllOtherShouldDependOn );
00289 #endif
00290 #ifdef _ENGINE_EDITABLE_
00291     /*!
00292         \ingroup    BaseContextDocGroup_InputOutputMethods
00293         \brief  Acts like Serialize_In() but keep all previous objects.
00294                 So you can load and mix 2 or more context this way.
00295         \param  _pDescriptionChunk the binary image of a context.
00296         \param _pendName specify a name to add at the end of each new object.
00297     */
00298     virtual  const unsigned char * MergeSerialize_In( const unsigned char * _pDescriptionChunk,const char *_pendName=0L);
00299 #endif
00300 #ifdef _ENGINE_EDITABLE_
00301     /*!
00302         \ingroup BaseContextDocGroup_EventManagement
00303         \brief  Even in editable mode, only one thread owns a context and can
00304                 edit, modify, use and destroy it. Other threads can just use 
00305                 its objects and methods through a AddOneLockForThreadUse()
00306                 RemoveOneLockForThreadUse() pair. If false is returned,
00307                 it means the lock can't be done, and you should wait a bit and retry.
00308                 This way, it avoids cases where an object is modified by the owner thread
00309                 and used by another.(For Example, the sound management thread of the Machines use it.)
00310                 Add/RemoveOneLockForThreadUse() must only be used by other threads.
00311                 Don't use RemoveOneLockForThreadUse() if false is returned.
00312             
00313                 Note: you can't use BaseObject::Create() on an object from another thread.
00314                 But you have to test isCreated() before using object's method, like in the main thread:
00315                 isCreated() ensures the object is coherently inited.
00316     */
00317     virtual  bool AddOneLockForThreadUse();
00318 #endif
00319 #ifdef _ENGINE_EDITABLE_
00320     /*!
00321         \ingroup BaseContextDocGroup_EventManagement
00322         \brief  Even in editable mode, only one thread owns a context and can
00323                 edit, modify, use and destroy it. Other threads can just use 
00324                 its objects and methods through a AddOneLockForThreadUse()
00325                 RemoveOneLockForThreadUse() pair. This is to avoid using an object
00326                 which could be modified or destroyed by the owner thread.
00327                 (it was made for sound management.)
00328     */
00329     virtual  void RemoveOneLockForThreadUse();
00330 #endif
00331 
00332 #ifdef _ENGINE_EDITABLE_
00333     /*!
00334         \ingroup    BaseContextDocGroup_ObjectEditionMethods
00335         \brief  give to _ContextToModify the same shape as this.
00336                 It means, the same classes are first registered to it, and then 
00337                 the same objects are cloned into it.
00338         \param  _pContextToModify to object modified to shape this.
00339     */
00340     void CloneClassesAndObjects(BaseContext *_pContextToModify);
00341 #endif
00342 
00343 #ifdef _ENGINE_EDITABLE_
00344     /*!
00345         \ingroup    BaseContextDocGroup_InputOutputMethods
00346         \brief  Export a .cpp file with 2 tables:
00347                     - First, a table of all the class descriptors used by the context, and
00348                     that can be used with RegisterClassList().
00349                     - Then, the context serialization binary, standing as a unsigned char table.
00350                 - This can be used for automatic executable generation by some implementations.
00351         \param  _filePath the path of the file to write. '.c' is added.
00352         \param  _pGobalTableName the name of the global variable in the .c file
00353         \param  _optimize if true, names are flushed and preferences destroyed, in a clone.
00354     */
00355     void ExportAsCPPTableFile(const char *_pfileToExport,const char *_pGobalTableName,bool _optimize=true);
00356 #endif
00357 #ifdef _ENGINE_EDITABLE_
00358     /*!
00359         \brief Get first element of the resource list. It lists all 
00360             Resources used as members in the objects. get the next with
00361             GetPointerOnNextResourceInContextList()
00362         \return the first resource
00363     */
00364     inline PackResource *GetFirstResourceInContextList() { return m_pFirstResourceInContextList; };
00365 #endif
00366 /*==================================================================
00367                                 PROTECTED
00368 ==================================================================*/
00369 protected:
00370     //! The context knows a list of all object-to-object references. This list is updated when the context is edited, and is used for reference resolution at input serialization.
00371     PackObjectReference     *m_pFirstObjectReferenceInContextList;
00372     //! The context knows or not a machine to use for hardware/API abstraction. This is not created or destroyed by the context.
00373     VirtualMachine          *m_pMachine;
00374 #ifdef _ENGINE_EDITABLE_
00375     //! The context knows a list of managed resource members.
00376     PackResource    *m_pFirstResourceInContextList;
00377 #endif
00378     /*!
00379         \brief  link a new PackObjectReference to the context list. Done at object member inition.
00380         \param  _pObjectReferenceToLink the new reference to link. 
00381     */
00382     void    LinkObjectReference( PackObjectReference *_pObjectReferenceToLink );
00383 #ifdef _ENGINE_EDITABLE_
00384     /*!
00385         \brief  remove a PackObjectReference from the context list, at its deletion.
00386         \param  _pReferenceToUnlink ...
00387     */
00388     void UnLinkObjectReference( PackObjectReference *_pReferenceToUnlink );
00389 #endif
00390 #ifdef _ENGINE_EDITABLE_
00391     /*!
00392         \brief  link a new PackResource to the context list. Done at object member inition.
00393                 It makes possible to keep an exact list of all managed resources.
00394         \param  _pResourceToLink the new reference to link. 
00395     */
00396     void    LinkResource( PackResource *_pResourceToLink );
00397 #endif
00398 #ifdef _ENGINE_EDITABLE_
00399     /*!
00400         \brief  remove a PackResource from the context list, at its deletion.
00401         \param  _pResourceToUnlink ...
00402     */
00403     void UnLinkResource( PackResource *_pResourceToUnlink );
00404 #endif
00405 #ifdef _ENGINE_EDITABLE_
00406     //! the nested class used by BaseContext::m_GUIUpdateFunctionList to manage a list of functions to send updates when the context is edited.
00407     class UpdateFunctionListCell : public PackStruct
00408     { public:
00409          void (*m_func)(void *_GUIObjectToUpdateReturned,eVedaUpdate _updateType,BaseContext *_ContextUpdated,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated);
00410          void *m_UserObject;
00411          static BaseType *NewCell(){ return new UpdateFunctionListCell(); };
00412     };
00413     //! The list of GUI functions to update when editing this context:
00414     PackList            m_GUIUpdateFunctionList;
00415 #endif
00416 
00417 #ifdef _ENGINE_EDITABLE_
00418     //! the nested class used as cells of the undo stack:
00419     class UndoCell : public PackStruct
00420     { 
00421     public:     
00422             UndoCell();
00423             void Init(unsigned int _editionType,BaseType *_pObjectMemberEdited,const unsigned char *_PreviousValueChunk,unsigned int _PreviousValueChunkLength,const unsigned char *_AfterValueChunk,unsigned int _AfterValueChunkLength);
00424             virtual ~UndoCell(void);
00425             inline BaseType *GetMemberToChange(){ return m_pObjectMemberEdited;};
00426             inline unsigned char *GetPreviousValueChunk(){ return m_pPreviousValueChunk;};
00427             inline unsigned char *GetAfterValueChunk(){ return m_pAfterValueChunk;};
00428             static BaseType *NewCell(){ return new UndoCell(); };
00429     protected:
00430         unsigned int            m_EditionType; // only 0 managed for the moment: member change.
00431         BaseType    *m_pObjectMemberEdited;
00432         unsigned char           *m_pPreviousValueChunk;
00433         unsigned char           *m_pAfterValueChunk;
00434     };
00435     //! The stack of undoable/redoable events:
00436     PackList            m_UndoStack;
00437     //! the cell of m_UndoStack currently focused by  m_UndoStack;
00438     PackStruct::Cell    *m_pCurrentUndoCell;
00439     //! The current number of undo-able events:
00440     unsigned int            m_CurrentNumberOfUndoableEvents;
00441     //! The maximum number of undo-able events:
00442     unsigned int            m_MaximumNumberOfUndoableEvents;
00443 #endif
00444 #ifdef _ENGINE_EDITABLE_
00445     /*!
00446         \brief  Updates all reference members of the context so that the refered
00447         object 's serialization ID is took as serialized value.
00448     */
00449     void UpdateAllReferencesSerializationID();
00450 #endif
00451 };
00452 
00453 #endif

      /\/\        4         N         k         !         N         D
                      _______  _ __ ___  _____            ___ _ _  ____
     ___________  __//___   /________  |/    / ___________\_______/    \
    /   _   _   \/   _     /    _   /      _/_/____/    _       __     /
   /    /   /       /     /    /    \      \/     /    /    \   \     /
  \\___/___/___/    ¯    _____/_____/       ______\___/_____/\________\\
               \________/_ ___ __ l____\      /elD!  
                 http://www.m4nkind.com \____/