Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/libraries/core/Identifier.cc @ 5778

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

Removed the Factory class.
Moved the networkID↔Identifier map from Factory to Identifier.
Replaced the name↔Identifier map from Factory with the already existing Identifier map in Identifier. This map additionally contains Identifiers without Factory. You can separate them with the new function identifier→hasFactory().

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