Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: sandbox/src/libraries/core/Identifier.h @ 7192

Last change on this file since 7192 was 6038, checked in by rgrieder, 15 years ago

Synchronised sandbox with current code trunk. There should be a few bug fixes.

  • Property svn:eol-style set to native
File size: 23.2 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @brief Definition of the Identifier class, definition and implementation of the ClassIdentifier class.
32
33    The Identifier contains all needed information about the class it belongs to:
34     - the name
35     - a list with all objects
36     - parents and children
37     - the factory (if available)
38     - the networkID that can be synchronised with the server
39     - all configurable variables (if available)
40
41    Every object has a pointer to the Identifier of its class. This allows the use isA(...),
42    isExactlyA(...), isChildOf(...) and isParentOf(...).
43
44    To create the class-hierarchy, the Identifier has some intern functions and variables.
45
46    Every Identifier is in fact a ClassIdentifier, but they are derived from Identifier.
47*/
48
49#ifndef _Identifier_H__
50#define _Identifier_H__
51
52#include "CorePrereqs.h"
53
54#include <cassert>
55#include <map>
56#include <set>
57#include <string>
58#include <typeinfo>
59
60#include "util/Debug.h"
61#include "util/TypeTraits.h"
62#include "MetaObjectList.h"
63#include "ObjectList.h"
64#include "ObjectListBase.h"
65
66namespace orxonox
67{
68    // ###############################
69    // ###       Identifier        ###
70    // ###############################
71    //! The Identifier is used to identify the class of an object and to store information about the class.
72    /**
73        The Identifier contains all needed information about the class it belongs to:
74         - the name
75         - a list with all objects
76         - parents and children
77         - the factory (if available)
78         - the networkID that can be synchronised with the server
79         - all configurable variables (if available)
80
81        Every object has a pointer to the Identifier of its class. This allows the use isA(...),
82        isExactlyA(...), isChildOf(...) and isParentOf(...).
83
84        You can't directly create an Identifier, it's just the base-class for ClassIdentifier.
85    */
86    class _CoreExport Identifier
87    {
88        public:
89            /** @brief Returns the name of the class the Identifier belongs to. @return The name */
90            inline const std::string& getName() const { return this->name_; }
91            void setName(const std::string& name);
92
93            /** @brief Returns the unique ID of the class */
94            FORCEINLINE unsigned int getClassID() const { return this->classID_; }
95
96            /** @brief Returns the list of all existing objects of this class. @return The list */
97            inline ObjectListBase* getObjects() const { return this->objects_; }
98
99            /** @brief Sets the Factory. @param factory The factory to assign */
100            inline void addFactory(Factory* factory) { this->factory_ = factory; }
101            /** @brief Returns true if the Identifier has a Factory. */
102            inline bool hasFactory() const { return (this->factory_ != 0); }
103
104            BaseObject* fabricate(BaseObject* creator);
105
106            bool isA(const Identifier* identifier) const;
107            bool isExactlyA(const Identifier* identifier) const;
108            bool isChildOf(const Identifier* identifier) const;
109            bool isDirectChildOf(const Identifier* identifier) const;
110            bool isParentOf(const Identifier* identifier) const;
111            bool isDirectParentOf(const Identifier* identifier) const;
112
113
114            /////////////////////////////
115            ////// Class Hierarchy //////
116            /////////////////////////////
117            static void createClassHierarchy();
118
119            /** @brief Returns true, if a branch of the class-hierarchy is being created, causing all new objects to store their parents. @return The status of the class-hierarchy creation */
120            inline static bool isCreatingHierarchy() { return (hierarchyCreatingCounter_s > 0); }
121
122            /** @brief Returns the parents of the class the Identifier belongs to. @return The list of all parents */
123            inline const std::set<const Identifier*>& getParents() const { return this->parents_; }
124            /** @brief Returns the begin-iterator of the parents-list. @return The begin-iterator */
125            inline std::set<const Identifier*>::const_iterator getParentsBegin() const { return this->parents_.begin(); }
126            /** @brief Returns the end-iterator of the parents-list. @return The end-iterator */
127            inline std::set<const Identifier*>::const_iterator getParentsEnd() const { return this->parents_.end(); }
128
129            /** @brief Returns the children of the class the Identifier belongs to. @return The list of all children */
130            inline const std::set<const Identifier*>& getChildren() const { return this->children_; }
131            /** @brief Returns the begin-iterator of the children-list. @return The begin-iterator */
132            inline std::set<const Identifier*>::const_iterator getChildrenBegin() const { return this->children_.begin(); }
133            /** @brief Returns the end-iterator of the children-list. @return The end-iterator */
134            inline std::set<const Identifier*>::const_iterator getChildrenEnd() const { return this->children_.end(); }
135
136            /** @brief Returns the direct parents of the class the Identifier belongs to. @return The list of all direct parents */
137            inline const std::set<const Identifier*>& getDirectParents() const { return this->directParents_; }
138            /** @brief Returns the begin-iterator of the direct-parents-list. @return The begin-iterator */
139            inline std::set<const Identifier*>::const_iterator getDirectParentsBegin() const { return this->directParents_.begin(); }
140            /** @brief Returns the end-iterator of the direct-parents-list. @return The end-iterator */
141            inline std::set<const Identifier*>::const_iterator getDirectParentsEnd() const { return this->directParents_.end(); }
142
143            /** @brief Returns the direct children the class the Identifier belongs to. @return The list of all direct children */
144            inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; }
145            /** @brief Returns the begin-iterator of the direct-children-list. @return The begin-iterator */
146            inline std::set<const Identifier*>::const_iterator getDirectChildrenBegin() const { return this->directChildren_.begin(); }
147            /** @brief Returns the end-iterator of the direct-children-list. @return The end-iterator */
148            inline std::set<const Identifier*>::const_iterator getDirectChildrenEnd() const { return this->directChildren_.end(); }
149
150
151            //////////////////////////
152            ///// Identifier Map /////
153            //////////////////////////
154            static void destroyAllIdentifiers();
155
156            static Identifier* getIdentifierByString(const std::string& name);
157            static Identifier* getIdentifierByLowercaseString(const std::string& name);
158            static Identifier* getIdentifierByID(uint32_t id);
159
160            static void clearNetworkIDs();
161
162            /** @brief Returns the map that stores all Identifiers with their names. @return The map */
163            static inline const std::map<std::string, Identifier*>& getStringIdentifierMap() { return Identifier::getStringIdentifierMapIntern(); }
164            /** @brief Returns a const_iterator to the beginning of the map that stores all Identifiers with their names. @return The const_iterator */
165            static inline std::map<std::string, Identifier*>::const_iterator getStringIdentifierMapBegin() { return Identifier::getStringIdentifierMap().begin(); }
166            /** @brief Returns a const_iterator to the end of the map that stores all Identifiers with their names. @return The const_iterator */
167            static inline std::map<std::string, Identifier*>::const_iterator getStringIdentifierMapEnd() { return Identifier::getStringIdentifierMap().end(); }
168
169            /** @brief Returns the map that stores all Identifiers with their names in lowercase. @return The map */
170            static inline const std::map<std::string, Identifier*>& getLowercaseStringIdentifierMap() { return Identifier::getLowercaseStringIdentifierMapIntern(); }
171            /** @brief Returns a const_iterator to the beginning of the map that stores all Identifiers with their names in lowercase. @return The const_iterator */
172            static inline std::map<std::string, Identifier*>::const_iterator getLowercaseStringIdentifierMapBegin() { return Identifier::getLowercaseStringIdentifierMap().begin(); }
173            /** @brief Returns a const_iterator to the end of the map that stores all Identifiers with their names in lowercase. @return The const_iterator */
174            static inline std::map<std::string, Identifier*>::const_iterator getLowercaseStringIdentifierMapEnd() { return Identifier::getLowercaseStringIdentifierMap().end(); }
175
176            /** @brief Returns the map that stores all Identifiers with their IDs. @return The map */
177            static inline const std::map<uint32_t, Identifier*>& getIDIdentifierMap() { return Identifier::getIDIdentifierMapIntern(); }
178            /** @brief Returns a const_iterator to the beginning of the map that stores all Identifiers with their IDs. @return The const_iterator */
179            static inline std::map<uint32_t, Identifier*>::const_iterator getIDIdentifierMapBegin() { return Identifier::getIDIdentifierMap().begin(); }
180            /** @brief Returns a const_iterator to the end of the map that stores all Identifiers with their IDs. @return The const_iterator */
181            static inline std::map<uint32_t, Identifier*>::const_iterator getIDIdentifierMapEnd() { return Identifier::getIDIdentifierMap().end(); }
182
183
184            /////////////////////////
185            ///// Config Values /////
186            /////////////////////////
187            virtual void updateConfigValues(bool updateChildren = true) const = 0;
188
189            /** @brief Returns true if this class has at least one config value. @return True if this class has at least one config value */
190            inline bool hasConfigValues() const { return this->bHasConfigValues_; }
191
192            /** @brief Returns the map that stores all config values. @return The const_iterator */
193            inline const std::map<std::string, ConfigValueContainer*>& getConfigValueMap() const { return this->configValues_; }
194            /** @brief Returns a const_iterator to the beginning of the map that stores all config values. @return The const_iterator */
195            inline std::map<std::string, ConfigValueContainer*>::const_iterator getConfigValueMapBegin() const { return this->configValues_.begin(); }
196            /** @brief Returns a const_iterator to the end of the map that stores all config values. @return The const_iterator */
197            inline std::map<std::string, ConfigValueContainer*>::const_iterator getConfigValueMapEnd() const { return this->configValues_.end(); }
198
199            /** @brief Returns the map that stores all config values with their names in lowercase. @return The const_iterator */
200            inline const std::map<std::string, ConfigValueContainer*>& getLowercaseConfigValueMap() const { return this->configValues_LC_; }
201            /** @brief Returns a const_iterator to the beginning of the map that stores all config values with their names in lowercase. @return The const_iterator */
202            inline std::map<std::string, ConfigValueContainer*>::const_iterator getLowercaseConfigValueMapBegin() const { return this->configValues_LC_.begin(); }
203            /** @brief Returns a const_iterator to the end of the map that stores all config values with their names in lowercase. @return The const_iterator */
204            inline std::map<std::string, ConfigValueContainer*>::const_iterator getLowercaseConfigValueMapEnd() const { return this->configValues_LC_.end(); }
205
206            void addConfigValueContainer(const std::string& varname, ConfigValueContainer* container);
207            ConfigValueContainer* getConfigValueContainer(const std::string& varname);
208            ConfigValueContainer* getLowercaseConfigValueContainer(const std::string& varname);
209
210
211        protected:
212            Identifier();
213            Identifier(const Identifier& identifier); // don't copy
214            virtual ~Identifier();
215
216            static Identifier* getIdentifierSingleton(const std::string& name, Identifier* proposal);
217
218            void initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass);
219
220            /** @brief Returns the map that stores all Identifiers with their names. @return The map */
221            static std::map<std::string, Identifier*>& getStringIdentifierMapIntern();
222            /** @brief Returns the map that stores all Identifiers with their names in lowercase. @return The map */
223            static std::map<std::string, Identifier*>& getLowercaseStringIdentifierMapIntern();
224            /** @brief Returns the map that stores all Identifiers with their network IDs. @return The map */
225            static std::map<uint32_t, Identifier*>& getIDIdentifierMapIntern();
226
227            /** @brief Returns the children of the class the Identifier belongs to. @return The list of all children */
228            inline std::set<const Identifier*>& getChildrenIntern() const { return this->children_; }
229            /** @brief Returns the direct children of the class the Identifier belongs to. @return The list of all direct children */
230            inline std::set<const Identifier*>& getDirectChildrenIntern() const { return this->directChildren_; }
231
232            ObjectListBase* objects_;                                      //!< The list of all objects of this class
233
234        private:
235            /** @brief Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents. */
236            inline static void startCreatingHierarchy() { hierarchyCreatingCounter_s++; }
237            /** @brief Decreases the hierarchyCreatingCounter_s variable, causing the objects to stop storing their parents. */
238            inline static void stopCreatingHierarchy()  { hierarchyCreatingCounter_s--; }
239
240            static std::map<std::string, Identifier*>& getTypeIDIdentifierMap();
241
242            void initialize(std::set<const Identifier*>* parents);
243
244            std::set<const Identifier*> parents_;                          //!< The parents of the class the Identifier belongs to
245            mutable std::set<const Identifier*> children_;                 //!< The children of the class the Identifier belongs to
246
247            std::set<const Identifier*> directParents_;                    //!< The direct parents of the class the Identifier belongs to
248            mutable std::set<const Identifier*> directChildren_;           //!< The direct children of the class the Identifier belongs to
249
250            bool bCreatedOneObject_;                                       //!< True if at least one object of the given type was created (used to determine the need of storing the parents)
251            bool bSetName_;                                                //!< True if the name is set
252            std::string name_;                                             //!< The name of the class the Identifier belongs to
253            Factory* factory_;                                             //!< The Factory, able to create new objects of the given class (if available)
254            static int hierarchyCreatingCounter_s;                         //!< Bigger than zero if at least one Identifier stores its parents (its an int instead of a bool to avoid conflicts with multithreading)
255            const unsigned int classID_;                                   //!< Uniquely identifies a class (might not be the same as the networkID_)
256            static unsigned int classIDCounter_s;                          //!< Static counter for the unique classIDs
257
258            bool bHasConfigValues_;                                        //!< True if this class has at least one assigned config value
259            std::map<std::string, ConfigValueContainer*> configValues_;    //!< A map to link the string of configurable variables with their ConfigValueContainer
260            std::map<std::string, ConfigValueContainer*> configValues_LC_; //!< A map to link the string of configurable variables with their ConfigValueContainer
261    };
262
263    _CoreExport std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list);
264
265
266    // ###############################
267    // ###     ClassIdentifier     ###
268    // ###############################
269    //! The ClassIdentifier is derived from Identifier and holds all class-specific functions and variables the Identifier cannot have.
270    /**
271        ClassIdentifier is a Singleton, which means that only one object of a given type T exists.
272        This makes it possible to store information about a class, sharing them with all
273        objects of that class without defining static variables in every class.
274
275        To be really sure that not more than exactly one object exists (even with libraries),
276        ClassIdentifiers are stored in the Identifier Singleton.
277    */
278    template <class T>
279    class ClassIdentifier : public Identifier
280    {
281        public:
282            static ClassIdentifier<T> *getIdentifier();
283            static ClassIdentifier<T> *getIdentifier(const std::string& name);
284
285            bool initialiseObject(T* object, const std::string& className, bool bRootClass);
286
287            void updateConfigValues(bool updateChildren = true) const;
288
289        private:
290            static void initialiseIdentifier();
291            ClassIdentifier(const ClassIdentifier<T>& identifier) {}    // don't copy
292            ClassIdentifier()
293            {
294            }
295            ~ClassIdentifier()
296            {
297            }
298
299            static ClassIdentifier<T>* classIdentifier_s;
300    };
301
302    template <class T>
303    ClassIdentifier<T>* ClassIdentifier<T>::classIdentifier_s = 0;
304
305    /**
306        @brief Returns the only instance of this class.
307        @return The unique Identifier
308    */
309    template <class T>
310    inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
311    {
312        // check if the Identifier already exists
313        if (!ClassIdentifier<T>::classIdentifier_s)
314            ClassIdentifier<T>::initialiseIdentifier();
315
316        return ClassIdentifier<T>::classIdentifier_s;
317    }
318
319    /**
320        @brief Does the same as getIdentifier() but sets the name if this wasn't done yet.
321        @param name The name of this Identifier
322        @return The Identifier
323    */
324    template <class T>
325    inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier(const std::string& name)
326    {
327        ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier();
328        identifier->setName(name);
329        return identifier;
330    }
331
332    /**
333        @brief Assigns the static field for the identifier singleton.
334    */
335    template <class T>
336    void ClassIdentifier<T>::initialiseIdentifier()
337    {
338        // Get the name of the class
339        std::string name = typeid(T).name();
340
341        // create a new identifier anyway. Will be deleted in Identifier::getIdentifier if not used.
342        ClassIdentifier<T>* proposal = new ClassIdentifier<T>();
343
344        // Get the entry from the map
345        ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*)Identifier::getIdentifierSingleton(name, proposal);
346
347        if (ClassIdentifier<T>::classIdentifier_s == proposal)
348        {
349            COUT(4) << "*** Identifier: Requested Identifier for " << name << " was not yet existing and got created." << std::endl;
350        }
351        else
352        {
353            COUT(4) << "*** Identifier: Requested Identifier for " << name << " was already existing and got assigned." << std::endl;
354        }
355    }
356
357    /**
358        @brief Adds an object of the given type to the ObjectList.
359        @param object The object to add
360    */
361    template <class T>
362    bool ClassIdentifier<T>::initialiseObject(T* object, const std::string& className, bool bRootClass)
363    {
364        if (bRootClass)
365            COUT(5) << "*** Register Root-Object: " << className << std::endl;
366        else
367            COUT(5) << "*** Register Object: " << className << std::endl;
368
369        object->identifier_ = this;
370        if (Identifier::isCreatingHierarchy())
371        {
372            if (bRootClass && !object->parents_)
373                object->parents_ = new std::set<const Identifier*>();
374
375            if (object->parents_)
376            {
377                this->initializeClassHierarchy(object->parents_, bRootClass);
378                object->parents_->insert(object->parents_->end(), this);
379            }
380
381            object->setConfigValues();
382            return true;
383        }
384        else
385        {
386            COUT(5) << "*** ClassIdentifier: Added object to " << this->getName() << "-list." << std::endl;
387            object->metaList_->add(this->objects_, this->objects_->add(new ObjectListElement<T>(object)));
388
389            // Add pointer of type T to the map in the OrxonoxClass instance that enables "dynamic_casts"
390            object->objectPointers_.push_back(std::make_pair(this->getClassID(), static_cast<void*>(object)));
391            return false;
392        }
393    }
394
395    /**
396        @brief Updates the config-values of all existing objects of this class by calling their setConfigValues() function.
397    */
398    template <class T>
399    void ClassIdentifier<T>::updateConfigValues(bool updateChildren) const
400    {
401        if (!this->hasConfigValues())
402            return;
403
404        for (ObjectListIterator<T> it = ObjectList<T>::begin(); it; ++it)
405            it->setConfigValues();
406
407        if (updateChildren)
408            for (std::set<const Identifier*>::const_iterator it = this->getChildrenBegin(); it != this->getChildrenEnd(); ++it)
409                (*it)->updateConfigValues(false);
410    }
411
412
413    // ###############################
414    // ###      orxonox_cast       ###
415    // ###############################
416    /**
417    @brief
418        Casts on object of type OrxonoxClass to any derived type that is
419        registered in the class hierarchy.
420    @return
421        Returns NULL if the cast is not possible
422    @note
423        In case of NULL return (and using MSVC), a dynamic_cast might still be possible if
424        a class forgot to register its objects.
425        Also note that the function is implemented differently for GCC/MSVC.
426    */
427    template <class T, class U>
428    FORCEINLINE T orxonox_cast(U source)
429    {
430#ifdef ORXONOX_COMPILER_MSVC
431        typedef Loki::TypeTraits<typename Loki::TypeTraits<T>::PointeeType>::NonConstType ClassType;
432        if (source != NULL)
433            return source->template getDerivedPointer<ClassType>(ClassIdentifier<ClassType>::getIdentifier()->getClassID());
434        else
435            return NULL;
436#else
437        return dynamic_cast<T>(source);
438#endif
439    }
440}
441
442#endif /* _Identifier_H__ */
Note: See TracBrowser for help on using the repository browser.