Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp6/src/core/Identifier.cc @ 5645

Last change on this file since 5645 was 3196, checked in by rgrieder, 15 years ago

Merged pch branch back to trunk.

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