Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/libs/src/libraries/core/class/IdentifierManager.cc @ 9703

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

merged core6 back to trunk

  • Property svn:eol-style set to native
File size: 8.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 "IdentifierManager.h"
35
36#include <ostream>
37
38#include "util/StringUtils.h"
39#include "core/CoreIncludes.h"
40#include "core/config/ConfigValueContainer.h"
41#include "core/XMLPort.h"
42#include "core/object/ClassFactory.h"
43
44namespace orxonox
45{
46    /* static */ IdentifierManager& IdentifierManager::getInstance()
47    {
48        static IdentifierManager instance;
49        return instance;
50    }
51
52    IdentifierManager::IdentifierManager()
53    {
54        this->hierarchyCreatingCounter_s = 0;
55        this->classIDCounter_s = 0;
56    }
57
58    /**
59        @brief Returns an identifier by name and adds it if not available
60        @param proposal A pointer to a newly created identifier for the case of non existence in the map
61        @return The identifier (unique instance)
62    */
63    Identifier* IdentifierManager::getGloballyUniqueIdentifier(Identifier* proposal)
64    {
65        const std::string& typeidName = proposal->getTypeidName();
66        std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.find(typeidName);
67
68        if (it != this->identifierByTypeidName_.end())
69        {
70            // There is already an entry: return it
71            return it->second;
72        }
73        else
74        {
75            // There is no entry: put the proposal into the map and return it
76            this->identifierByTypeidName_[typeidName] = proposal;
77            return proposal;
78        }
79    }
80
81    /**
82     * Registers the identifier in all maps of the IdentifierManager.
83     */
84    void IdentifierManager::addIdentifierToLookupMaps(Identifier* identifier)
85    {
86        const std::string& typeidName = identifier->getTypeidName();
87        if (this->identifierByTypeidName_.find(typeidName) != this->identifierByTypeidName_.end())
88        {
89            this->identifierByString_[identifier->getName()] = identifier;
90            this->identifierByLowercaseString_[getLowercase(identifier->getName())] = identifier;
91            this->identifierByNetworkId_[identifier->getNetworkID()] = identifier;
92        }
93        else
94            orxout(internal_warning) << "Trying to add an identifier to lookup maps which is not known to IdentifierManager" << endl;
95    }
96
97    /**
98        @brief Creates the class-hierarchy by creating and destroying one object of each type.
99    */
100    void IdentifierManager::createClassHierarchy()
101    {
102        orxout(internal_status) << "Create class-hierarchy" << endl;
103        this->startCreatingHierarchy();
104
105        std::set<Identifier*> initializedIdentifiers;
106
107        // ensure root context exists before starting to create objects. if the root context is dynamically created while creating the class hierarchy, we
108        // would mistakenly assume the class of the currently created object inherits from Context
109        Context::getRootContext();
110
111        // iterate over all identifiers, create one instance of each class and initialize the identifiers
112        {
113            Context temporaryContext(NULL);
114            for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
115            {
116                orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << it->second->getName() << ">-Singleton." << endl;
117                // To initialize the identifier, we create a new object and delete it afterwards.
118                if (it->second->hasFactory())
119                {
120                    this->identifiersOfNewObject_.clear();
121                    Identifiable* temp = it->second->fabricate(&temporaryContext);
122                    if (temp->getIdentifier() != it->second)
123                        orxout(internal_error) << "Newly created object of type " << it->second->getName() << " has unexpected identifier. Did you forget to use RegisterObject(classname)?" << endl;
124                    delete temp;
125
126                    it->second->initializeParents(this->identifiersOfNewObject_);
127                }
128                else
129                    it->second->initializeDirectParentsOfAbstractClass();
130
131                initializedIdentifiers.insert(it->second);
132            }
133
134            size_t numberOfObjects = temporaryContext.getObjectList<Listable>()->size();
135            if (numberOfObjects > 0)
136                orxout(internal_warning) << "There are still " << numberOfObjects << " listables left after creating the class hierarchy" << endl;
137        }
138
139        // finish the initialization of all identifiers
140        for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
141        {
142            if (initializedIdentifiers.find(it->second) != initializedIdentifiers.end())
143                it->second->finishInitialization();
144            else
145                orxout(internal_error) << "Identifier was registered late and is not initialized: " << it->second->getName() << " / " << it->second->getTypeidName() << endl;
146        }
147
148        this->stopCreatingHierarchy();
149        orxout(internal_status) << "Finished class-hierarchy creation" << endl;
150    }
151
152    /**
153        @brief Destroys all Identifiers. Called when exiting the program.
154    */
155    void IdentifierManager::destroyAllIdentifiers()
156    {
157        for (std::map<std::string, Identifier*>::iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
158            delete (it->second);
159
160        this->identifierByTypeidName_.clear();
161        this->identifierByString_.clear();
162        this->identifierByLowercaseString_.clear();
163        this->identifierByNetworkId_.clear();
164    }
165
166    /**
167     * @brief Notifies the IdentifierManager about a newly created object while creating the class hierarchy.
168     */
169    void IdentifierManager::createdObject(Identifiable* identifiable)
170    {
171        if (this->isCreatingHierarchy())
172            this->identifiersOfNewObject_.insert(identifiable->getIdentifier());
173        else
174            orxout(internal_warning) << "createdObject() called outside of class hierarchy creation" << endl;
175    }
176
177    /**
178        @brief Returns the Identifier with a given name.
179        @param name The name of the wanted Identifier
180        @return The Identifier
181    */
182    Identifier* IdentifierManager::getIdentifierByString(const std::string& name)
183    {
184        std::map<std::string, Identifier*>::const_iterator it = this->identifierByString_.find(name);
185        if (it != this->identifierByString_.end())
186            return it->second;
187        else
188            return 0;
189    }
190
191    /**
192        @brief Returns the Identifier with a given name in lowercase.
193        @param name The name of the wanted Identifier
194        @return The Identifier
195    */
196    Identifier* IdentifierManager::getIdentifierByLowercaseString(const std::string& name)
197    {
198        std::map<std::string, Identifier*>::const_iterator it = this->identifierByLowercaseString_.find(name);
199        if (it != this->identifierByLowercaseString_.end())
200            return it->second;
201        else
202            return 0;
203    }
204
205    /**
206        @brief Returns the Identifier with a given network ID.
207        @param id The network ID of the wanted Identifier
208        @return The Identifier
209    */
210    Identifier* IdentifierManager::getIdentifierByID(const uint32_t id)
211    {
212        std::map<uint32_t, Identifier*>::const_iterator it = this->identifierByNetworkId_.find(id);
213        if (it != this->identifierByNetworkId_.end())
214            return it->second;
215        else
216            return 0;
217    }
218
219    /**
220        @brief Cleans the NetworkID map (needed on clients for correct initialization)
221    */
222    void IdentifierManager::clearNetworkIDs()
223    {
224        this->identifierByNetworkId_.clear();
225    }
226}
Note: See TracBrowser for help on using the repository browser.