Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

delete factory before setting a new one (mostly for unit tests)

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