Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/core/Identifier.cc @ 2440

Last change on this file since 2440 was 2309, checked in by scheusso, 16 years ago

made some adjustments mostly to the networkid (classid) in order to have it platform independent

  • 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(uint32_t 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.