- Timestamp:
- Mar 24, 2013, 6:08:42 PM (11 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
code/branches/core6/src/libraries/core/class/IdentifierManager.h
r9563 r9564 28 28 29 29 /** 30 @ defgroup Identifier Identifier31 @ingroup Class 30 @file 31 @ingroup Class Identifier 32 32 */ 33 33 34 /** 35 @file 36 @ingroup Class Identifier 37 @brief Declaration of Identifier, definition of ClassIdentifier<T>; used to identify the class of an object. 38 39 @anchor IdentifierExample 40 41 An Identifier "identifies" the class of an object. It contains different information about 42 the class: Its name and ID, a list of all instances of this class, a factory to create new 43 instances of this class, and more. 44 45 It also contains information about the inheritance of this class: It stores a list of the 46 Identifiers of all parent-classes as well as a list of all child-classes. These relationships 47 can be tested using functions like @c isA(), @c isChildOf(), @c isParentOf(), and more. 48 49 Every Identifier is in fact a ClassIdentifier<T> (where T is the class that is identified 50 by the Identifier), Identifier is just the common base-class. 51 52 Example: 53 @code 54 MyClass* object = new MyClass(); // create an instance of MyClass 55 56 object->getIdentifier()->getName(); // returns "MyClass" 57 58 OrxonoxClass* other = object->getIdentifier()->fabricate(0); // fabricates a new instance of MyClass 59 60 61 // iterate through all objects of type MyClass: 62 ObjectListBase* objects = object->getIdentifier()->getObjects(); // get a pointer to the object-list 63 int count; 64 for (Iterator<MyClass> it = objects.begin(); it != objects.end(); ++it) // iterate through the objects 65 ++count; 66 orxout() << count << endl; // prints "2" because we created 2 instances of MyClass so far 67 68 69 // test the class hierarchy 70 object->getIdentifier()->isA(Class(MyClass)); // returns true 71 object->isA(Class(MyClass)); // returns true (short version) 72 73 object->isA(Class(BaseClass)); // returns true if MyClass is a child of BaseClass 74 75 Class(ChildClass)->isChildOf(object->getIdentifier()); // returns true if ChildClass is a child of MyClass 76 @endcode 77 */ 78 79 #ifndef _Identifier_H__ 80 #define _Identifier_H__ 34 #ifndef _IdentifierManager_H__ 35 #define _IdentifierManager_H__ 81 36 82 37 #include "core/CorePrereqs.h" 83 38 84 #include <cassert>85 39 #include <map> 86 #include <set>87 40 #include <string> 88 #include <typeinfo>89 #include <loki/TypeTraits.h>90 91 #include "util/Output.h"92 #include "core/object/MetaObjectList.h"93 #include "core/object/ObjectList.h"94 #include "core/object/ObjectListBase.h"95 #include "Super.h"96 41 97 42 namespace orxonox 98 43 { 99 // ############################### 100 // ### Identifier ### 101 // ############################### 102 /** 103 @brief The Identifier is used to identify the class of an object and to store information about the class. 44 class _CoreExport IdentifierManager 45 { 46 friend class Identifier; 47 template <class T> friend class ClassIdentifier; 104 48 105 Each Identifier stores information about one class. The Identifier can then be used to identify106 this class. On the other hand it's also possible to get the corresponding Identifier of a class,107 for example by using the macro Class().108 109 @see See @ref IdentifierExample "Identifier.h" for more information and some examples.110 111 @note You can't directly create an Identifier, it's just the base-class of ClassIdentifier<T>.112 */113 class _CoreExport Identifier114 {115 49 public: 116 /// Returns the name of the class the Identifier belongs to.117 inline const std::string& getName() const { return this->name_; }118 void setName(const std::string& name);119 120 /// Returns the network ID to identify a class through the network.121 inline uint32_t getNetworkID() const { return this->networkID_; }122 void setNetworkID(uint32_t id);123 124 /// Returns the unique ID of the class.125 ORX_FORCEINLINE unsigned int getClassID() const { return this->classID_; }126 127 /// Returns the list of all existing objects of this class.128 inline ObjectListBase* getObjects() const { return this->objects_; }129 130 /// Sets the Factory.131 inline void addFactory(Factory* factory) { this->factory_ = factory; }132 /// Returns true if the Identifier has a Factory.133 inline bool hasFactory() const { return (this->factory_ != 0); }134 135 OrxonoxClass* fabricate(BaseObject* creator);136 137 /// Returns true if the class can be loaded through XML.138 inline bool isLoadable() const { return this->bLoadable_; }139 /// Set the class to be loadable through XML or not.140 inline void setLoadable(bool bLoadable) { this->bLoadable_ = bLoadable; }141 142 bool isA(const Identifier* identifier) const;143 bool isExactlyA(const Identifier* identifier) const;144 bool isChildOf(const Identifier* identifier) const;145 bool isDirectChildOf(const Identifier* identifier) const;146 bool isParentOf(const Identifier* identifier) const;147 bool isDirectParentOf(const Identifier* identifier) const;148 149 150 50 ///////////////////////////// 151 51 ////// Class Hierarchy ////// … … 154 54 155 55 /// Returns true, if a branch of the class-hierarchy is being created, causing all new objects to store their parents. 156 inline static bool isCreatingHierarchy() { return (hierarchyCreatingCounter_s > 0); } 157 158 /// Returns the parents of the class the Identifier belongs to. 159 inline const std::set<const Identifier*>& getParents() const { return this->parents_; } 160 /// Returns the begin-iterator of the parents-list. 161 inline std::set<const Identifier*>::const_iterator getParentsBegin() const { return this->parents_.begin(); } 162 /// Returns the end-iterator of the parents-list. 163 inline std::set<const Identifier*>::const_iterator getParentsEnd() const { return this->parents_.end(); } 164 165 /// Returns the children of the class the Identifier belongs to. 166 inline const std::set<const Identifier*>& getChildren() const { return this->children_; } 167 /// Returns the begin-iterator of the children-list. 168 inline std::set<const Identifier*>::const_iterator getChildrenBegin() const { return this->children_.begin(); } 169 /// Returns the end-iterator of the children-list. 170 inline std::set<const Identifier*>::const_iterator getChildrenEnd() const { return this->children_.end(); } 171 172 /// Returns the direct parents of the class the Identifier belongs to. 173 inline const std::set<const Identifier*>& getDirectParents() const { return this->directParents_; } 174 /// Returns the begin-iterator of the direct-parents-list. 175 inline std::set<const Identifier*>::const_iterator getDirectParentsBegin() const { return this->directParents_.begin(); } 176 /// Returns the end-iterator of the direct-parents-list. 177 inline std::set<const Identifier*>::const_iterator getDirectParentsEnd() const { return this->directParents_.end(); } 178 179 /// Returns the direct children the class the Identifier belongs to. 180 inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; } 181 /// Returns the begin-iterator of the direct-children-list. 182 inline std::set<const Identifier*>::const_iterator getDirectChildrenBegin() const { return this->directChildren_.begin(); } 183 /// Returns the end-iterator of the direct-children-list. 184 inline std::set<const Identifier*>::const_iterator getDirectChildrenEnd() const { return this->directChildren_.end(); } 56 inline static bool isCreatingHierarchy() 57 { return (hierarchyCreatingCounter_s > 0); } 185 58 186 59 … … 197 70 198 71 /// Returns the map that stores all Identifiers with their names. 199 static inline const std::map<std::string, Identifier*>& getStringIdentifierMap() { return Identifier::getStringIdentifierMapIntern(); } 72 static inline const std::map<std::string, Identifier*>& getStringIdentifierMap() 73 { return IdentifierManager::getStringIdentifierMapIntern(); } 200 74 /// Returns a const_iterator to the beginning of the map that stores all Identifiers with their names. 201 static inline std::map<std::string, Identifier*>::const_iterator getStringIdentifierMapBegin() { return Identifier::getStringIdentifierMap().begin(); } 75 static inline std::map<std::string, Identifier*>::const_iterator getStringIdentifierMapBegin() 76 { return IdentifierManager::getStringIdentifierMap().begin(); } 202 77 /// Returns a const_iterator to the end of the map that stores all Identifiers with their names. 203 static inline std::map<std::string, Identifier*>::const_iterator getStringIdentifierMapEnd() { return Identifier::getStringIdentifierMap().end(); } 78 static inline std::map<std::string, Identifier*>::const_iterator getStringIdentifierMapEnd() 79 { return IdentifierManager::getStringIdentifierMap().end(); } 204 80 205 81 /// Returns the map that stores all Identifiers with their names in lowercase. 206 static inline const std::map<std::string, Identifier*>& getLowercaseStringIdentifierMap() { return Identifier::getLowercaseStringIdentifierMapIntern(); } 82 static inline const std::map<std::string, Identifier*>& getLowercaseStringIdentifierMap() 83 { return IdentifierManager::getLowercaseStringIdentifierMapIntern(); } 207 84 /// Returns a const_iterator to the beginning of the map that stores all Identifiers with their names in lowercase. 208 static inline std::map<std::string, Identifier*>::const_iterator getLowercaseStringIdentifierMapBegin() { return Identifier::getLowercaseStringIdentifierMap().begin(); } 85 static inline std::map<std::string, Identifier*>::const_iterator getLowercaseStringIdentifierMapBegin() 86 { return IdentifierManager::getLowercaseStringIdentifierMap().begin(); } 209 87 /// Returns a const_iterator to the end of the map that stores all Identifiers with their names in lowercase. 210 static inline std::map<std::string, Identifier*>::const_iterator getLowercaseStringIdentifierMapEnd() { return Identifier::getLowercaseStringIdentifierMap().end(); } 88 static inline std::map<std::string, Identifier*>::const_iterator getLowercaseStringIdentifierMapEnd() 89 { return IdentifierManager::getLowercaseStringIdentifierMap().end(); } 211 90 212 91 /// Returns the map that stores all Identifiers with their IDs. 213 static inline const std::map<uint32_t, Identifier*>& getIDIdentifierMap() { return Identifier::getIDIdentifierMapIntern(); } 92 static inline const std::map<uint32_t, Identifier*>& getIDIdentifierMap() 93 { return IdentifierManager::getIDIdentifierMapIntern(); } 214 94 /// Returns a const_iterator to the beginning of the map that stores all Identifiers with their IDs. 215 static inline std::map<uint32_t, Identifier*>::const_iterator getIDIdentifierMapBegin() { return Identifier::getIDIdentifierMap().begin(); } 95 static inline std::map<uint32_t, Identifier*>::const_iterator getIDIdentifierMapBegin() 96 { return IdentifierManager::getIDIdentifierMap().begin(); } 216 97 /// Returns a const_iterator to the end of the map that stores all Identifiers with their IDs. 217 static inline std::map<uint32_t, Identifier*>::const_iterator getIDIdentifierMapEnd() { return Identifier::getIDIdentifierMap().end(); } 218 219 220 ///////////////////////// 221 ///// Config Values ///// 222 ///////////////////////// 223 virtual void updateConfigValues(bool updateChildren = true) const = 0; 224 225 /// Returns true if this class has at least one config value. 226 inline bool hasConfigValues() const { return this->bHasConfigValues_; } 227 228 void addConfigValueContainer(const std::string& varname, ConfigValueContainer* container); 229 ConfigValueContainer* getConfigValueContainer(const std::string& varname); 230 231 232 /////////////////// 233 ///// XMLPort ///// 234 /////////////////// 235 /// Returns the map that stores all XMLPort params. 236 inline const std::map<std::string, XMLPortParamContainer*>& getXMLPortParamMap() const { return this->xmlportParamContainers_; } 237 /// Returns a const_iterator to the beginning of the map that stores all XMLPort params. 238 inline std::map<std::string, XMLPortParamContainer*>::const_iterator getXMLPortParamMapBegin() const { return this->xmlportParamContainers_.begin(); } 239 /// Returns a const_iterator to the end of the map that stores all XMLPort params. 240 inline std::map<std::string, XMLPortParamContainer*>::const_iterator getXMLPortParamMapEnd() const { return this->xmlportParamContainers_.end(); } 241 242 /// Returns the map that stores all XMLPort objects. 243 inline const std::map<std::string, XMLPortObjectContainer*>& getXMLPortObjectMap() const { return this->xmlportObjectContainers_; } 244 /// Returns a const_iterator to the beginning of the map that stores all XMLPort objects. 245 inline std::map<std::string, XMLPortObjectContainer*>::const_iterator getXMLPortObjectMapBegin() const { return this->xmlportObjectContainers_.begin(); } 246 /// Returns a const_iterator to the end of the map that stores all XMLPort objects. 247 inline std::map<std::string, XMLPortObjectContainer*>::const_iterator getXMLPortObjectMapEnd() const { return this->xmlportObjectContainers_.end(); } 248 249 void addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container); 250 XMLPortParamContainer* getXMLPortParamContainer(const std::string& paramname); 251 252 void addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container); 253 XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname); 254 98 static inline std::map<uint32_t, Identifier*>::const_iterator getIDIdentifierMapEnd() 99 { return IdentifierManager::getIDIdentifierMap().end(); } 255 100 256 101 protected: 257 Identifier();258 Identifier(const Identifier& identifier); // don't copy259 virtual ~Identifier();260 261 102 static Identifier* getIdentifierSingleton(const std::string& name, Identifier* proposal); 262 virtual void createSuperFunctionCaller() const = 0;263 264 void initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass);265 103 266 104 /// Returns the map that stores all Identifiers with their names. … … 271 109 static std::map<uint32_t, Identifier*>& getIDIdentifierMapIntern(); 272 110 273 /// Returns the children of the class the Identifier belongs to.274 inline std::set<const Identifier*>& getChildrenIntern() const { return this->children_; }275 /// Returns the direct children of the class the Identifier belongs to.276 inline std::set<const Identifier*>& getDirectChildrenIntern() const { return this->directChildren_; }277 278 ObjectListBase* objects_; //!< The list of all objects of this class279 280 111 private: 281 112 /// Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents. 282 inline static void startCreatingHierarchy() { hierarchyCreatingCounter_s++; } 113 inline static void startCreatingHierarchy() 114 { hierarchyCreatingCounter_s++; } 283 115 /// Decreases the hierarchyCreatingCounter_s variable, causing the objects to stop storing their parents. 284 inline static void stopCreatingHierarchy() { hierarchyCreatingCounter_s--; } 116 inline static void stopCreatingHierarchy() 117 { hierarchyCreatingCounter_s--; } 285 118 286 119 static std::map<std::string, Identifier*>& getTypeIDIdentifierMap(); 287 120 288 void initialize(std::set<const Identifier*>* parents);289 290 std::set<const Identifier*> parents_; //!< The parents of the class the Identifier belongs to291 mutable std::set<const Identifier*> children_; //!< The children of the class the Identifier belongs to292 293 std::set<const Identifier*> directParents_; //!< The direct parents of the class the Identifier belongs to294 mutable std::set<const Identifier*> directChildren_; //!< The direct children of the class the Identifier belongs to295 296 bool bCreatedOneObject_; //!< True if at least one object of the given type was created (used to determine the need of storing the parents)297 bool bSetName_; //!< True if the name is set298 bool bLoadable_; //!< False = it's not permitted to load the object through XML299 std::string name_; //!< The name of the class the Identifier belongs to300 Factory* factory_; //!< The Factory, able to create new objects of the given class (if available)301 121 static int hierarchyCreatingCounter_s; //!< Bigger than zero if at least one Identifier stores its parents (its an int instead of a bool to avoid conflicts with multithreading) 302 uint32_t networkID_; //!< The network ID to identify a class through the network303 const unsigned int classID_; //!< Uniquely identifies a class (might not be the same as the networkID_)304 122 static unsigned int classIDCounter_s; //!< Static counter for the unique classIDs 305 306 bool bHasConfigValues_; //!< True if this class has at least one assigned config value307 std::map<std::string, ConfigValueContainer*> configValues_; //!< A map to link the string of configurable variables with their ConfigValueContainer308 309 std::map<std::string, XMLPortParamContainer*> xmlportParamContainers_; //!< All loadable parameters310 std::map<std::string, XMLPortObjectContainer*> xmlportObjectContainers_; //!< All attachable objects311 123 }; 312 313 _CoreExport std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list);314 315 316 // ###############################317 // ### ClassIdentifier ###318 // ###############################319 /**320 @brief The ClassIdentifier is derived from Identifier and holds all class-specific functions and variables the Identifier cannot have.321 322 ClassIdentifier is a Singleton, which means that only one ClassIdentifier for a given type T exists.323 This makes it possible to store information about a class, sharing them with all324 objects of that class without defining static variables in every class.325 326 To be really sure that not more than exactly one object exists (even with libraries),327 ClassIdentifiers are stored in a static map in Identifier.328 */329 template <class T>330 class ClassIdentifier : public Identifier331 {332 #ifndef DOXYGEN_SHOULD_SKIP_THIS333 #define SUPER_INTRUSIVE_DECLARATION_INCLUDE334 #include "Super.h"335 #endif336 337 public:338 static ClassIdentifier<T>* getIdentifier();339 static ClassIdentifier<T>* getIdentifier(const std::string& name);340 341 bool initialiseObject(T* object, const std::string& className, bool bRootClass);342 343 void updateConfigValues(bool updateChildren = true) const;344 345 private:346 static void initialiseIdentifier();347 ClassIdentifier(const ClassIdentifier<T>& identifier) {} // don't copy348 ClassIdentifier()349 {350 SuperFunctionInitialization<0, T>::initialize(this);351 }352 ~ClassIdentifier()353 {354 SuperFunctionDestruction<0, T>::destroy(this);355 }356 357 static ClassIdentifier<T>* classIdentifier_s;358 };359 360 template <class T>361 ClassIdentifier<T>* ClassIdentifier<T>::classIdentifier_s = 0;362 363 /**364 @brief Returns the only instance of this class.365 @return The unique Identifier366 */367 template <class T>368 inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()369 {370 // check if the Identifier already exists371 if (!ClassIdentifier<T>::classIdentifier_s)372 ClassIdentifier<T>::initialiseIdentifier();373 374 return ClassIdentifier<T>::classIdentifier_s;375 }376 377 /**378 @brief Does the same as getIdentifier() but sets the name if this wasn't done yet.379 @param name The name of this Identifier380 @return The Identifier381 */382 template <class T>383 inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier(const std::string& name)384 {385 ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier();386 identifier->setName(name);387 return identifier;388 }389 390 /**391 @brief Assigns the static field for the identifier singleton.392 */393 template <class T>394 void ClassIdentifier<T>::initialiseIdentifier()395 {396 // Get the name of the class397 std::string name = typeid(T).name();398 399 // create a new identifier anyway. Will be deleted in Identifier::getIdentifier if not used.400 ClassIdentifier<T>* proposal = new ClassIdentifier<T>();401 402 // Get the entry from the map403 ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*)Identifier::getIdentifierSingleton(name, proposal);404 405 if (ClassIdentifier<T>::classIdentifier_s == proposal)406 {407 orxout(verbose, context::identifier) << "Requested Identifier for " << name << " was not yet existing and got created." << endl;408 }409 else410 {411 orxout(verbose, context::identifier) << "Requested Identifier for " << name << " was already existing and got assigned." << endl;412 }413 }414 415 /**416 @brief Adds an object of the given type to the ObjectList.417 @param object The object to add418 @param className The name of the class T419 @param bRootClass True if this is a root class (i.e. it inherits directly from OrxonoxClass)420 */421 template <class T>422 bool ClassIdentifier<T>::initialiseObject(T* object, const std::string& className, bool bRootClass)423 {424 if (bRootClass)425 orxout(verbose, context::object_list) << "Register Root-Object: " << className << endl;426 else427 orxout(verbose, context::object_list) << "Register Object: " << className << endl;428 429 object->identifier_ = this;430 if (Identifier::isCreatingHierarchy())431 {432 if (bRootClass && !object->parents_)433 object->parents_ = new std::set<const Identifier*>();434 435 if (object->parents_)436 {437 this->initializeClassHierarchy(object->parents_, bRootClass);438 object->parents_->insert(object->parents_->end(), this);439 }440 441 object->setConfigValues();442 return true;443 }444 else445 {446 orxout(verbose, context::object_list) << "Added object to " << this->getName() << "-list." << endl;447 object->metaList_->add(this->objects_, this->objects_->add(new ObjectListElement<T>(object)));448 449 // Add pointer of type T to the map in the OrxonoxClass instance that enables "dynamic_casts"450 object->objectPointers_.push_back(std::make_pair(this->getClassID(), static_cast<void*>(object)));451 return false;452 }453 }454 455 /**456 @brief Updates the config-values of all existing objects of this class by calling their setConfigValues() function.457 */458 template <class T>459 void ClassIdentifier<T>::updateConfigValues(bool updateChildren) const460 {461 if (!this->hasConfigValues())462 return;463 464 for (ObjectListIterator<T> it = ObjectList<T>::begin(); it; ++it)465 it->setConfigValues();466 467 if (updateChildren)468 for (std::set<const Identifier*>::const_iterator it = this->getChildrenBegin(); it != this->getChildrenEnd(); ++it)469 (*it)->updateConfigValues(false);470 }471 472 473 // ###############################474 // ### orxonox_cast ###475 // ###############################476 /**477 @brief478 Casts on object of type OrxonoxClass to any derived type that is479 registered in the class hierarchy.480 @return481 Returns NULL if the cast is not possible482 @note483 In case of NULL return (and using MSVC), a dynamic_cast might still be possible if484 a class forgot to register its objects.485 Also note that the function is implemented differently for GCC/MSVC.486 */487 template <class T, class U>488 ORX_FORCEINLINE T orxonox_cast(U* source)489 {490 #ifdef ORXONOX_COMPILER_MSVC491 typedef Loki::TypeTraits<typename Loki::TypeTraits<T>::PointeeType>::NonConstType ClassType;492 if (source != NULL)493 return source->template getDerivedPointer<ClassType>(ClassIdentifier<ClassType>::getIdentifier()->getClassID());494 else495 return NULL;496 #else497 return dynamic_cast<T>(source);498 #endif499 }500 124 } 501 125 502 #endif /* _Identifier _H__ */126 #endif /* _IdentifierManager_H__ */
Note: See TracChangeset
for help on using the changeset viewer.