Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/Identifier.cc @ 1574

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

big change in ObjectList: separated the class into a non-template base and a template wrapper for the base. this also changes the Iterator, there is now a non-template IteratorBase. this brings much more flexibility, like iterating through all objects of a given identifier without knowing the type. however this needs a dynamic_cast, which isn't quite optimal, but I think there are much worser things than that out there. ;)

there isn't much you have to know about this, except there is no more ObjectList<myClass>::start() function but a ObjectList<myClass>::begin() to be more STLish. another thing: ObjectList<myClass>::end() points now to the element _after_ the last element, so it's possible to iterate in a for-loop until (it != ObjectList<myClass>::end()). the reason is the same as above. however, (it) as a boolean still works perfectly fine.

  • Property svn:eol-style set to native
File size: 13.5 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 "ConsoleCommand.h"
40#include "CommandExecutor.h"
41#include "MetaObjectList.h"
42#include "ObjectList.h"
43#include "OrxonoxClass.h"
44
45namespace orxonox
46{
47    // ###############################
48    // ###       Identifier        ###
49    // ###############################
50    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)
51
52    /**
53        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
54    */
55    Identifier::Identifier()
56    {
57        this->objects_ = new ObjectListBase(this);
58
59        this->bCreatedOneObject_ = 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    }
81
82    /**
83        @brief Returns an identifier by name and adds it if not available
84        @param name The name of the identifier as typeid().name() suggests
85        @param proposal A pointer to a newly created identifier for the case of non existance in the map
86        @return The identifier (unique instance)
87    */
88    Identifier *Identifier::getIdentifier(std::string &name, Identifier *proposal)
89    {
90        static std::map<std::string, Identifier*> identifiers;    //!< The map to store all Identifiers.
91        std::map<std::string, Identifier*>::const_iterator it = identifiers.find(name);
92        if (it == identifiers.end())
93        {
94            // there isn't an entry yet, put the proposal in it
95            identifiers[name] = proposal;
96        }
97        else
98        {
99            // this happens when a template exists twice --> delete the proposal
100            delete proposal;
101        }
102        return identifiers[name];
103    }
104
105    /**
106        @brief Initializes the Identifier with a list containing all parents of the class the Identifier belongs to.
107        @param parents A list containing all parents
108    */
109    void Identifier::initialize(std::set<const Identifier*>* parents)
110    {
111        COUT(4) << "*** Identifier: Initialize " << this->name_ << "-Singleton." << std::endl;
112        this->bCreatedOneObject_ = true;
113
114        if (parents)
115        {
116            this->parents_ = (*parents);
117            this->directParents_ = (*parents);
118
119            // Iterate through all parents
120            for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
121            {
122                // Tell the parent we're one of it's children
123                (*it)->getChildrenIntern().insert((*it)->getChildrenIntern().end(), this);
124
125                // Erase all parents of our parent from our direct-parent-list
126                for (std::set<const Identifier*>::const_iterator it1 = (*it)->getParents().begin(); it1 != (*it)->getParents().end(); ++it1)
127                {
128                    // Search for the parent's parent in our direct-parent-list
129                    for (std::set<const Identifier*>::iterator it2 = this->directParents_.begin(); it2 != this->directParents_.end(); ++it2)
130                    {
131                        if ((*it1) == (*it2))
132                        {
133                            // We've found a non-direct parent in our list: Erase it
134                            this->directParents_.erase(it2);
135                            break;
136                        }
137                    }
138                }
139            }
140
141            // Now iterate through all direct parents
142            for (std::set<const Identifier*>::iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
143            {
144                // Tell the parent we're one of it's direct children
145                (*it)->getDirectChildrenIntern().insert((*it)->getDirectChildrenIntern().end(), this);
146            }
147        }
148    }
149
150    /**
151        @brief Creates an object of the type the Identifier belongs to.
152        @return The new object
153    */
154    BaseObject* Identifier::fabricate()
155    {
156        if (this->factory_)
157        {
158            return this->factory_->fabricate(); // We have to return a BaseObject, because we don't know the exact type.
159        }
160        else
161        {
162            COUT(1) << "An error occurred in Identifier.cc:" << std::endl;
163            COUT(1) << "Error: Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << std::endl;
164            COUT(1) << "Aborting..." << std::endl;
165            abort();
166            return NULL;
167        }
168    }
169
170    /**
171        @brief Sets the network ID to a new value and changes the entry in the Factory.
172        @param id The new network ID
173    */
174    void Identifier::setNetworkID(unsigned int id)
175    {
176        Factory::changeNetworkID(this, this->classID_, id);
177        this->classID_ = id;
178    }
179
180    /**
181        @brief Adds an object of the given type to the ObjectList.
182        @param object The object to add
183    */
184    void Identifier::addObject(OrxonoxClass* object)
185    {
186        COUT(5) << "*** ClassIdentifier: Added object to " << this->getName() << "-list." << std::endl;
187        object->getMetaList().add(this->objects_, this->objects_->add(object));
188    }
189
190    /**
191        @brief Returns true, if the Identifier is at least of the given type.
192        @param identifier The identifier to compare with
193    */
194    bool Identifier::isA(const Identifier* identifier) const
195    {
196        return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
197    }
198
199    /**
200        @brief Returns true, if the Identifier is exactly of the given type.
201        @param identifier The identifier to compare with
202    */
203    bool Identifier::isExactlyA(const Identifier* identifier) const
204    {
205        return (identifier == this);
206    }
207
208    /**
209        @brief Returns true, if the assigned identifier is a child of the given identifier.
210        @param identifier The identifier to compare with
211    */
212    bool Identifier::isChildOf(const Identifier* identifier) const
213    {
214        return (this->parents_.find(identifier) != this->parents_.end());
215    }
216
217    /**
218        @brief Returns true, if the assigned identifier is a direct child of the given identifier.
219        @param identifier The identifier to compare with
220    */
221    bool Identifier::isDirectChildOf(const Identifier* identifier) const
222    {
223        return (this->directParents_.find(identifier) != this->directParents_.end());
224    }
225
226    /**
227        @brief Returns true, if the assigned identifier is a parent of the given identifier.
228        @param identifier The identifier to compare with
229    */
230    bool Identifier::isParentOf(const Identifier* identifier) const
231    {
232        return (this->children_->find(identifier) != this->children_->end());
233    }
234
235    /**
236        @brief Returns true, if the assigned identifier is a direct parent of the given identifier.
237        @param identifier The identifier to compare with
238    */
239    bool Identifier::isDirectParentOf(const Identifier* identifier) const
240    {
241        return (this->directChildren_->find(identifier) != this->directChildren_->end());
242    }
243
244    /**
245        @brief Returns the map that stores all Identifiers.
246        @return The map
247    */
248    std::map<std::string, Identifier*>& Identifier::getIdentifierMapIntern()
249    {
250        static std::map<std::string, Identifier*> identifierMap;
251        return identifierMap;
252    }
253
254    /**
255        @brief Returns the map that stores all Identifiers.
256        @return The map
257    */
258    std::map<std::string, Identifier*>& Identifier::getLowercaseIdentifierMapIntern()
259    {
260        static std::map<std::string, Identifier*> lowercaseIdentifierMap;
261        return lowercaseIdentifierMap;
262    }
263
264    /**
265        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
266        @param varname The name of the variablee
267        @param container The container
268    */
269    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
270    {
271        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
272        if (it != this->configValues_.end())
273        {
274            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << "." << std::endl;
275        }
276
277        this->bHasConfigValues_ = true;
278        this->configValues_[varname] = container;
279        this->configValues_LC_[getLowercase(varname)] = container;
280    }
281
282    /**
283        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
284        @param varname The name of the variable
285        @return The ConfigValueContainer
286    */
287    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
288    {
289        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
290        if (it != configValues_.end())
291            return ((*it).second);
292        else
293            return 0;
294    }
295
296    /**
297        @brief Returns the ConfigValueContainer of a variable, given by the string of its name in lowercase.
298        @param varname The name of the variable in lowercase
299        @return The ConfigValueContainer
300    */
301    ConfigValueContainer* Identifier::getLowercaseConfigValueContainer(const std::string& varname)
302    {
303        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_LC_.find(varname);
304        if (it != configValues_LC_.end())
305            return ((*it).second);
306        else
307            return 0;
308    }
309
310    /**
311        @brief Adds a new console command of this class.
312        @param executor The executor of the command
313        @param bCreateShortcut If this is true a shortcut gets created so you don't have to add the classname to access this command
314        @return The executor of the command
315    */
316    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
317    {
318        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
319        if (it != this->consoleCommands_.end())
320        {
321            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << "." << std::endl;
322        }
323
324        this->bHasConsoleCommands_ = true;
325        this->consoleCommands_[command->getName()] = command;
326        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
327
328        if (bCreateShortcut)
329            CommandExecutor::addConsoleCommandShortcut(command);
330
331        return (*command);
332    }
333
334    /**
335        @brief Returns the executor of a console command with given name.
336        @brief name The name of the requested console command
337        @return The executor of the requested console command
338    */
339    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
340    {
341        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
342        if (it != this->consoleCommands_.end())
343            return (*it).second;
344        else
345            return 0;
346    }
347
348    /**
349        @brief Returns the executor of a console command with given name in lowercase.
350        @brief name The name of the requested console command in lowercae
351        @return The executor of the requested console command
352    */
353    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
354    {
355        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
356        if (it != this->consoleCommands_LC_.end())
357            return (*it).second;
358        else
359            return 0;
360    }
361
362    /**
363        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
364        @param out The outstream
365        @param list The list (or set) of Identifiers
366        @return The outstream
367    */
368    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
369    {
370        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
371            out << (*it)->getName() << " ";
372
373        return out;
374    }
375}
Note: See TracBrowser for help on using the repository browser.