Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core6/src/libraries/core/class/Identifier.cc @ 9640

Last change on this file since 9640 was 9640, checked in by landauf, 11 years ago

made IdentifierManager a self-initializing singleton

  • Property svn:eol-style set to native
File size: 13.6 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
31    @brief Implementation of the Identifier class.
32*/
33
34#include "Identifier.h"
35
36#include <ostream>
37
38#include "util/StringUtils.h"
39#include "core/config/ConfigValueContainer.h"
40#include "core/XMLPort.h"
41#include "core/object/ClassFactory.h"
42
43namespace orxonox
44{
45    // ###############################
46    // ###       Identifier        ###
47    // ###############################
48    /**
49        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
50    */
51    Identifier::Identifier()
52        : classID_(IdentifierManager::getInstance().classIDCounter_s++)
53    {
54        this->bCreatedOneObject_ = false;
55        this->bSetName_ = false;
56        this->factory_ = 0;
57        this->bLoadable_ = false;
58
59        this->bHasConfigValues_ = false;
60
61        // Default network ID is the class ID
62        this->networkID_ = this->classID_;
63    }
64
65    /**
66        @brief Destructor: Deletes the list containing the children.
67    */
68    Identifier::~Identifier()
69    {
70        if (this->factory_)
71            delete this->factory_;
72
73        for (std::map<std::string, ConfigValueContainer*>::iterator it = this->configValues_.begin(); it != this->configValues_.end(); ++it)
74            delete (it->second);
75        for (std::map<std::string, XMLPortParamContainer*>::iterator it = this->xmlportParamContainers_.begin(); it != this->xmlportParamContainers_.end(); ++it)
76            delete (it->second);
77        for (std::map<std::string, XMLPortObjectContainer*>::iterator it = this->xmlportObjectContainers_.begin(); it != this->xmlportObjectContainers_.end(); ++it)
78            delete (it->second);
79    }
80
81    /**
82        @brief Registers a class, which means that the name and the parents get stored.
83        @param parents A list, containing the Identifiers of all parents of the class
84        @param bRootClass True if the class is either an Interface or the BaseObject itself
85    */
86    void Identifier::initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass)
87    {
88        // Check if at least one object of the given type was created
89        if (!this->bCreatedOneObject_ && IdentifierManager::getInstance().isCreatingHierarchy())
90        {
91            // If no: We have to store the information and initialize the Identifier
92            orxout(verbose, context::identifier) << "Register Class in ClassIdentifier<" << this->getName() << ">-Singleton -> Initialize Singleton." << endl;
93            if (bRootClass)
94                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.
95            else
96                this->initialize(parents);
97        }
98    }
99
100    /**
101        @brief Initializes the Identifier with a list containing all parents of the class the Identifier belongs to.
102        @param parents A list containing all parents
103    */
104    void Identifier::initialize(std::set<const Identifier*>* parents)
105    {
106        orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << this->name_ << ">-Singleton." << endl;
107        this->bCreatedOneObject_ = true;
108
109        if (parents)
110        {
111            this->parents_ = (*parents);
112            this->directParents_ = (*parents);
113
114            // Iterate through all parents
115            for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
116            {
117                // Tell the parent we're one of it's children
118                (*it)->children_.insert((*it)->children_.end(), this);
119
120                // Erase all parents of our parent from our direct-parent-list
121                for (std::set<const Identifier*>::const_iterator it1 = (*it)->getParents().begin(); it1 != (*it)->getParents().end(); ++it1)
122                {
123                    // Search for the parent's parent in our direct-parent-list
124                    for (std::set<const Identifier*>::iterator it2 = this->directParents_.begin(); it2 != this->directParents_.end(); ++it2)
125                    {
126                        if ((*it1) == (*it2))
127                        {
128                            // We've found a non-direct parent in our list: Erase it
129                            this->directParents_.erase(it2);
130                            break;
131                        }
132                    }
133                }
134            }
135
136            // Now iterate through all direct parents
137            for (std::set<const Identifier*>::iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
138            {
139                // Tell the parent we're one of it's direct children
140                (*it)->directChildren_.insert((*it)->directChildren_.end(), this);
141
142                // Create the super-function dependencies
143                (*it)->createSuperFunctionCaller();
144            }
145        }
146    }
147
148    /**
149        @brief Sets the name of the class.
150    */
151    void Identifier::setName(const std::string& name)
152    {
153        if (!this->bSetName_)
154        {
155            this->name_ = name;
156            this->bSetName_ = true;
157            IdentifierManager::getInstance().identifierByString_[name] = this;
158            IdentifierManager::getInstance().identifierByLowercaseString_[getLowercase(name)] = this;
159            IdentifierManager::getInstance().identifierByNetworkId_[this->networkID_] = this;
160        }
161    }
162
163    void Identifier::setFactory(Factory* factory)
164    {
165        if (this->factory_)
166            delete this->factory_;
167
168        this->factory_ = factory;
169    }
170
171
172    /**
173        @brief Creates an object of the type the Identifier belongs to.
174        @return The new object
175    */
176    Identifiable* Identifier::fabricate(Context* context)
177    {
178        if (this->factory_)
179        {
180            return this->factory_->fabricate(context);
181        }
182        else
183        {
184            orxout(user_error) << "An error occurred in Identifier.cc:" << endl;
185            orxout(user_error) << "Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << endl;
186            orxout(user_error) << "Aborting..." << endl;
187            abort();
188            return 0;
189        }
190    }
191
192    /**
193        @brief Sets the network ID to a new value and changes the entry in the ID-Identifier-map.
194    */
195    void Identifier::setNetworkID(uint32_t id)
196    {
197//        Identifier::getIDIdentifierMapIntern().erase(this->networkID_);
198        IdentifierManager::getInstance().identifierByNetworkId_[id] = this;
199        this->networkID_ = id;
200    }
201
202    /**
203        @brief Returns true, if the Identifier is at least of the given type.
204        @param identifier The identifier to compare with
205    */
206    bool Identifier::isA(const Identifier* identifier) const
207    {
208        return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
209    }
210
211    /**
212        @brief Returns true, if the Identifier is exactly of the given type.
213        @param identifier The identifier to compare with
214    */
215    bool Identifier::isExactlyA(const Identifier* identifier) const
216    {
217        return (identifier == this);
218    }
219
220    /**
221        @brief Returns true, if the assigned identifier is a child of the given identifier.
222        @param identifier The identifier to compare with
223    */
224    bool Identifier::isChildOf(const Identifier* identifier) const
225    {
226        return (this->parents_.find(identifier) != this->parents_.end());
227    }
228
229    /**
230        @brief Returns true, if the assigned identifier is a direct child of the given identifier.
231        @param identifier The identifier to compare with
232    */
233    bool Identifier::isDirectChildOf(const Identifier* identifier) const
234    {
235        return (this->directParents_.find(identifier) != this->directParents_.end());
236    }
237
238    /**
239        @brief Returns true, if the assigned identifier is a parent of the given identifier.
240        @param identifier The identifier to compare with
241    */
242    bool Identifier::isParentOf(const Identifier* identifier) const
243    {
244        return (this->children_.find(identifier) != this->children_.end());
245    }
246
247    /**
248        @brief Returns true, if the assigned identifier is a direct parent of the given identifier.
249        @param identifier The identifier to compare with
250    */
251    bool Identifier::isDirectParentOf(const Identifier* identifier) const
252    {
253        return (this->directChildren_.find(identifier) != this->directChildren_.end());
254    }
255
256    /**
257        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
258        @param varname The name of the variablee
259        @param container The container
260    */
261    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
262    {
263        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
264        if (it != this->configValues_.end())
265        {
266            orxout(internal_warning) << "Overwriting config-value with name " << varname << " in class " << this->getName() << '.' << endl;
267            delete (it->second);
268        }
269
270        this->bHasConfigValues_ = true;
271        this->configValues_[varname] = container;
272    }
273
274    /**
275        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
276        @param varname The name of the variable
277        @return The ConfigValueContainer
278    */
279    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
280    {
281        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
282        if (it != configValues_.end())
283            return it->second;
284        else
285            return 0;
286    }
287
288    /**
289        @brief Returns a XMLPortParamContainer that loads a parameter of this class.
290        @param paramname The name of the parameter
291        @return The container
292    */
293    XMLPortParamContainer* Identifier::getXMLPortParamContainer(const std::string& paramname)
294    {
295        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
296        if (it != this->xmlportParamContainers_.end())
297            return it->second;
298        else
299            return 0;
300    }
301
302    /**
303        @brief Adds a new XMLPortParamContainer that loads a parameter of this class.
304        @param paramname The name of the parameter
305        @param container The container
306    */
307    void Identifier::addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container)
308    {
309        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
310        if (it != this->xmlportParamContainers_.end())
311        {
312            orxout(internal_warning) << "Overwriting XMLPortParamContainer in class " << this->getName() << '.' << endl;
313            delete (it->second);
314        }
315
316        this->xmlportParamContainers_[paramname] = container;
317    }
318
319    /**
320        @brief Returns a XMLPortObjectContainer that attaches an object to this class.
321        @param sectionname The name of the section that contains the attachable objects
322        @return The container
323    */
324    XMLPortObjectContainer* Identifier::getXMLPortObjectContainer(const std::string& sectionname)
325    {
326        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
327        if (it != this->xmlportObjectContainers_.end())
328            return it->second;
329        else
330            return 0;
331    }
332
333    /**
334        @brief Adds a new XMLPortObjectContainer that attaches an object to this class.
335        @param sectionname The name of the section that contains the attachable objects
336        @param container The container
337    */
338    void Identifier::addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container)
339    {
340        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
341        if (it != this->xmlportObjectContainers_.end())
342        {
343            orxout(internal_warning) << "Overwriting XMLPortObjectContainer in class " << this->getName() << '.' << endl;
344            delete (it->second);
345        }
346
347        this->xmlportObjectContainers_[sectionname] = container;
348    }
349
350    /**
351        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
352        @param out The outstream
353        @param list The list (or set) of Identifiers
354        @return The outstream
355    */
356    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
357    {
358        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
359        {
360            if (it != list.begin())
361                out << ' ';
362            out << (*it)->getName();
363        }
364
365        return out;
366    }
367}
Note: See TracBrowser for help on using the repository browser.