Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 544 was 457, checked in by landauf, 17 years ago

changed the class-hierarchy creation: call Factory::createClassHierarchy() to create the hierarchy.
until now it was automatically created at the program-start, but that could have been a problem in the future when classes depend on ogre, because ogre isn't already initialized at that program-start, so i've changed it.

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