Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy/src/orxonox/core/Identifier.h @ 365

Last change on this file since 365 was 365, checked in by landauf, 16 years ago

added comments

File size: 15.3 KB
RevLine 
[365]1/*!
2    @file Identifier.h
3    @brief Definition of the Identifier, ClassIdentifier and SubclassIdentifier classes.
4
5    The Identifier contains all needed informations about the class it belongs to:
6     - the name
7     - a list with all objects
8     - parents and childs
9     - the factory, if available
10     - the networkID that can be synchronised with the server
11
12    Every object has a pointer to the Identifier of its class. This allows the use isA(...),
13    isDirectlyA(...), isChildOf(...) and isParentOf(...).
14
15    To create the class-hierarchy, the Identifier has some intern functions and variables.
16
17    Every Identifier is in fact a ClassIdentifier, but they are derived from Identifier.
18
19    SubclassIdentifier is a separated class, acting like an Identifier, but has a given class.
20    You can only assign Identifiers of the given class or a derivative to a SubclassIdentifier.
21*/
22
[197]23#ifndef _Identifier_H__
24#define _Identifier_H__
25
[219]26#include <iostream>
27
[197]28#include "IdentifierList.h"
29#include "ObjectList.h"
[218]30#include "Factory.h"
[197]31
[246]32#define HIERARCHY_VERBOSE false
[219]33
34
[197]35namespace orxonox
36{
[365]37    class BaseObject; // Forward declaration
[219]38
[224]39    // ###############################
40    // ###       Identifier        ###
41    // ###############################
[365]42    //! The Identifier is used to identify the class of an object and to store informations about the class.
43    /**
44        The Identifier contains all needed informations about the class it belongs to:
45         - the name
46         - a list with all objects
47         - parents and childs
48         - the factory, if available
49         - the networkID that can be synchronised with the server
50
51        Every object has a pointer to the Identifier of its class. This allows the use isA(...),
52        isDirectlyA(...), isChildOf(...) and isParentOf(...).
53
54        You can't directly create an Identifier, it's just the base-class for ClassIdentifier.
55    */
[197]56    class Identifier
57    {
58        template <class T>
[365]59        friend class ClassIdentifier; // Forward declaration
[197]60
61        template <class T>
[365]62        friend class SubclassIdentifier; // Forward declaration
[197]63
[244]64        template <class T>
[365]65        friend class ClassFactory; // Forward declaration
[244]66
[197]67        public:
[365]68            /** @brief Sets the Factory. @param facotry The factory to assign */
[244]69            inline void addFactory(BaseFactory* factory) { this->factory_ = factory; }
[365]70
[244]71            BaseObject* fabricate();
[218]72
[239]73            bool isA(const Identifier* identifier) const;
74            bool isDirectlyA(const Identifier* identifier) const;
75            bool isChildOf(const Identifier* identifier) const;
76            bool isParentOf(const Identifier* identifier) const;
[197]77
[365]78            /** @returns the name of the class the Identifier belongs to. */
[244]79            inline const std::string& getName() const { return this->name_; }
[365]80
81            /** @returns the parents of the class the Identifier belongs to. */
[244]82            inline const IdentifierList& getParents() const { return this->parents_; }
[365]83
84            /** @returns the children of the class the Identifier belongs to. */
[244]85            inline IdentifierList& getChildren() const { return *this->children_; }
[197]86
[365]87            /** @returns true, if a branch of the class-hierarchy is getting created, causing all new objects to store their parents. */
[244]88            inline static bool isCreatingHierarchy() { return (hierarchyCreatingCounter_s > 0); }
[219]89
[365]90            /** @returns the NetworkID to identify a class through the network. */
[362]91            inline const unsigned int getNetworkID() const { return this->classID_; }
[365]92
[362]93            void setNetworkID(unsigned int id);
94
[197]95        private:
96            Identifier();
[365]97            Identifier(const Identifier& identifier) {} // don't copy
[197]98            virtual ~Identifier();
[239]99            void initialize(const IdentifierList* parents);
[197]100
[365]101            /**
102                @brief Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents.
103            */
[244]104            inline static void startCreatingHierarchy()
[231]105            {
106                hierarchyCreatingCounter_s++;
107#if HIERARCHY_VERBOSE
108                std::cout << "*** Increased Hierarchy-Creating-Counter to " << hierarchyCreatingCounter_s << "\n";
109#endif
110            }
[197]111
[365]112            /**
113                @brief Decreases the hierarchyCreatingCounter_s variable, causing the objects to stop storing their parents.
114            */
[244]115            inline static void stopCreatingHierarchy()
[231]116            {
117                hierarchyCreatingCounter_s--;
118#if HIERARCHY_VERBOSE
119                std::cout << "*** Decreased Hierarchy-Creating-Counter to " << hierarchyCreatingCounter_s << "\n";
120#endif
121            }
122
[365]123            IdentifierList parents_;                    //!< The Parents of the class the Identifier belongs to
124            IdentifierList* children_;                  //!< The Children of the class the Identifier belongs to
[219]125
[365]126            std::string name_;                          //!< The name of the class the Identifier belongs to
[197]127
[365]128            BaseFactory* factory_;                      //!< The Factory, able to create new objects of the given class
129            bool bCreatedOneObject_;                    //!< True if at least one object of the given type was created (used to determine the need of storing the parents)
130            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)
131            static unsigned int classIDcounter_s;       //!< The number of unique Identifiers
132            unsigned int classID_;                      //!< The networkID to identify a class through the network
[197]133    };
134
135
[224]136    // ###############################
137    // ###     ClassIdentifier     ###
138    // ###############################
[365]139    //! The ClassIdentifier is derived from Identifier and holds all class-specific functions and variables the Identifier cannot have.
140    /**
141        ClassIdentifier is a Singleton, which means that only one object of a given type T exists.
142        This makes it possible to store informations about a class, sharing them with all
143        objects of that class without defining static variables in every class.
144    */
[197]145    template <class T>
146    class ClassIdentifier : public Identifier
147    {
148        public:
[244]149            static ClassIdentifier<T>* registerClass(const IdentifierList* parents, const std::string& name, bool bRootClass);
[197]150            static ClassIdentifier<T>* getIdentifier();
[224]151            static void addObject(T* object);
[197]152
153        private:
154            ClassIdentifier();
[365]155            ClassIdentifier(const ClassIdentifier<T>& identifier) {} // don't copy
[197]156            ~ClassIdentifier();
157
[365]158            static ClassIdentifier<T>* pointer_s;       //!< A pointer to the singleton-object
159            ObjectList<T>* objects_;                    //!< The ObjectList, containing all objects of type T
[197]160    };
161
162    template <class T>
[365]163    ClassIdentifier<T>* ClassIdentifier<T>::pointer_s = NULL; // Set the static member variable pointer_s to zero
[197]164
[365]165    /**
166        @brief Constructor: Create the ObjectList.
167    */
[197]168    template <class T>
169    ClassIdentifier<T>::ClassIdentifier()
170    {
[239]171        this->objects_ = new ObjectList<T>;
[197]172    }
173
[365]174    /**
175        @brief Destructor: Delete the ObjectList, set the singleton-pointer to zero.
176    */
[197]177    template <class T>
178    ClassIdentifier<T>::~ClassIdentifier()
179    {
[239]180        delete this->objects_;
[219]181        this->pointer_s = NULL;
[197]182    }
183
[365]184    /**
185        @brief Registers a class, which means that the name and the parents get stored.
186        @param parents An IdentifierList, containing the Identifiers of all parents of the class
187        @param name A string, containing exactly the name of the class
188        @param bRootClass True if the class is either an Interface or BaseObject itself
189        @return The ClassIdentifier itself
190    */
[197]191    template <class T>
[244]192    ClassIdentifier<T>* ClassIdentifier<T>::registerClass(const IdentifierList* parents, const std::string& name, bool bRootClass)
[218]193    {
[231]194#if HIERARCHY_VERBOSE
[197]195        std::cout << "*** Register Class in " << name << "-Singleton.\n";
[231]196#endif
[365]197
198        // It's a singleton, so maybe we have to create it first
[219]199        if (!pointer_s)
[197]200        {
[231]201#if HIERARCHY_VERBOSE
[197]202            std::cout << "*** Register Class in " << name << "-Singleton -> Create Singleton.\n";
[231]203#endif
[244]204            pointer_s = new ClassIdentifier();
205        }
[218]206
[365]207        // Check if at least one object of the given type was created
[244]208        if (!pointer_s->bCreatedOneObject_)
209        {
[365]210            // If no: We have to store the informations and initialize the Identifier
211
[244]212#if HIERARCHY_VERBOSE
213            std::cout << "*** Register Class in " << name << "-Singleton -> Initialize Singleton.\n";
214#endif
215            pointer_s->name_ = name;
[365]216            Factory::add(name, pointer_s); // Add the Identifier to the Factory
[218]217
[244]218            if (bRootClass)
[365]219                pointer_s->initialize(NULL); // If a class is derived from two interfaces, the second interface might think it's derived from the first because of the order of constructor-calls. Thats why we set parents to zero in that case.
[197]220            else
[244]221                pointer_s->initialize(parents);
[197]222        }
223
[219]224        return pointer_s;
[197]225    }
226
[365]227    /**
228        @returns the Identifier itself
229    */
[197]230    template <class T>
231    ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
232    {
[219]233        if (!pointer_s)
[197]234        {
[231]235#if HIERARCHY_VERBOSE
[244]236            std::cout << "*** Create Singleton.\n";
[231]237#endif
[244]238            pointer_s = new ClassIdentifier();
[197]239        }
240
[219]241        return pointer_s;
[197]242    }
243
[365]244    /**
245        @brief Adds an object of the given type to the ObjectList.
246        @param object The object to add
247    */
[224]248    template <class T>
249    void ClassIdentifier<T>::addObject(T* object)
250    {
[231]251#if HIERARCHY_VERBOSE
[224]252        std::cout << "*** Added object to " << ClassIdentifier<T>::getIdentifier()->getName() << "-list.\n";
[231]253#endif
[365]254        object->getMetaList().add(ClassIdentifier<T>::getIdentifier()->objects_, ClassIdentifier<T>::getIdentifier()->objects_->add(object));
[224]255    }
256
257
258    // ###############################
[242]259    // ###   SubclassIdentifier    ###
[224]260    // ###############################
[365]261    //! The SubclassIdentifier acts almost like an Identifier, but has some prerequisites.
262    /**
263        You can only assign Identifiers that belong to a class of at least B (or derived) to a SubclassIdentifier<T>.
264        If you assign something else, the program aborts.
265        Because we know the minimal type, a dynamic_cast is done, which makes it easier to create a new object.
266    */
267    template <class T>
[242]268    class SubclassIdentifier
[197]269    {
270        public:
[365]271            /**
272                @brief Constructor: Automaticaly assigns the Identifier of the given class.
273            */
274            SubclassIdentifier()
275            {
276                this->identifier_ = ClassIdentifier<T>::getIdentifier();
277            }
[197]278
[365]279            /**
280                @brief Overloading of the = operator: assigns the identifier and checks its type.
281                @param identifier The Identifier to assign
282                @return The SubclassIdentifier itself
283            */
284            SubclassIdentifier<T>& operator=(Identifier* identifier)
[197]285            {
[365]286                if (!identifier->isA(ClassIdentifier<T>::getIdentifier()))
[197]287                {
[365]288                    std::cout << "Error: Class " << identifier->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << "!\n";
289                    std::cout << "Error: SubclassIdentifier<" << ClassIdentifier<T>::getIdentifier()->getName() << "> = Class(" << identifier->getName() << ") is forbidden.\n";
[197]290                    std::cout << "Aborting...\n";
291                    abort();
292                }
293                this->identifier_ = identifier;
294                return *this;
295            }
[218]296
[365]297            /**
298                @brief Overloading of the * operator: returns the assigned identifier.
299                @return The assigned identifier
300            */
[221]301            Identifier* operator*()
[218]302            {
303                return this->identifier_;
304            }
305
[365]306            /**
307                @brief Overloading of the -> operator: returns the assigned identifier.
308                @return The assigned identifier
309            */
[221]310            Identifier* operator->() const
[218]311            {
312                return this->identifier_;
313            }
314
[365]315            /**
316                @brief Creates a new object of the type of the assigned identifier and dynamic_casts it to the minimal type given by the SubclassIdentifier.
317                @return The new object
318            */
319            T* fabricate()
[218]320            {
[219]321                BaseObject* newObject = this->identifier_->fabricate();
[365]322
323                // Check if the creation worked
[218]324                if (newObject)
325                {
[365]326                    // Do a dynamic_cast, because an object of type T is much better than of type BaseObject
327                    return dynamic_cast<T*>(newObject);
[218]328                }
329                else
330                {
[365]331                    // Something went terribly wrong
[218]332                    if (this->identifier_)
333                    {
[365]334                        std::cout << "Error: Class " << this->identifier_->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << "!\n";
[218]335                        std::cout << "Error: Couldn't fabricate a new Object.\n";
336                        std::cout << "Aborting...\n";
337                    }
338                    else
339                    {
340                        std::cout << "Error: Couldn't fabricate a new Object - Identifier is undefined.\n";
341                        std::cout << "Aborting...\n";
342                    }
343
344                    abort();
345                }
346            }
347
[365]348            /** @returns the assigned identifier. */
[239]349            inline const Identifier* getIdentifier() const
[197]350                { return this->identifier_; }
[365]351
352            /** @returns true, if the assigned identifier is at least of the given type. @param identifier The identifier to compare with */
[239]353            inline bool isA(const Identifier* identifier) const
[197]354                { return this->identifier_->isA(identifier); }
[365]355
356            /** @returns true, if the assigned identifier is exactly of the given type. @param identifier The identifier to compare with */
[239]357            inline bool isDirectlyA(const Identifier* identifier) const
[197]358                { return this->identifier_->isDirectlyA(identifier); }
[365]359
360            /** @returns true, if the assigned identifier is a child of the given identifier. @param identifier The identifier to compare with */
[239]361            inline bool isChildOf(const Identifier* identifier) const
[197]362                { return this->identifier_->isChildOf(identifier); }
[365]363
364            /** @returns true, if the assigned identifier is a parent of the given identifier. @param identifier The identifier to compare with */
[239]365            inline bool isParentOf(const Identifier* identifier) const
[197]366                { return this->identifier_->isParentOf(identifier); }
367
368        private:
[365]369            Identifier* identifier_;        //!< The assigned identifier
[197]370    };
371}
372
373#endif
Note: See TracBrowser for help on using the repository browser.