Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

we should initialize this with false now (since ClassByString also returns classes without factory since r5778)

  • 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_ = false;
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.