Index: code/trunk/src/libraries/core/class/Identifier.h
===================================================================
--- code/trunk/src/libraries/core/class/Identifier.h	(revision 9667)
+++ code/trunk/src/libraries/core/class/Identifier.h	(revision 10624)
@@ -80,6 +80,9 @@
 #include <typeinfo>
 #include <loki/TypeTraits.h>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_base_of.hpp>
 
 #include "util/Output.h"
+#include "util/OrxAssert.h"
 #include "core/object/ObjectList.h"
 #include "core/object/Listable.h"
@@ -109,5 +112,12 @@
     {
         public:
-            Identifier();
+            struct InheritsFrom //! helper class to manually define inheritance
+            {
+                virtual ~InheritsFrom() {}
+                virtual Identifier* getParent() const = 0;
+            };
+
+        public:
+            Identifier(const std::string& name, Factory* factory, bool bLoadable);
             Identifier(const Identifier& identifier); // don't copy
             virtual ~Identifier();
@@ -115,8 +125,7 @@
             /// Returns the name of the class the Identifier belongs to.
             inline const std::string& getName() const { return this->name_; }
-            void setName(const std::string& name);
-
-            /// Returns the name of the class as it is returned by typeid(T).name()
-            virtual const std::string& getTypeidName() = 0;
+
+            /// Returns the type_info of the class as it is returned by typeid(T)
+            virtual const std::type_info& getTypeInfo() = 0;
 
             /// Returns the network ID to identify a class through the network.
@@ -127,6 +136,4 @@
             ORX_FORCEINLINE unsigned int getClassID() const { return this->classID_; }
 
-            /// Sets the Factory.
-            void setFactory(Factory* factory);
             /// Returns true if the Identifier has a Factory.
             inline bool hasFactory() const { return (this->factory_ != 0); }
@@ -136,9 +143,18 @@
             /// Returns true if the class can be loaded through XML.
             inline bool isLoadable() const { return this->bLoadable_; }
-            /// Set the class to be loadable through XML or not.
-            inline void setLoadable(bool bLoadable) { this->bLoadable_ = bLoadable; }
+
+            /// Returns true if child classes should inherit virtually from this class.
+            inline bool isVirtualBase() const { return this->bIsVirtualBase_; }
+            /// Defines if child classes should inherit virtually from this class.
+            inline void setVirtualBase(bool bIsVirtualBase) { this->bIsVirtualBase_ = bIsVirtualBase; }
 
             /// Returns true if the Identifier was completely initialized.
             inline bool isInitialized() const { return this->bInitialized_; }
+
+            virtual void destroyObjects() = 0;
+
+            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
+
+            static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible
 
 
@@ -146,9 +162,9 @@
             ////// Class Hierarchy //////
             /////////////////////////////
-            Identifier& inheritsFrom(Identifier* directParent);
-
-            void initializeParents(const std::set<const Identifier*>& identifiers);
-            void initializeDirectParentsOfAbstractClass();
+            Identifier& inheritsFrom(InheritsFrom* directParent);
+
+            void initializeParents(const std::list<const Identifier*>& initializationTrace);
             void finishInitialization();
+            void reset();
 
             bool isA(const Identifier* identifier) const;
@@ -159,31 +175,13 @@
             bool isDirectParentOf(const Identifier* identifier) const;
 
+            /// Returns the direct parents of the class the Identifier belongs to.
+            inline const std::list<const Identifier*>& getDirectParents() const { return this->directParents_; }
             /// Returns the parents of the class the Identifier belongs to.
-            inline const std::set<const Identifier*>& getParents() const { return this->parents_; }
-            /// Returns the begin-iterator of the parents-list.
-            inline std::set<const Identifier*>::const_iterator getParentsBegin() const { return this->parents_.begin(); }
-            /// Returns the end-iterator of the parents-list.
-            inline std::set<const Identifier*>::const_iterator getParentsEnd() const { return this->parents_.end(); }
-
+            inline const std::list<const Identifier*>& getParents() const { return this->parents_; }
+
+            /// Returns the direct children the class the Identifier belongs to.
+            inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; }
             /// Returns the children of the class the Identifier belongs to.
             inline const std::set<const Identifier*>& getChildren() const { return this->children_; }
-            /// Returns the begin-iterator of the children-list.
-            inline std::set<const Identifier*>::const_iterator getChildrenBegin() const { return this->children_.begin(); }
-            /// Returns the end-iterator of the children-list.
-            inline std::set<const Identifier*>::const_iterator getChildrenEnd() const { return this->children_.end(); }
-
-            /// Returns the direct parents of the class the Identifier belongs to.
-            inline const std::set<const Identifier*>& getDirectParents() const { return this->directParents_; }
-            /// Returns the begin-iterator of the direct-parents-list.
-            inline std::set<const Identifier*>::const_iterator getDirectParentsBegin() const { return this->directParents_.begin(); }
-            /// Returns the end-iterator of the direct-parents-list.
-            inline std::set<const Identifier*>::const_iterator getDirectParentsEnd() const { return this->directParents_.end(); }
-
-            /// Returns the direct children the class the Identifier belongs to.
-            inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; }
-            /// Returns the begin-iterator of the direct-children-list.
-            inline std::set<const Identifier*>::const_iterator getDirectChildrenBegin() const { return this->directChildren_.begin(); }
-            /// Returns the end-iterator of the direct-children-list.
-            inline std::set<const Identifier*>::const_iterator getDirectChildrenEnd() const { return this->directChildren_.end(); }
 
 
@@ -223,21 +221,25 @@
             XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname);
 
-
         protected:
             virtual void createSuperFunctionCaller() const = 0;
 
         private:
-            std::set<const Identifier*> parents_;                          //!< The parents of the class the Identifier belongs to
+            void verifyIdentifierTrace() const;
+            void addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const;
+
+            std::list<const InheritsFrom*> manualDirectParents_;            //!< Manually defined direct parents
+            std::list<const Identifier*> directParents_;                    //!< The direct parents of the class the Identifier belongs to (sorted by their order of initialization)
+            std::list<const Identifier*> parents_;                          //!< The parents of the class the Identifier belongs to (sorted by their order of initialization)
+
+            std::set<const Identifier*> directChildren_;                   //!< The direct children of the class the Identifier belongs to
             std::set<const Identifier*> children_;                         //!< The children of the class the Identifier belongs to
-
-            std::set<const Identifier*> directParents_;                    //!< The direct parents of the class the Identifier belongs to
-            std::set<const Identifier*> directChildren_;                   //!< The direct children of the class the Identifier belongs to
 
             bool bInitialized_;                                            //!< Is true if the Identifier was completely initialized
             bool bLoadable_;                                               //!< False = it's not permitted to load the object through XML
+            bool bIsVirtualBase_;                                          //!< If true, it is recommended to inherit virtually from this class. This changes the order of initialization of child classes, thus this information is necessary to check the class hierarchy.
             std::string name_;                                             //!< The name of the class the Identifier belongs to
             Factory* factory_;                                             //!< The Factory, able to create new objects of the given class (if available)
             uint32_t networkID_;                                           //!< The network ID to identify a class through the network
-            const unsigned int classID_;                                   //!< Uniquely identifies a class (might not be the same as the networkID_)
+            unsigned int classID_;                                         //!< Uniquely identifies a class (might not be the same as the networkID_)
 
             bool bHasConfigValues_;                                        //!< True if this class has at least one assigned config value
@@ -267,4 +269,6 @@
     class ClassIdentifier : public Identifier
     {
+        BOOST_STATIC_ASSERT((boost::is_base_of<Identifiable, T>::value));
+
         #ifndef DOXYGEN_SHOULD_SKIP_THIS
           #define SUPER_INTRUSIVE_DECLARATION_INCLUDE
@@ -273,27 +277,9 @@
 
         public:
-            static ClassIdentifier<T>* getIdentifier();
-            static ClassIdentifier<T>* getIdentifier(const std::string& name);
-
-            bool initializeObject(T* object);
-
-            void setConfigValues(T* object, Configurable*) const;
-            void setConfigValues(T* object, Identifiable*) const;
-
-            void addObjectToList(T* object, Listable*);
-            void addObjectToList(T* object, Identifiable*);
-
-            virtual void updateConfigValues(bool updateChildren = true) const;
-
-            virtual const std::string& getTypeidName()
-                { return this->typeidName_; }
-
-        private:
-            static void initializeIdentifier();
-
-            ClassIdentifier(const ClassIdentifier<T>& identifier) {}    // don't copy
-            ClassIdentifier()
+            ClassIdentifier(const std::string& name, Factory* factory, bool bLoadable) : Identifier(name, factory, bLoadable)
             {
-                this->typeidName_ = typeid(T).name();
+                OrxVerify(ClassIdentifier<T>::classIdentifier_s == NULL, "Assertion failed in ClassIdentifier of type " << typeid(T).name());
+                ClassIdentifier<T>::classIdentifier_s = this;
+
                 SuperFunctionInitialization<0, T>::initialize(this);
             }
@@ -303,8 +289,36 @@
             }
 
+            bool initializeObject(T* object);
+
+            virtual void updateConfigValues(bool updateChildren = true) const;
+
+            virtual const std::type_info& getTypeInfo()
+                { return typeid(T); }
+
+            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const
+                { return dynamic_cast<T*>(object) != 0; }
+
+            virtual void destroyObjects();
+
+            static ClassIdentifier<T>* getIdentifier();
+
+        private:
+            ClassIdentifier(const ClassIdentifier<T>& identifier) {}    // don't copy
+
+            void setConfigValues(T* object, Configurable*) const;
+            void setConfigValues(T* object, Identifiable*) const;
+
+            void addObjectToList(T* object, Listable*);
+            void addObjectToList(T* object, Identifiable*);
+
+            void destroyObjects(Listable*);
+            void destroyObjects(void*);
+
+            void destroyObject(Destroyable* object);
+            void destroyObject(void* object);
+
             void updateConfigValues(bool updateChildren, Listable*) const;
             void updateConfigValues(bool updateChildren, Identifiable*) const;
 
-            std::string typeidName_;
             static WeakPtr<ClassIdentifier<T> > classIdentifier_s;
     };
@@ -318,45 +332,11 @@
     */
     template <class T>
-    inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
-    {
-        // check if the Identifier already exists
-        if (!ClassIdentifier<T>::classIdentifier_s)
-            ClassIdentifier<T>::initializeIdentifier();
-
+    /*static*/ inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
+    {
+        if (ClassIdentifier<T>::classIdentifier_s == NULL)
+            ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*) IdentifierManager::getInstance().getIdentifierByTypeInfo(typeid(T));
+
+        OrxVerify(ClassIdentifier<T>::classIdentifier_s != NULL, "Did you forget to register the class of type " << typeid(T).name() << "?");
         return ClassIdentifier<T>::classIdentifier_s;
-    }
-
-    /**
-        @brief Does the same as getIdentifier() but sets the name if this wasn't done yet.
-        @param name The name of this Identifier
-        @return The Identifier
-    */
-    template <class T>
-    inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier(const std::string& name)
-    {
-        ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier();
-        identifier->setName(name);
-        return identifier;
-    }
-
-    /**
-        @brief Assigns the static field for the identifier singleton.
-    */
-    template <class T>
-    /*static */ void ClassIdentifier<T>::initializeIdentifier()
-    {
-        // create a new identifier anyway. Will be deleted if not used.
-        ClassIdentifier<T>* proposal = new ClassIdentifier<T>();
-
-        // Get the entry from the map
-        ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*)IdentifierManager::getInstance().getGloballyUniqueIdentifier(proposal);
-
-        if (ClassIdentifier<T>::classIdentifier_s == proposal)
-            orxout(verbose, context::identifier) << "Requested Identifier for " << proposal->getTypeidName() << " was not yet existing and got created." << endl;
-        else
-        {
-            orxout(verbose, context::identifier) << "Requested Identifier for " << proposal->getTypeidName() << " was already existing and got assigned." << endl;
-            delete proposal; // delete proposal (it is not used anymore)
-        }
     }
 
@@ -375,5 +355,7 @@
             IdentifierManager::getInstance().createdObject(object);
 
-            this->setConfigValues(object, object);
+            if (Identifier::initConfigValues_s)
+                this->setConfigValues(object, object);
+
             return true;
         }
@@ -420,4 +402,48 @@
 
     /**
+     * @brief Destroy all objects of this class (must be Listable).
+     * Destroyables are destroyed with destroy(), all other classes with delete.
+     */
+    template <class T>
+    void ClassIdentifier<T>::destroyObjects()
+    {
+        this->destroyObjects((T*)0);
+    }
+
+    /**
+     * @brief Only searches and destroys objects if is a @ref Listable
+     */
+    template <class T>
+    void ClassIdentifier<T>::destroyObjects(Listable*)
+    {
+        ObjectListBase* objectList = Context::getRootContext()->getObjectList(this);
+        ObjectListElement<T>* begin = static_cast<ObjectListElement<T>*>(objectList->begin());
+        ObjectListElement<T>* end = static_cast<ObjectListElement<T>*>(objectList->end());
+        for (typename ObjectList<T>::iterator it = begin; it != end; )
+            this->destroyObject(*(it++));
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::destroyObjects(void*)
+    {
+        // no action
+    }
+
+    /**
+     * @brief Call 'object->destroy()' for Destroyables and 'delete object' for all other types.
+     */
+    template <class T>
+    void ClassIdentifier<T>::destroyObject(Destroyable* object)
+    {
+        object->destroy();
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::destroyObject(void* object)
+    {
+        delete static_cast<Identifiable*>(object);
+    }
+
+    /**
         @brief Updates the config-values of all existing objects of this class by calling their setConfigValues() function.
     */
@@ -438,5 +464,5 @@
 
         if (updateChildren)
-            for (std::set<const Identifier*>::const_iterator it = this->getChildrenBegin(); it != this->getChildrenEnd(); ++it)
+            for (std::set<const Identifier*>::const_iterator it = this->getChildren().begin(); it != this->getChildren().end(); ++it)
                 (*it)->updateConfigValues(false);
     }
