Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Renamed BaseFactory as Factory
Added function ClassByLowercaseString

  • Property svn:eol-style set to native
File size: 23.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/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_ = true;
64
65        this->bHasConfigValues_ = false;
66        this->bHasConsoleCommands_ = false;
67
68        this->children_ = new std::set<const Identifier*>();
69        this->directChildren_ = new std::set<const Identifier*>();
70
71        // Default network ID is the class ID
72        this->networkID_ = this->classID_;
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 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    /**
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    */
112    Identifier* Identifier::getIdentifierSingleton(const std::string& name, Identifier* proposal)
113    {
114        std::map<std::string, Identifier*>::const_iterator it = getTypeIDIdentifierMap().find(name);
115
116        if (it != getTypeIDIdentifierMap().end())
117        {
118            // There is already an entry: return it and delete the proposal
119            delete proposal;
120            return (*it).second;
121        }
122        else
123        {
124            // There is no entry: put the proposal into the map and return it
125            getTypeIDIdentifierMap()[name] = proposal;
126            return proposal;
127        }
128    }
129
130    /**
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        {
140            // If no: We have to store the information and initialize the Identifier
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    /**
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
152    */
153    void Identifier::initialize(std::set<const Identifier*>* parents)
154    {
155        COUT(4) << "*** Identifier: Initialize " << this->name_ << "-Singleton." << std::endl;
156        this->bCreatedOneObject_ = true;
157
158        if (parents)
159        {
160            this->parents_ = (*parents);
161            this->directParents_ = (*parents);
162
163            // Iterate through all parents
164            for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
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                }
183            }
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);
190
191                // Create the super-function dependencies
192                (*it)->createSuperFunctionCaller();
193            }
194        }
195    }
196
197    /**
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    /**
220        @brief Destroys all Identifiers. Called when exiting the program.
221    */
222    void Identifier::destroyAllIdentifiers()
223    {
224        for (std::map<std::string, Identifier*>::iterator it = Identifier::getTypeIDIdentifierMap().begin(); it != Identifier::getTypeIDIdentifierMap().end(); ++it)
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;
238            Identifier::getStringIdentifierMapIntern()[name] = this;
239            Identifier::getLowercaseStringIdentifierMapIntern()[getLowercase(name)] = this;
240            Identifier::getIDIdentifierMapIntern()[this->networkID_] = this;
241        }
242    }
243
244    /**
245        @brief Creates an object of the type the Identifier belongs to.
246        @return The new object
247    */
248    BaseObject* Identifier::fabricate(BaseObject* creator)
249    {
250        if (this->factory_)
251        {
252            return this->factory_->fabricate(creator); // We have to return a BaseObject, because we don't know the exact type.
253        }
254        else
255        {
256            COUT(1) << "An error occurred in Identifier.cc:" << std::endl;
257            COUT(1) << "Error: Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << std::endl;
258            COUT(1) << "Aborting..." << std::endl;
259            abort();
260            return 0;
261        }
262    }
263
264    /**
265        @brief Sets the network ID to a new value and changes the entry in the ID-Identifier-map.
266        @param id The new network ID
267    */
268    void Identifier::setNetworkID(uint32_t id)
269    {
270//        Identifier::getIDIdentifierMapIntern().erase(this->networkID_);
271        Identifier::getIDIdentifierMapIntern()[id] = this;
272        this->networkID_ = id;
273    }
274
275    /**
276        @brief Returns true, if the Identifier is at least of the given type.
277        @param identifier The identifier to compare with
278    */
279    bool Identifier::isA(const Identifier* identifier) const
280    {
281        return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
282    }
283
284    /**
285        @brief Returns true, if the Identifier is exactly of the given type.
286        @param identifier The identifier to compare with
287    */
288    bool Identifier::isExactlyA(const Identifier* identifier) const
289    {
290        return (identifier == this);
291    }
292
293    /**
294        @brief Returns true, if the assigned identifier is a child of the given identifier.
295        @param identifier The identifier to compare with
296    */
297    bool Identifier::isChildOf(const Identifier* identifier) const
298    {
299        return (this->parents_.find(identifier) != this->parents_.end());
300    }
301
302    /**
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    /**
312        @brief Returns true, if the assigned identifier is a parent of the given identifier.
313        @param identifier The identifier to compare with
314    */
315    bool Identifier::isParentOf(const Identifier* identifier) const
316    {
317        return (this->children_->find(identifier) != this->children_->end());
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    /**
330        @brief Returns the map that stores all Identifiers with their names.
331        @return The map
332    */
333    std::map<std::string, Identifier*>& Identifier::getStringIdentifierMapIntern()
334    {
335        static std::map<std::string, Identifier*> identifierMap;
336        return identifierMap;
337    }
338
339    /**
340        @brief Returns the map that stores all Identifiers with their names in lowercase.
341        @return The map
342    */
343    std::map<std::string, Identifier*>& Identifier::getLowercaseStringIdentifierMapIntern()
344    {
345        static std::map<std::string, Identifier*> lowercaseIdentifierMap;
346        return lowercaseIdentifierMap;
347    }
348
349    /**
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 name in lowercase.
375        @param name The name of the wanted Identifier
376        @return The Identifier
377    */
378    Identifier* Identifier::getIdentifierByLowercaseString(const std::string& name)
379    {
380        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseStringIdentifierMapIntern().find(name);
381        if (it != Identifier::getLowercaseStringIdentifierMapIntern().end())
382            return it->second;
383        else
384            return 0;
385    }
386
387    /**
388        @brief Returns the Identifier with a given network ID.
389        @param id The network ID of the wanted Identifier
390        @return The Identifier
391    */
392    Identifier* Identifier::getIdentifierByID(const uint32_t id)
393    {
394        std::map<uint32_t, Identifier*>::const_iterator it = Identifier::getIDIdentifierMapIntern().find(id);
395        if (it != Identifier::getIDIdentifierMapIntern().end())
396            return it->second;
397        else
398            return 0;
399    }
400
401    /**
402        @brief Cleans the NetworkID map (needed on clients for correct initialization)
403    */
404    void Identifier::clearNetworkIDs()
405    {
406        Identifier::getIDIdentifierMapIntern().clear();
407    }
408
409    /**
410        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
411        @param varname The name of the variablee
412        @param container The container
413    */
414    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
415    {
416        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
417        if (it != this->configValues_.end())
418        {
419            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << "." << std::endl;
420            delete (it->second);
421        }
422
423        this->bHasConfigValues_ = true;
424        this->configValues_[varname] = container;
425        this->configValues_LC_[getLowercase(varname)] = container;
426    }
427
428    /**
429        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
430        @param varname The name of the variable
431        @return The ConfigValueContainer
432    */
433    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
434    {
435        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
436        if (it != configValues_.end())
437            return ((*it).second);
438        else
439            return 0;
440    }
441
442    /**
443        @brief Returns the ConfigValueContainer of a variable, given by the string of its name in lowercase.
444        @param varname The name of the variable in lowercase
445        @return The ConfigValueContainer
446    */
447    ConfigValueContainer* Identifier::getLowercaseConfigValueContainer(const std::string& varname)
448    {
449        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_LC_.find(varname);
450        if (it != configValues_LC_.end())
451            return ((*it).second);
452        else
453            return 0;
454    }
455
456    /**
457        @brief Adds a new console command of this class.
458        @param executor The executor of the command
459        @param bCreateShortcut If this is true a shortcut gets created so you don't have to add the classname to access this command
460        @return The executor of the command
461    */
462    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
463    {
464        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
465        if (it != this->consoleCommands_.end())
466        {
467            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << "." << std::endl;
468            delete (it->second);
469        }
470
471        this->bHasConsoleCommands_ = true;
472        this->consoleCommands_[command->getName()] = command;
473        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
474
475        if (bCreateShortcut)
476            CommandExecutor::addConsoleCommandShortcut(command);
477
478        return (*command);
479    }
480
481    /**
482        @brief Returns the executor of a console command with given name.
483        @brief name The name of the requested console command
484        @return The executor of the requested console command
485    */
486    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
487    {
488        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
489        if (it != this->consoleCommands_.end())
490            return (*it).second;
491        else
492            return 0;
493    }
494
495    /**
496        @brief Returns the executor of a console command with given name in lowercase.
497        @brief name The name of the requested console command in lowercae
498        @return The executor of the requested console command
499    */
500    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
501    {
502        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
503        if (it != this->consoleCommands_LC_.end())
504            return (*it).second;
505        else
506            return 0;
507    }
508
509    /**
510        @brief Returns a XMLPortParamContainer that loads a parameter of this class.
511        @param paramname The name of the parameter
512        @return The container
513    */
514    XMLPortParamContainer* Identifier::getXMLPortParamContainer(const std::string& paramname)
515    {
516        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
517        if (it != this->xmlportParamContainers_.end())
518            return ((*it).second);
519        else
520            return 0;
521    }
522
523    /**
524        @brief Adds a new XMLPortParamContainer that loads a parameter of this class.
525        @param paramname The name of the parameter
526        @param container The container
527    */
528    void Identifier::addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container)
529    {
530        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
531        if (it != this->xmlportParamContainers_.end())
532        {
533            COUT(2) << "Warning: Overwriting XMLPortParamContainer in class " << this->getName() << "." << std::endl;
534            delete (it->second);
535        }
536
537        this->xmlportParamContainers_[paramname] = container;
538    }
539
540    /**
541        @brief Returns a XMLPortObjectContainer that attaches an object to this class.
542        @param sectionname The name of the section that contains the attachable objects
543        @return The container
544    */
545    XMLPortObjectContainer* Identifier::getXMLPortObjectContainer(const std::string& sectionname)
546    {
547        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
548        if (it != this->xmlportObjectContainers_.end())
549            return ((*it).second);
550        else
551            return 0;
552    }
553
554    /**
555        @brief Adds a new XMLPortObjectContainer that attaches an object to this class.
556        @param sectionname The name of the section that contains the attachable objects
557        @param container The container
558    */
559    void Identifier::addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container)
560    {
561        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
562        if (it != this->xmlportObjectContainers_.end())
563        {
564            COUT(2) << "Warning: Overwriting XMLPortObjectContainer in class " << this->getName() << "." << std::endl;
565            delete (it->second);
566        }
567
568        this->xmlportObjectContainers_[sectionname] = container;
569    }
570
571    /**
572        @brief Returns a XMLPortEventContainer that attaches an event to this class.
573        @param sectionname The name of the section that contains the event
574        @return The container
575    */
576    XMLPortObjectContainer* Identifier::getXMLPortEventContainer(const std::string& eventname)
577    {
578        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportEventContainers_.find(eventname);
579        if (it != this->xmlportEventContainers_.end())
580            return ((*it).second);
581        else
582            return 0;
583    }
584
585    /**
586        @brief Adds a new XMLPortEventContainer that attaches an event to this class.
587        @param sectionname The name of the section that contains the event
588        @param container The container
589    */
590    void Identifier::addXMLPortEventContainer(const std::string& eventname, XMLPortObjectContainer* container)
591    {
592        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportEventContainers_.find(eventname);
593        if (it != this->xmlportEventContainers_.end())
594        {
595            COUT(2) << "Warning: Overwriting XMLPortEventContainer in class " << this->getName() << "." << std::endl;
596            delete (it->second);
597        }
598
599        this->xmlportEventContainers_[eventname] = container;
600    }
601
602    /**
603        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
604        @param out The outstream
605        @param list The list (or set) of Identifiers
606        @return The outstream
607    */
608    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
609    {
610        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
611            out << (*it)->getName() << " ";
612
613        return out;
614    }
615}
Note: See TracBrowser for help on using the repository browser.