Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2171 was 2171, checked in by landauf, 15 years ago

merged revisions 2111-2170 from objecthierarchy branch back to trunk.

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