Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/archive/tutorialHS08/src/core/Identifier.cc @ 9215

Last change on this file since 9215 was 1747, checked in by landauf, 16 years ago

merged core3 back to trunk

  • Property svn:eol-style set to native
File size: 16.8 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 Initializes the Identifier with a list containing all parents of the class the Identifier belongs to.
122        @param parents A list containing all parents
123    */
124    void Identifier::initialize(std::set<const Identifier*>* parents)
125    {
126        COUT(4) << "*** Identifier: Initialize " << this->name_ << "-Singleton." << std::endl;
127        this->bCreatedOneObject_ = true;
128
129        if (parents)
130        {
131            this->parents_ = (*parents);
132            this->directParents_ = (*parents);
133
134            // Iterate through all parents
135            for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
136            {
137                // Tell the parent we're one of it's children
138                (*it)->getChildrenIntern().insert((*it)->getChildrenIntern().end(), this);
139
140                // Erase all parents of our parent from our direct-parent-list
141                for (std::set<const Identifier*>::const_iterator it1 = (*it)->getParents().begin(); it1 != (*it)->getParents().end(); ++it1)
142                {
143                    // Search for the parent's parent in our direct-parent-list
144                    for (std::set<const Identifier*>::iterator it2 = this->directParents_.begin(); it2 != this->directParents_.end(); ++it2)
145                    {
146                        if ((*it1) == (*it2))
147                        {
148                            // We've found a non-direct parent in our list: Erase it
149                            this->directParents_.erase(it2);
150                            break;
151                        }
152                    }
153                }
154            }
155
156            // Now iterate through all direct parents
157            for (std::set<const Identifier*>::iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
158            {
159                // Tell the parent we're one of it's direct children
160                (*it)->getDirectChildrenIntern().insert((*it)->getDirectChildrenIntern().end(), this);
161
162                // Create the super-function dependencies
163                (*it)->createSuperFunctionCaller();
164            }
165        }
166    }
167
168    /**
169        @brief Destroys all Identifiers. Called when exiting the program.
170    */
171    void Identifier::destroyAllIdentifiers()
172    {
173        for (std::map<std::string, Identifier*>::iterator it = Identifier::getIdentifierMapIntern().begin(); it != Identifier::getIdentifierMapIntern().end(); ++it)
174            delete (it->second);
175    }
176
177    /**
178        @brief Sets the name of the class.
179        @param name The name
180    */
181    void Identifier::setName(const std::string& name)
182    {
183        if (!this->bSetName_)
184        {
185            this->name_ = name;
186            this->bSetName_ = true;
187            Identifier::getIdentifierMapIntern()[name] = this;
188            Identifier::getLowercaseIdentifierMapIntern()[getLowercase(name)] = this;
189        }
190    }
191
192    /**
193        @brief Creates an object of the type the Identifier belongs to.
194        @return The new object
195    */
196    BaseObject* Identifier::fabricate()
197    {
198        if (this->factory_)
199        {
200            return this->factory_->fabricate(); // We have to return a BaseObject, because we don't know the exact type.
201        }
202        else
203        {
204            COUT(1) << "An error occurred in Identifier.cc:" << std::endl;
205            COUT(1) << "Error: Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << std::endl;
206            COUT(1) << "Aborting..." << std::endl;
207            abort();
208            return NULL;
209        }
210    }
211
212    /**
213        @brief Sets the network ID to a new value and changes the entry in the Factory.
214        @param id The new network ID
215    */
216    void Identifier::setNetworkID(unsigned int id)
217    {
218        Factory::changeNetworkID(this, this->classID_, id);
219        this->classID_ = id;
220    }
221
222    /**
223        @brief Returns true, if the Identifier is at least of the given type.
224        @param identifier The identifier to compare with
225    */
226    bool Identifier::isA(const Identifier* identifier) const
227    {
228        return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
229    }
230
231    /**
232        @brief Returns true, if the Identifier is exactly of the given type.
233        @param identifier The identifier to compare with
234    */
235    bool Identifier::isExactlyA(const Identifier* identifier) const
236    {
237        return (identifier == this);
238    }
239
240    /**
241        @brief Returns true, if the assigned identifier is a child of the given identifier.
242        @param identifier The identifier to compare with
243    */
244    bool Identifier::isChildOf(const Identifier* identifier) const
245    {
246        return (this->parents_.find(identifier) != this->parents_.end());
247    }
248
249    /**
250        @brief Returns true, if the assigned identifier is a direct child of the given identifier.
251        @param identifier The identifier to compare with
252    */
253    bool Identifier::isDirectChildOf(const Identifier* identifier) const
254    {
255        return (this->directParents_.find(identifier) != this->directParents_.end());
256    }
257
258    /**
259        @brief Returns true, if the assigned identifier is a parent of the given identifier.
260        @param identifier The identifier to compare with
261    */
262    bool Identifier::isParentOf(const Identifier* identifier) const
263    {
264        return (this->children_->find(identifier) != this->children_->end());
265    }
266
267    /**
268        @brief Returns true, if the assigned identifier is a direct parent of the given identifier.
269        @param identifier The identifier to compare with
270    */
271    bool Identifier::isDirectParentOf(const Identifier* identifier) const
272    {
273        return (this->directChildren_->find(identifier) != this->directChildren_->end());
274    }
275
276    /**
277        @brief Returns the map that stores all Identifiers.
278        @return The map
279    */
280    std::map<std::string, Identifier*>& Identifier::getIdentifierMapIntern()
281    {
282        static std::map<std::string, Identifier*> identifierMap;
283        return identifierMap;
284    }
285
286    /**
287        @brief Returns the map that stores all Identifiers.
288        @return The map
289    */
290    std::map<std::string, Identifier*>& Identifier::getLowercaseIdentifierMapIntern()
291    {
292        static std::map<std::string, Identifier*> lowercaseIdentifierMap;
293        return lowercaseIdentifierMap;
294    }
295
296    /**
297        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
298        @param varname The name of the variablee
299        @param container The container
300    */
301    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
302    {
303        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
304        if (it != this->configValues_.end())
305        {
306            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << "." << std::endl;
307            delete (it->second);
308        }
309
310        this->bHasConfigValues_ = true;
311        this->configValues_[varname] = container;
312        this->configValues_LC_[getLowercase(varname)] = container;
313    }
314
315    /**
316        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
317        @param varname The name of the variable
318        @return The ConfigValueContainer
319    */
320    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
321    {
322        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
323        if (it != configValues_.end())
324            return ((*it).second);
325        else
326            return 0;
327    }
328
329    /**
330        @brief Returns the ConfigValueContainer of a variable, given by the string of its name in lowercase.
331        @param varname The name of the variable in lowercase
332        @return The ConfigValueContainer
333    */
334    ConfigValueContainer* Identifier::getLowercaseConfigValueContainer(const std::string& varname)
335    {
336        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_LC_.find(varname);
337        if (it != configValues_LC_.end())
338            return ((*it).second);
339        else
340            return 0;
341    }
342
343    /**
344        @brief Adds a new console command of this class.
345        @param executor The executor of the command
346        @param bCreateShortcut If this is true a shortcut gets created so you don't have to add the classname to access this command
347        @return The executor of the command
348    */
349    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
350    {
351        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
352        if (it != this->consoleCommands_.end())
353        {
354            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << "." << std::endl;
355            delete (it->second);
356        }
357
358        this->bHasConsoleCommands_ = true;
359        this->consoleCommands_[command->getName()] = command;
360        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
361
362        if (bCreateShortcut)
363            CommandExecutor::addConsoleCommandShortcut(command);
364
365        return (*command);
366    }
367
368    /**
369        @brief Returns the executor of a console command with given name.
370        @brief name The name of the requested console command
371        @return The executor of the requested console command
372    */
373    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
374    {
375        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
376        if (it != this->consoleCommands_.end())
377            return (*it).second;
378        else
379            return 0;
380    }
381
382    /**
383        @brief Returns the executor of a console command with given name in lowercase.
384        @brief name The name of the requested console command in lowercae
385        @return The executor of the requested console command
386    */
387    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
388    {
389        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
390        if (it != this->consoleCommands_LC_.end())
391            return (*it).second;
392        else
393            return 0;
394    }
395
396    /**
397        @brief Returns a XMLPortParamContainer that loads a parameter of this class.
398        @param paramname The name of the parameter
399        @return The container
400    */
401    XMLPortParamContainer* Identifier::getXMLPortParamContainer(const std::string& paramname)
402    {
403        std::map<std::string, XMLPortParamContainer*>::const_iterator it = xmlportParamContainers_.find(paramname);
404        if (it != xmlportParamContainers_.end())
405            return ((*it).second);
406        else
407            return 0;
408    }
409
410    /**
411        @brief Adds a new XMLPortParamContainer that loads a parameter of this class.
412        @param paramname The name of the parameter
413        @param container The container
414    */
415    void Identifier::addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container)
416    {
417        this->xmlportParamContainers_[paramname] = container;
418    }
419
420    /**
421        @brief Returns a XMLPortObjectContainer that attaches an object to this class.
422        @param sectionname The name of the section that contains the attachable objects
423        @return The container
424    */
425    XMLPortObjectContainer* Identifier::getXMLPortObjectContainer(const std::string& sectionname)
426    {
427        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = xmlportObjectContainers_.find(sectionname);
428        if (it != xmlportObjectContainers_.end())
429            return ((*it).second);
430        else
431            return 0;
432    }
433
434    /**
435        @brief Adds a new XMLPortObjectContainer that attaches an object to this class.
436        @param sectionname The name of the section that contains the attachable objects
437        @param container The container
438    */
439    void Identifier::addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container)
440    {
441        this->xmlportObjectContainers_[sectionname] = container;
442    }
443
444    /**
445        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
446        @param out The outstream
447        @param list The list (or set) of Identifiers
448        @return The outstream
449    */
450    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
451    {
452        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
453            out << (*it)->getName() << " ";
454
455        return out;
456    }
457}
Note: See TracBrowser for help on using the repository browser.