Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 733 was 732, checked in by nicolasc, 17 years ago
  • added copyrightnotice to spaceshipsteeringobject
  • added OPTION to build networktools
  • minor cleanups
File size: 17.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28/*!
29    @file Identifier.h
30    @brief Definition of the Identifier, ClassIdentifier and SubclassIdentifier classes, implementation of the ClassIdentifier and SubclassIdentifier classes.
31
32    The Identifier contains all needed informations about the class it belongs to:
33     - the name
34     - a list with all objects
35     - parents and childs
36     - the factory (if available)
37     - the networkID that can be synchronised with the server
38     - all configurable variables (if available)
39
40    Every object has a pointer to the Identifier of its class. This allows the use isA(...),
41    isDirectlyA(...), isChildOf(...) and isParentOf(...).
42
43    To create the class-hierarchy, the Identifier has some intern functions and variables.
44
45    Every Identifier is in fact a ClassIdentifier, but they are derived from Identifier.
46
47    SubclassIdentifier is a separated class, acting like an Identifier, but has a given class.
48    You can only assign Identifiers of exactly the given class or of a derivative to a SubclassIdentifier.
49*/
50
51#ifndef _Identifier_H__
52#define _Identifier_H__
53
54#include <map>
55#include <string>
56#include <utility>
57
58#include "CorePrereqs.h"
59
60#include "ObjectList.h"
61#include "IdentifierList.h"
62#include "Factory.h"
63#include "Debug.h"
64// These two files would actually be need, but they would produce
65// circular dependencies. Anyway, it does compile without them
66// #include "OrxonoxClass.h"
67// #include "MetaObjectList.h"
68
69namespace orxonox
70{
71    class BaseObject; // Forward declaration
72
73    // ###############################
74    // ###       Identifier        ###
75    // ###############################
76    //! The Identifier is used to identify the class of an object and to store informations about the class.
77    /**
78        The Identifier contains all needed informations about the class it belongs to:
79         - the name
80         - a list with all objects
81         - parents and childs
82         - the factory (if available)
83         - the networkID that can be synchronised with the server
84         - all configurable variables (if available)
85
86        Every object has a pointer to the Identifier of its class. This allows the use isA(...),
87        isDirectlyA(...), isChildOf(...) and isParentOf(...).
88
89        You can't directly create an Identifier, it's just the base-class for ClassIdentifier.
90    */
91    class _CoreExport Identifier
92    {
93        template <class T>
94        friend class ClassIdentifier; // Forward declaration
95
96        template <class T>
97        friend class SubclassIdentifier; // Forward declaration
98
99        friend class Factory; // Forward declaration
100
101        public:
102            /** @brief Sets the Factory.
103             *  @param factory The factory to assign
104             */
105            inline void addFactory(BaseFactory* factory) { this->factory_ = factory; }
106
107            BaseObject* fabricate();
108
109            bool isA(const Identifier* identifier) const;
110            bool isDirectlyA(const Identifier* identifier) const;
111            bool isChildOf(const Identifier* identifier) const;
112            bool isParentOf(const Identifier* identifier) const;
113
114            /** @returns the name of the class the Identifier belongs to. */
115            inline const std::string& getName() const { return this->name_; }
116
117            /** @returns the parents of the class the Identifier belongs to. */
118            inline const IdentifierList& getParents() const { return this->parents_; }
119
120            /** @returns the children of the class the Identifier belongs to. */
121            inline IdentifierList& getChildren() const { return *this->children_; }
122
123            /** @returns true, if a branch of the class-hierarchy is being created, causing all new objects to store their parents. */
124            inline static bool isCreatingHierarchy() { return (hierarchyCreatingCounter_s > 0); }
125
126            /** @returns the network ID to identify a class through the network. */
127            inline const unsigned int getNetworkID() const { return this->classID_; }
128
129            /** @brief Sets the network ID to a new value. @param id The new value */
130            void setNetworkID(unsigned int id);
131
132            /** @returns the ConfigValueContainer of a variable, given by the string of its name. @param varname The name of the variable */
133            inline ConfigValueContainer* getConfigValueContainer(const std::string& varname)
134                { return this->configValues_[varname]; }
135
136            /** @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 */
137            inline void setConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
138                { this->configValues_[varname] = container; }
139
140            static std::map<std::string, Identifier*>& getIdentifierMap();
141
142        private:
143            Identifier();
144            Identifier(const Identifier& identifier) {} // don't copy
145            virtual ~Identifier();
146            void initialize(const IdentifierList* parents);
147
148            /**
149                @brief Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents.
150            */
151            inline static void startCreatingHierarchy()
152            {
153                hierarchyCreatingCounter_s++;
154                COUT(4) << "*** Increased Hierarchy-Creating-Counter to " << hierarchyCreatingCounter_s << std::endl;
155            }
156
157            /**
158                @brief Decreases the hierarchyCreatingCounter_s variable, causing the objects to stop storing their parents.
159            */
160            inline static void stopCreatingHierarchy()
161            {
162                hierarchyCreatingCounter_s--;
163                COUT(4) << "*** Decreased Hierarchy-Creating-Counter to " << hierarchyCreatingCounter_s << std::endl;
164            }
165
166            IdentifierList parents_;                                    //!< The Parents of the class the Identifier belongs to
167            IdentifierList* children_;                                  //!< The Children of the class the Identifier belongs to
168
169            std::string name_;                                          //!< The name of the class the Identifier belongs to
170
171            BaseFactory* factory_;                                      //!< The Factory, able to create new objects of the given class (if available)
172            bool bCreatedOneObject_;                                    //!< True if at least one object of the given type was created (used to determine the need of storing the parents)
173            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)
174            unsigned int classID_;                                      //!< The network ID to identify a class through the network
175            std::map<std::string, ConfigValueContainer*> configValues_; //!< A map to link the string of configurable variables with their ConfigValueContainer
176    };
177
178
179    // ###############################
180    // ###     ClassIdentifier     ###
181    // ###############################
182    //! The ClassIdentifier is derived from Identifier and holds all class-specific functions and variables the Identifier cannot have.
183    /**
184        ClassIdentifier is a Singleton, which means that only one object of a given type T exists.
185        This makes it possible to store informations about a class, sharing them with all
186        objects of that class without defining static variables in every class.
187    */
188    template <class T>
189    class ClassIdentifier : public Identifier
190    {
191        public:
192            static ClassIdentifier<T>* registerClass(const IdentifierList* parents, const std::string& name, bool bRootClass);
193            static void addObject(T* object);
194            static ClassIdentifier<T>* getIdentifier();
195            void setName(const std::string& name);
196
197        private:
198            ClassIdentifier();
199            ClassIdentifier(const ClassIdentifier<T>& identifier) {}    // don't copy
200            ~ClassIdentifier() {}                                       // don't delete
201
202            ObjectList<T>* objects_;    //!< The ObjectList, containing all objects of type T
203            bool bSetName_;             //!< True if the name is set
204    };
205
206    /**
207        @brief Constructor: Creates the ObjectList.
208    */
209    template <class T>
210    ClassIdentifier<T>::ClassIdentifier()
211    {
212        this->objects_ = ObjectList<T>::getList();
213        this->bSetName_ = false;
214    }
215
216    /**
217        @brief Registers a class, which means that the name and the parents get stored.
218        @param parents An IdentifierList, containing the Identifiers of all parents of the class
219        @param name A string, containing exactly the name of the class
220        @param bRootClass True if the class is either an Interface or the BaseObject itself
221        @return The ClassIdentifier itself
222    */
223    template <class T>
224    ClassIdentifier<T>* ClassIdentifier<T>::registerClass(const IdentifierList* parents, const std::string& name, bool bRootClass)
225    {
226        COUT(4) << "*** Register Class in " << name << "-Singleton." << std::endl;
227
228        // Check if at least one object of the given type was created
229        if (!getIdentifier()->bCreatedOneObject_)
230        {
231            // If no: We have to store the informations and initialize the Identifier
232            getIdentifier()->setName(name);
233
234            COUT(4) << "*** Register Class in " << name << "-Singleton -> Initialize Singleton." << std::endl;
235            if (bRootClass)
236                getIdentifier()->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.
237            else
238                getIdentifier()->initialize(parents);
239        }
240
241        return getIdentifier();
242    }
243
244    /**
245        @brief Creates the only instance of this class for the template class T.
246        @return The Identifier itself
247    */
248    template <class T>
249    ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
250    {
251        static ClassIdentifier<T> theOneAndOnlyInstance = ClassIdentifier<T>();
252        static bool bIdentifierCreated = false;
253
254        if (!bIdentifierCreated)
255        {
256            COUT(4) << "*** Create Identifier Singleton." << std::endl;
257            bIdentifierCreated = true;
258        }
259
260        return &theOneAndOnlyInstance;
261    }
262
263    /**
264        @brief Sets the name of the class.
265        @param name The name
266    */
267    template <class T>
268    void ClassIdentifier<T>::setName(const std::string& name)
269    {
270        // Make sure we didn't already set the name, to avoid duplicate entries in the Identifier map
271        if (!this->bSetName_)
272        {
273            this->name_ = name;
274            this->getIdentifierMap().insert(std::pair<std::string, Identifier*>(name, this));
275            this->bSetName_ = true;
276        }
277    }
278
279    /**
280        @brief Adds an object of the given type to the ObjectList.
281        @param object The object to add
282    */
283    template <class T>
284    void ClassIdentifier<T>::addObject(T* object)
285    {
286        COUT(4) << "*** Added object to " << ClassIdentifier<T>::getIdentifier()->getName() << "-list." << std::endl;
287        object->getMetaList().add(ClassIdentifier<T>::getIdentifier()->objects_, ClassIdentifier<T>::getIdentifier()->objects_->add(object));
288    }
289
290
291    // ###############################
292    // ###   SubclassIdentifier    ###
293    // ###############################
294    //! The SubclassIdentifier acts almost like an Identifier, but has some prerequisites.
295    /**
296        You can only assign an Identifier that belongs to a class T (or derived) to a SubclassIdentifier<T>.
297        If you assign something else, the program aborts.
298        Because we know the minimal type, a dynamic_cast is done, which makes it easier to create a new object.
299    */
300    template <class T>
301    class SubclassIdentifier
302    {
303        public:
304            /**
305                @brief Constructor: Automaticaly assigns the Identifier of the given class.
306            */
307            SubclassIdentifier()
308            {
309                this->identifier_ = ClassIdentifier<T>::getIdentifier();
310            }
311
312            /**
313                @brief Overloading of the = operator: assigns the identifier and checks its type.
314                @param identifier The Identifier to assign
315                @return The SubclassIdentifier itself
316            */
317            SubclassIdentifier<T>& operator=(Identifier* identifier)
318            {
319                if (!identifier->isA(ClassIdentifier<T>::getIdentifier()))
320                {
321                    COUT(1) << "Error: Class " << identifier->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << "!" << std::endl;
322                    COUT(1) << "Error: SubclassIdentifier<" << ClassIdentifier<T>::getIdentifier()->getName() << "> = Class(" << identifier->getName() << ") is forbidden." << std::endl;
323                    COUT(1) << "Aborting..." << std::endl;
324                    abort();
325                }
326                this->identifier_ = identifier;
327                return *this;
328            }
329
330            /**
331                @brief Overloading of the * operator: returns the assigned identifier.
332                @return The assigned identifier
333            */
334            Identifier* operator*()
335            {
336                return this->identifier_;
337            }
338
339            /**
340                @brief Overloading of the -> operator: returns the assigned identifier.
341                @return The assigned identifier
342            */
343            Identifier* operator->() const
344            {
345                return this->identifier_;
346            }
347
348            /**
349                @brief Creates a new object of the type of the assigned Identifier and dynamic_casts it to the minimal type given by T.
350                @return The new object
351            */
352            T* fabricate()
353            {
354                BaseObject* newObject = this->identifier_->fabricate();
355
356                // Check if the creation was successful
357                if (newObject)
358                {
359                    // Do a dynamic_cast, because an object of type T is much better than of type BaseObject
360                    return (T*)(newObject);
361                }
362                else
363                {
364                    // Something went terribly wrong
365                    if (this->identifier_)
366                    {
367                        COUT(1) << "Error: Class " << this->identifier_->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << "!" << std::endl;
368                        COUT(1) << "Error: Couldn't fabricate a new Object." << std::endl;
369                        COUT(1) << "Aborting..." << std::endl;
370                    }
371                    else
372                    {
373                        COUT(1) << "Error: Couldn't fabricate a new Object - Identifier is undefined." << std::endl;
374                        COUT(1) << "Aborting..." << std::endl;
375                    }
376
377                    abort();
378                }
379            }
380
381            /** @returns the assigned identifier. */
382            inline const Identifier* getIdentifier() const
383                { return this->identifier_; }
384
385            /** @returns true, if the assigned identifier is at least of the given type. @param identifier The identifier to compare with */
386            inline bool isA(const Identifier* identifier) const
387                { return this->identifier_->isA(identifier); }
388
389            /** @returns true, if the assigned identifier is exactly of the given type. @param identifier The identifier to compare with */
390            inline bool isDirectlyA(const Identifier* identifier) const
391                { return this->identifier_->isDirectlyA(identifier); }
392
393            /** @returns true, if the assigned identifier is a child of the given identifier. @param identifier The identifier to compare with */
394            inline bool isChildOf(const Identifier* identifier) const
395                { return this->identifier_->isChildOf(identifier); }
396
397            /** @returns true, if the assigned identifier is a parent of the given identifier. @param identifier The identifier to compare with */
398            inline bool isParentOf(const Identifier* identifier) const
399                { return this->identifier_->isParentOf(identifier); }
400
401        private:
402            Identifier* identifier_;        //!< The assigned identifier
403    };
404}
405
406#endif /* _Identifier_H__ */
Note: See TracBrowser for help on using the repository browser.