Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy/src/core/Identifier.cc @ 1952

Last change on this file since 1952 was 1940, checked in by landauf, 16 years ago

did some first (and very unfinished) steps to deal with different players on server and client

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