Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 598 was 592, checked in by nicolasc, 17 years ago

added engineglow particle effect - based of treibwerk
other various changes

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