Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/Identifier.cc @ 1856

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