Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/FICN/src/orxonox/core/Identifier.h @ 543

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

added files from objecthierarchy, changed includes

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