Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/Identifier.cc @ 5967

Last change on this file since 5967 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

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