Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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