Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core4/src/core/Identifier.cc @ 3246

Last change on this file since 3246 was 3223, checked in by rgrieder, 15 years ago

Add a new core-feature: orxonox_cast<T>()
The functions casts objects like dynamic_cast, but uses the identifier instead for MSVC (much faster) and is just a redirection to dynamic_cast for GCC.
Also replaced almost all dynamic_casts (of course only those related to the class hierarchy).

  • Property svn:eol-style set to native
File size: 20.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @brief Implementation of the Identifier class.
32*/
33
34#include "Identifier.h"
35
36#include <ostream>
37
38#include "util/String.h"
39#include "ConfigValueContainer.h"
40#include "ConsoleCommand.h"
41#include "Factory.h"
42#include "XMLPort.h"
43
44namespace orxonox
45{
46    // ###############################
47    // ###       Identifier        ###
48    // ###############################
49    int Identifier::hierarchyCreatingCounter_s = 0;
50    unsigned int Identifier::classIDCounter_s = 0;
51
52    /**
53        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
54    */
55    Identifier::Identifier()
56        : classID_(classIDCounter_s++)
57    {
58        this->objects_ = new ObjectListBase(this);
59
60        this->bCreatedOneObject_ = false;
61        this->bSetName_ = false;
62        this->factory_ = 0;
63        this->bLoadable_ = true;
64
65        this->bHasConfigValues_ = false;
66        this->bHasConsoleCommands_ = false;
67
68        this->children_ = new std::set<const Identifier*>();
69        this->directChildren_ = new std::set<const Identifier*>();
70
71        // Default network ID is the class ID
72        this->networkID_ = this->classID_;
73    }
74
75    /**
76        @brief Destructor: Deletes the list containing the children.
77    */
78    Identifier::~Identifier()
79    {
80        delete this->children_;
81        delete this->directChildren_;
82        delete this->objects_;
83
84        if (this->factory_)
85            delete this->factory_;
86
87        for (std::map<std::string, ConsoleCommand*>::iterator it = this->consoleCommands_.begin(); it != this->consoleCommands_.end(); ++it)
88            delete (it->second);
89        for (std::map<std::string, ConfigValueContainer*>::iterator it = this->configValues_.begin(); it != this->configValues_.end(); ++it)
90            delete (it->second);
91        for (std::map<std::string, XMLPortParamContainer*>::iterator it = this->xmlportParamContainers_.begin(); it != this->xmlportParamContainers_.end(); ++it)
92            delete (it->second);
93        for (std::map<std::string, XMLPortObjectContainer*>::iterator it = this->xmlportObjectContainers_.begin(); it != this->xmlportObjectContainers_.end(); ++it)
94            delete (it->second);
95    }
96
97    /**
98        @brief Returns the identifier map with the names as received by typeid(). This is only used internally.
99    */
100    std::map<std::string, Identifier*>& Identifier::getTypeIDIdentifierMap()
101    {
102        static std::map<std::string, Identifier*> identifiers;    //!< The map to store all Identifiers.
103        return identifiers;
104    }
105
106    /**
107        @brief Returns an identifier by name and adds it if not available
108        @param name The name of the identifier as typeid().name() suggests
109        @param proposal A pointer to a newly created identifier for the case of non existance in the map
110        @return The identifier (unique instance)
111    */
112    Identifier* Identifier::getIdentifierSingleton(const std::string& name, Identifier* proposal)
113    {
114        std::map<std::string, Identifier*>::const_iterator it = getTypeIDIdentifierMap().find(name);
115
116        if (it != getTypeIDIdentifierMap().end())
117        {
118            // There is already an entry: return it and delete the proposal
119            delete proposal;
120            return (*it).second;
121        }
122        else
123        {
124            // There is no entry: put the proposal into the map and return it
125            getTypeIDIdentifierMap()[name] = proposal;
126            return proposal;
127        }
128    }
129
130    /**
131        @brief Registers a class, which means that the name and the parents get stored.
132        @param parents A list, containing the Identifiers of all parents of the class
133        @param bRootClass True if the class is either an Interface or the BaseObject itself
134    */
135    void Identifier::initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass)
136    {
137        // Check if at least one object of the given type was created
138        if (!this->bCreatedOneObject_ && Identifier::isCreatingHierarchy())
139        {
140            // If no: We have to store the informations and initialize the Identifier
141            COUT(4) << "*** ClassIdentifier: Register Class in " << this->getName() << "-Singleton -> Initialize Singleton." << std::endl;
142            if (bRootClass)
143                this->initialize(0); // 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.
144            else
145                this->initialize(parents);
146        }
147    }
148
149    /**
150        @brief Initializes the Identifier with a list containing all parents of the class the Identifier belongs to.
151        @param parents A list containing all parents
152    */
153    void Identifier::initialize(std::set<const Identifier*>* parents)
154    {
155        COUT(4) << "*** Identifier: Initialize " << this->name_ << "-Singleton." << std::endl;
156        this->bCreatedOneObject_ = true;
157
158        if (parents)
159        {
160            this->parents_ = (*parents);
161            this->directParents_ = (*parents);
162
163            // Iterate through all parents
164            for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
165            {
166                // Tell the parent we're one of it's children
167                (*it)->getChildrenIntern().insert((*it)->getChildrenIntern().end(), this);
168
169                // Erase all parents of our parent from our direct-parent-list
170                for (std::set<const Identifier*>::const_iterator it1 = (*it)->getParents().begin(); it1 != (*it)->getParents().end(); ++it1)
171                {
172                    // Search for the parent's parent in our direct-parent-list
173                    for (std::set<const Identifier*>::iterator it2 = this->directParents_.begin(); it2 != this->directParents_.end(); ++it2)
174                    {
175                        if ((*it1) == (*it2))
176                        {
177                            // We've found a non-direct parent in our list: Erase it
178                            this->directParents_.erase(it2);
179                            break;
180                        }
181                    }
182                }
183            }
184
185            // Now iterate through all direct parents
186            for (std::set<const Identifier*>::iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
187            {
188                // Tell the parent we're one of it's direct children
189                (*it)->getDirectChildrenIntern().insert((*it)->getDirectChildrenIntern().end(), this);
190
191                // Create the super-function dependencies
192                (*it)->createSuperFunctionCaller();
193            }
194        }
195    }
196
197    /**
198        @brief Destroys all Identifiers. Called when exiting the program.
199    */
200    void Identifier::destroyAllIdentifiers()
201    {
202        for (std::map<std::string, Identifier*>::iterator it = Identifier::getTypeIDIdentifierMap().begin(); it != Identifier::getTypeIDIdentifierMap().end(); ++it)
203            delete (it->second);
204    }
205
206    /**
207        @brief Sets the name of the class.
208        @param name The name
209    */
210    void Identifier::setName(const std::string& name)
211    {
212        if (!this->bSetName_)
213        {
214            this->name_ = name;
215            this->bSetName_ = true;
216            Identifier::getIdentifierMapIntern()[name] = this;
217            Identifier::getLowercaseIdentifierMapIntern()[getLowercase(name)] = this;
218        }
219    }
220
221    /**
222        @brief Creates an object of the type the Identifier belongs to.
223        @return The new object
224    */
225    BaseObject* Identifier::fabricate(BaseObject* creator)
226    {
227        if (this->factory_)
228        {
229            return this->factory_->fabricate(creator); // We have to return a BaseObject, because we don't know the exact type.
230        }
231        else
232        {
233            COUT(1) << "An error occurred in Identifier.cc:" << std::endl;
234            COUT(1) << "Error: Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << std::endl;
235            COUT(1) << "Aborting..." << std::endl;
236            abort();
237            return NULL;
238        }
239    }
240
241    /**
242        @brief Sets the network ID to a new value and changes the entry in the Factory.
243        @param id The new network ID
244    */
245    void Identifier::setNetworkID(uint32_t id)
246    {
247        Factory::changeNetworkID(this, this->networkID_, id);
248        this->networkID_ = id;
249    }
250
251    /**
252        @brief Returns true, if the Identifier is at least of the given type.
253        @param identifier The identifier to compare with
254    */
255    bool Identifier::isA(const Identifier* identifier) const
256    {
257        return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
258    }
259
260    /**
261        @brief Returns true, if the Identifier is exactly of the given type.
262        @param identifier The identifier to compare with
263    */
264    bool Identifier::isExactlyA(const Identifier* identifier) const
265    {
266        return (identifier == this);
267    }
268
269    /**
270        @brief Returns true, if the assigned identifier is a child of the given identifier.
271        @param identifier The identifier to compare with
272    */
273    bool Identifier::isChildOf(const Identifier* identifier) const
274    {
275        return (this->parents_.find(identifier) != this->parents_.end());
276    }
277
278    /**
279        @brief Returns true, if the assigned identifier is a direct child of the given identifier.
280        @param identifier The identifier to compare with
281    */
282    bool Identifier::isDirectChildOf(const Identifier* identifier) const
283    {
284        return (this->directParents_.find(identifier) != this->directParents_.end());
285    }
286
287    /**
288        @brief Returns true, if the assigned identifier is a parent of the given identifier.
289        @param identifier The identifier to compare with
290    */
291    bool Identifier::isParentOf(const Identifier* identifier) const
292    {
293        return (this->children_->find(identifier) != this->children_->end());
294    }
295
296    /**
297        @brief Returns true, if the assigned identifier is a direct parent of the given identifier.
298        @param identifier The identifier to compare with
299    */
300    bool Identifier::isDirectParentOf(const Identifier* identifier) const
301    {
302        return (this->directChildren_->find(identifier) != this->directChildren_->end());
303    }
304
305    /**
306        @brief Returns the map that stores all Identifiers.
307        @return The map
308    */
309    std::map<std::string, Identifier*>& Identifier::getIdentifierMapIntern()
310    {
311        static std::map<std::string, Identifier*> identifierMap;
312        return identifierMap;
313    }
314
315    /**
316        @brief Returns the map that stores all Identifiers.
317        @return The map
318    */
319    std::map<std::string, Identifier*>& Identifier::getLowercaseIdentifierMapIntern()
320    {
321        static std::map<std::string, Identifier*> lowercaseIdentifierMap;
322        return lowercaseIdentifierMap;
323    }
324
325    /**
326        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
327        @param varname The name of the variablee
328        @param container The container
329    */
330    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
331    {
332        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
333        if (it != this->configValues_.end())
334        {
335            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << "." << std::endl;
336            delete (it->second);
337        }
338
339        this->bHasConfigValues_ = true;
340        this->configValues_[varname] = container;
341        this->configValues_LC_[getLowercase(varname)] = container;
342    }
343
344    /**
345        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
346        @param varname The name of the variable
347        @return The ConfigValueContainer
348    */
349    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
350    {
351        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
352        if (it != configValues_.end())
353            return ((*it).second);
354        else
355            return 0;
356    }
357
358    /**
359        @brief Returns the ConfigValueContainer of a variable, given by the string of its name in lowercase.
360        @param varname The name of the variable in lowercase
361        @return The ConfigValueContainer
362    */
363    ConfigValueContainer* Identifier::getLowercaseConfigValueContainer(const std::string& varname)
364    {
365        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_LC_.find(varname);
366        if (it != configValues_LC_.end())
367            return ((*it).second);
368        else
369            return 0;
370    }
371
372    /**
373        @brief Adds a new console command of this class.
374        @param executor The executor of the command
375        @param bCreateShortcut If this is true a shortcut gets created so you don't have to add the classname to access this command
376        @return The executor of the command
377    */
378    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
379    {
380        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
381        if (it != this->consoleCommands_.end())
382        {
383            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << "." << std::endl;
384            delete (it->second);
385        }
386
387        this->bHasConsoleCommands_ = true;
388        this->consoleCommands_[command->getName()] = command;
389        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
390
391        if (bCreateShortcut)
392            CommandExecutor::addConsoleCommandShortcut(command);
393
394        return (*command);
395    }
396
397    /**
398        @brief Returns the executor of a console command with given name.
399        @brief name The name of the requested console command
400        @return The executor of the requested console command
401    */
402    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
403    {
404        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
405        if (it != this->consoleCommands_.end())
406            return (*it).second;
407        else
408            return 0;
409    }
410
411    /**
412        @brief Returns the executor of a console command with given name in lowercase.
413        @brief name The name of the requested console command in lowercae
414        @return The executor of the requested console command
415    */
416    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
417    {
418        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
419        if (it != this->consoleCommands_LC_.end())
420            return (*it).second;
421        else
422            return 0;
423    }
424
425    /**
426        @brief Returns a XMLPortParamContainer that loads a parameter of this class.
427        @param paramname The name of the parameter
428        @return The container
429    */
430    XMLPortParamContainer* Identifier::getXMLPortParamContainer(const std::string& paramname)
431    {
432        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
433        if (it != this->xmlportParamContainers_.end())
434            return ((*it).second);
435        else
436            return 0;
437    }
438
439    /**
440        @brief Adds a new XMLPortParamContainer that loads a parameter of this class.
441        @param paramname The name of the parameter
442        @param container The container
443    */
444    void Identifier::addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container)
445    {
446        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
447        if (it != this->xmlportParamContainers_.end())
448        {
449            COUT(2) << "Warning: Overwriting XMLPortParamContainer in class " << this->getName() << "." << std::endl;
450            delete (it->second);
451        }
452
453        this->xmlportParamContainers_[paramname] = container;
454    }
455
456    /**
457        @brief Returns a XMLPortObjectContainer that attaches an object to this class.
458        @param sectionname The name of the section that contains the attachable objects
459        @return The container
460    */
461    XMLPortObjectContainer* Identifier::getXMLPortObjectContainer(const std::string& sectionname)
462    {
463        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
464        if (it != this->xmlportObjectContainers_.end())
465            return ((*it).second);
466        else
467            return 0;
468    }
469
470    /**
471        @brief Adds a new XMLPortObjectContainer that attaches an object to this class.
472        @param sectionname The name of the section that contains the attachable objects
473        @param container The container
474    */
475    void Identifier::addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container)
476    {
477        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
478        if (it != this->xmlportObjectContainers_.end())
479        {
480            COUT(2) << "Warning: Overwriting XMLPortObjectContainer in class " << this->getName() << "." << std::endl;
481            delete (it->second);
482        }
483
484        this->xmlportObjectContainers_[sectionname] = container;
485    }
486
487    /**
488        @brief Returns a XMLPortEventContainer that attaches an event to this class.
489        @param sectionname The name of the section that contains the event
490        @return The container
491    */
492    XMLPortObjectContainer* Identifier::getXMLPortEventContainer(const std::string& eventname)
493    {
494        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportEventContainers_.find(eventname);
495        if (it != this->xmlportEventContainers_.end())
496            return ((*it).second);
497        else
498            return 0;
499    }
500
501    /**
502        @brief Adds a new XMLPortEventContainer that attaches an event to this class.
503        @param sectionname The name of the section that contains the event
504        @param container The container
505    */
506    void Identifier::addXMLPortEventContainer(const std::string& eventname, XMLPortObjectContainer* container)
507    {
508        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportEventContainers_.find(eventname);
509        if (it != this->xmlportEventContainers_.end())
510        {
511            COUT(2) << "Warning: Overwriting XMLPortEventContainer in class " << this->getName() << "." << std::endl;
512            delete (it->second);
513        }
514
515        this->xmlportEventContainers_[eventname] = container;
516    }
517
518    /**
519        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
520        @param out The outstream
521        @param list The list (or set) of Identifiers
522        @return The outstream
523    */
524    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
525    {
526        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
527            out << (*it)->getName() << " ";
528
529        return out;
530    }
531}
Note: See TracBrowser for help on using the repository browser.