Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/Identifier.cc @ 2747

Last change on this file since 2747 was 2662, checked in by rgrieder, 16 years ago

Merged presentation branch back to trunk.

  • Property svn:eol-style set to native
File size: 21.6 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 "Factory.h"
39#include "ConfigValueContainer.h"
40#include "ConsoleCommand.h"
41#include "CommandExecutor.h"
42#include "XMLPort.h"
43
44namespace orxonox
45{
46    // ###############################
47    // ###       Identifier        ###
48    // ###############################
49    int Identifier::hierarchyCreatingCounter_s = 0; // Set the static member variable hierarchyCreatingCounter_s to zero (this static member variable is ok: it's used in main(), not before)
50
51    /**
52        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
53    */
54    Identifier::Identifier()
55    {
56        this->objects_ = new ObjectListBase(this);
57
58        this->bCreatedOneObject_ = false;
59        this->bSetName_ = false;
60        this->factory_ = 0;
61        this->bLoadable_ = true;
62
63        this->bHasConfigValues_ = false;
64        this->bHasConsoleCommands_ = false;
65        this->bHasConstructionCallback_ = false;
66
67        this->children_ = new std::set<const Identifier*>();
68        this->directChildren_ = new std::set<const Identifier*>();
69
70        // Use a static variable because the classID gets created before main() and that's why we should avoid static member variables
71        static unsigned int classIDcounter_s = 0;
72        this->classID_ = classIDcounter_s++;
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        for (std::vector<Functor*>::iterator it = this->constructionCallbacks_.begin(); it != this->constructionCallbacks_.end(); ++it)
96            delete *it;
97    }
98
99    /**
100        @brief Returns the identifier map with the names as received by typeid(). This is only used internally.
101    */
102    std::map<std::string, Identifier*>& Identifier::getTypeIDIdentifierMap()
103    {
104        static std::map<std::string, Identifier*> identifiers;    //!< The map to store all Identifiers.
105        return identifiers;
106    }
107
108    /**
109        @brief Returns an identifier by name and adds it if not available
110        @param name The name of the identifier as typeid().name() suggests
111        @param proposal A pointer to a newly created identifier for the case of non existance in the map
112        @return The identifier (unique instance)
113    */
114    Identifier* Identifier::getIdentifierSingleton(const std::string& name, Identifier* proposal)
115    {
116        std::map<std::string, Identifier*>::const_iterator it = getTypeIDIdentifierMap().find(name);
117
118        if (it != getTypeIDIdentifierMap().end())
119        {
120            // There is already an entry: return it and delete the proposal
121            delete proposal;
122            return (*it).second;
123        }
124        else
125        {
126            // There is no entry: put the proposal into the map and return it
127            getTypeIDIdentifierMap()[name] = proposal;
128            return proposal;
129        }
130    }
131
132    /**
133        @brief Registers a class, which means that the name and the parents get stored.
134        @param parents A list, containing the Identifiers of all parents of the class
135        @param bRootClass True if the class is either an Interface or the BaseObject itself
136    */
137    void Identifier::initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass)
138    {
139        // Check if at least one object of the given type was created
140        if (!this->bCreatedOneObject_ && Identifier::isCreatingHierarchy())
141        {
142            // If no: We have to store the informations and initialize the Identifier
143            COUT(4) << "*** ClassIdentifier: Register Class in " << this->getName() << "-Singleton -> Initialize Singleton." << std::endl;
144            if (bRootClass)
145                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.
146            else
147                this->initialize(parents);
148        }
149    }
150
151    /**
152        @brief Initializes the Identifier with a list containing all parents of the class the Identifier belongs to.
153        @param parents A list containing all parents
154    */
155    void Identifier::initialize(std::set<const Identifier*>* parents)
156    {
157        COUT(4) << "*** Identifier: Initialize " << this->name_ << "-Singleton." << std::endl;
158        this->bCreatedOneObject_ = true;
159
160        if (parents)
161        {
162            this->parents_ = (*parents);
163            this->directParents_ = (*parents);
164
165            // Iterate through all parents
166            for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
167            {
168                // Tell the parent we're one of it's children
169                (*it)->getChildrenIntern().insert((*it)->getChildrenIntern().end(), this);
170
171                // Erase all parents of our parent from our direct-parent-list
172                for (std::set<const Identifier*>::const_iterator it1 = (*it)->getParents().begin(); it1 != (*it)->getParents().end(); ++it1)
173                {
174                    // Search for the parent's parent in our direct-parent-list
175                    for (std::set<const Identifier*>::iterator it2 = this->directParents_.begin(); it2 != this->directParents_.end(); ++it2)
176                    {
177                        if ((*it1) == (*it2))
178                        {
179                            // We've found a non-direct parent in our list: Erase it
180                            this->directParents_.erase(it2);
181                            break;
182                        }
183                    }
184                }
185            }
186
187            // Now iterate through all direct parents
188            for (std::set<const Identifier*>::iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
189            {
190                // Tell the parent we're one of it's direct children
191                (*it)->getDirectChildrenIntern().insert((*it)->getDirectChildrenIntern().end(), this);
192
193                // Create the super-function dependencies
194                (*it)->createSuperFunctionCaller();
195            }
196        }
197    }
198
199    /**
200        @brief Destroys all Identifiers. Called when exiting the program.
201    */
202    void Identifier::destroyAllIdentifiers()
203    {
204        for (std::map<std::string, Identifier*>::iterator it = Identifier::getTypeIDIdentifierMap().begin(); it != Identifier::getTypeIDIdentifierMap().end(); ++it)
205            delete (it->second);
206    }
207
208    /**
209        @brief Sets the name of the class.
210        @param name The name
211    */
212    void Identifier::setName(const std::string& name)
213    {
214        if (!this->bSetName_)
215        {
216            this->name_ = name;
217            this->bSetName_ = true;
218            Identifier::getIdentifierMapIntern()[name] = this;
219            Identifier::getLowercaseIdentifierMapIntern()[getLowercase(name)] = this;
220        }
221    }
222
223    /**
224        @brief Creates an object of the type the Identifier belongs to.
225        @return The new object
226    */
227    BaseObject* Identifier::fabricate(BaseObject* creator)
228    {
229        if (this->factory_)
230        {
231            return this->factory_->fabricate(creator); // We have to return a BaseObject, because we don't know the exact type.
232        }
233        else
234        {
235            COUT(1) << "An error occurred in Identifier.cc:" << std::endl;
236            COUT(1) << "Error: Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << std::endl;
237            COUT(1) << "Aborting..." << std::endl;
238            abort();
239            return NULL;
240        }
241    }
242
243    /**
244        @brief Sets the network ID to a new value and changes the entry in the Factory.
245        @param id The new network ID
246    */
247    void Identifier::setNetworkID(uint32_t id)
248    {
249        Factory::changeNetworkID(this, this->classID_, id);
250        this->classID_ = id;
251    }
252
253    /**
254        @brief Returns true, if the Identifier is at least of the given type.
255        @param identifier The identifier to compare with
256    */
257    bool Identifier::isA(const Identifier* identifier) const
258    {
259        return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
260    }
261
262    /**
263        @brief Returns true, if the Identifier is exactly of the given type.
264        @param identifier The identifier to compare with
265    */
266    bool Identifier::isExactlyA(const Identifier* identifier) const
267    {
268        return (identifier == this);
269    }
270
271    /**
272        @brief Returns true, if the assigned identifier is a child of the given identifier.
273        @param identifier The identifier to compare with
274    */
275    bool Identifier::isChildOf(const Identifier* identifier) const
276    {
277        return (this->parents_.find(identifier) != this->parents_.end());
278    }
279
280    /**
281        @brief Returns true, if the assigned identifier is a direct child of the given identifier.
282        @param identifier The identifier to compare with
283    */
284    bool Identifier::isDirectChildOf(const Identifier* identifier) const
285    {
286        return (this->directParents_.find(identifier) != this->directParents_.end());
287    }
288
289    /**
290        @brief Returns true, if the assigned identifier is a parent of the given identifier.
291        @param identifier The identifier to compare with
292    */
293    bool Identifier::isParentOf(const Identifier* identifier) const
294    {
295        return (this->children_->find(identifier) != this->children_->end());
296    }
297
298    /**
299        @brief Returns true, if the assigned identifier is a direct parent of the given identifier.
300        @param identifier The identifier to compare with
301    */
302    bool Identifier::isDirectParentOf(const Identifier* identifier) const
303    {
304        return (this->directChildren_->find(identifier) != this->directChildren_->end());
305    }
306
307    /**
308        @brief Returns the map that stores all Identifiers.
309        @return The map
310    */
311    std::map<std::string, Identifier*>& Identifier::getIdentifierMapIntern()
312    {
313        static std::map<std::string, Identifier*> identifierMap;
314        return identifierMap;
315    }
316
317    /**
318        @brief Returns the map that stores all Identifiers.
319        @return The map
320    */
321    std::map<std::string, Identifier*>& Identifier::getLowercaseIdentifierMapIntern()
322    {
323        static std::map<std::string, Identifier*> lowercaseIdentifierMap;
324        return lowercaseIdentifierMap;
325    }
326
327    /**
328        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
329        @param varname The name of the variablee
330        @param container The container
331    */
332    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
333    {
334        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
335        if (it != this->configValues_.end())
336        {
337            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << "." << std::endl;
338            delete (it->second);
339        }
340
341        this->bHasConfigValues_ = true;
342        this->configValues_[varname] = container;
343        this->configValues_LC_[getLowercase(varname)] = container;
344    }
345
346    /**
347        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
348        @param varname The name of the variable
349        @return The ConfigValueContainer
350    */
351    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
352    {
353        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
354        if (it != configValues_.end())
355            return ((*it).second);
356        else
357            return 0;
358    }
359
360    /**
361        @brief Returns the ConfigValueContainer of a variable, given by the string of its name in lowercase.
362        @param varname The name of the variable in lowercase
363        @return The ConfigValueContainer
364    */
365    ConfigValueContainer* Identifier::getLowercaseConfigValueContainer(const std::string& varname)
366    {
367        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_LC_.find(varname);
368        if (it != configValues_LC_.end())
369            return ((*it).second);
370        else
371            return 0;
372    }
373
374    /**
375        @brief Adds a new console command of this class.
376        @param executor The executor of the command
377        @param bCreateShortcut If this is true a shortcut gets created so you don't have to add the classname to access this command
378        @return The executor of the command
379    */
380    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
381    {
382        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
383        if (it != this->consoleCommands_.end())
384        {
385            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << "." << std::endl;
386            delete (it->second);
387        }
388
389        this->bHasConsoleCommands_ = true;
390        this->consoleCommands_[command->getName()] = command;
391        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
392
393        if (bCreateShortcut)
394            CommandExecutor::addConsoleCommandShortcut(command);
395
396        return (*command);
397    }
398
399    /**
400        @brief Returns the executor of a console command with given name.
401        @brief name The name of the requested console command
402        @return The executor of the requested console command
403    */
404    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
405    {
406        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
407        if (it != this->consoleCommands_.end())
408            return (*it).second;
409        else
410            return 0;
411    }
412
413    /**
414        @brief Returns the executor of a console command with given name in lowercase.
415        @brief name The name of the requested console command in lowercae
416        @return The executor of the requested console command
417    */
418    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
419    {
420        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
421        if (it != this->consoleCommands_LC_.end())
422            return (*it).second;
423        else
424            return 0;
425    }
426
427    /**
428        @brief Returns a XMLPortParamContainer that loads a parameter of this class.
429        @param paramname The name of the parameter
430        @return The container
431    */
432    XMLPortParamContainer* Identifier::getXMLPortParamContainer(const std::string& paramname)
433    {
434        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
435        if (it != this->xmlportParamContainers_.end())
436            return ((*it).second);
437        else
438            return 0;
439    }
440
441    /**
442        @brief Adds a new XMLPortParamContainer that loads a parameter of this class.
443        @param paramname The name of the parameter
444        @param container The container
445    */
446    void Identifier::addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container)
447    {
448        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
449        if (it != this->xmlportParamContainers_.end())
450        {
451            COUT(2) << "Warning: Overwriting XMLPortParamContainer in class " << this->getName() << "." << std::endl;
452            delete (it->second);
453        }
454
455        this->xmlportParamContainers_[paramname] = container;
456    }
457
458    /**
459        @brief Returns a XMLPortObjectContainer that attaches an object to this class.
460        @param sectionname The name of the section that contains the attachable objects
461        @return The container
462    */
463    XMLPortObjectContainer* Identifier::getXMLPortObjectContainer(const std::string& sectionname)
464    {
465        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
466        if (it != this->xmlportObjectContainers_.end())
467            return ((*it).second);
468        else
469            return 0;
470    }
471
472    /**
473        @brief Adds a new XMLPortObjectContainer that attaches an object to this class.
474        @param sectionname The name of the section that contains the attachable objects
475        @param container The container
476    */
477    void Identifier::addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container)
478    {
479        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
480        if (it != this->xmlportObjectContainers_.end())
481        {
482            COUT(2) << "Warning: Overwriting XMLPortObjectContainer in class " << this->getName() << "." << std::endl;
483            delete (it->second);
484        }
485
486        this->xmlportObjectContainers_[sectionname] = container;
487    }
488
489    /**
490        @brief Returns a XMLPortEventContainer that attaches an event to this class.
491        @param sectionname The name of the section that contains the event
492        @return The container
493    */
494    XMLPortObjectContainer* Identifier::getXMLPortEventContainer(const std::string& eventname)
495    {
496        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportEventContainers_.find(eventname);
497        if (it != this->xmlportEventContainers_.end())
498            return ((*it).second);
499        else
500            return 0;
501    }
502
503    /**
504        @brief Adds a new XMLPortEventContainer that attaches an event to this class.
505        @param sectionname The name of the section that contains the event
506        @param container The container
507    */
508    void Identifier::addXMLPortEventContainer(const std::string& eventname, XMLPortObjectContainer* container)
509    {
510        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportEventContainers_.find(eventname);
511        if (it != this->xmlportEventContainers_.end())
512        {
513            COUT(2) << "Warning: Overwriting XMLPortEventContainer in class " << this->getName() << "." << std::endl;
514            delete (it->second);
515        }
516
517        this->xmlportEventContainers_[eventname] = container;
518    }
519
520    /**
521        @brief Adds a construction callback functor that gets called every time an object is created.
522        @param functor Functor pointer to any function with no argument.
523    */
524    void Identifier::addConstructionCallback(Functor* functor)
525    {
526        for (unsigned int i = 0; i < this->constructionCallbacks_.size(); ++i)
527        {
528            if (this->constructionCallbacks_[i] == functor)
529                return;
530        }
531        this->constructionCallbacks_.push_back(functor);
532        this->bHasConstructionCallback_ = true;
533    }
534
535    /**
536        @brief Removes a construction callback functor that gets called every time an object is created.
537        @param functor Functor pointer to any function with no argument.
538    */
539    void Identifier::removeConstructionCallback(Functor* functor)
540    {
541        for (unsigned int i = 0; i < this->constructionCallbacks_.size(); ++i)
542        {
543            if (this->constructionCallbacks_[i] == functor)
544            {
545                this->constructionCallbacks_.erase(this->constructionCallbacks_.begin() + i);
546            }
547        }
548        if (constructionCallbacks_.empty())
549            this->bHasConstructionCallback_ = false;
550    }
551
552    /**
553        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
554        @param out The outstream
555        @param list The list (or set) of Identifiers
556        @return The outstream
557    */
558    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
559    {
560        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
561            out << (*it)->getName() << " ";
562
563        return out;
564    }
565}
Note: See TracBrowser for help on using the repository browser.