Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 4, 2015, 9:12:21 PM (9 years ago)
Author:
landauf
Message:

merged branch core7 back to trunk

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/libraries/core/class/Identifier.cc

    r9667 r10624  
    4444namespace orxonox
    4545{
     46    bool Identifier::initConfigValues_s = true;
     47
    4648    // ###############################
    4749    // ###       Identifier        ###
     
    5052        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
    5153    */
    52     Identifier::Identifier()
    53         : classID_(IdentifierManager::getInstance().getUniqueClassId())
    54     {
    55         this->factory_ = 0;
     54    Identifier::Identifier(const std::string& name, Factory* factory, bool bLoadable)
     55    {
     56        orxout(verbose, context::identifier) << "Create identifier for " << name << endl;
     57
     58        static unsigned int classIDCounter = 0;
     59
     60        this->classID_ = classIDCounter++;
     61        this->name_ = name;
     62        this->factory_ = factory;
     63        this->bLoadable_ = bLoadable;
    5664        this->bInitialized_ = false;
    57         this->bLoadable_ = false;
     65        this->bIsVirtualBase_ = false;
    5866
    5967        this->bHasConfigValues_ = false;
     
    7179            delete this->factory_;
    7280
     81        for (std::list<const InheritsFrom*>::const_iterator it = this->manualDirectParents_.begin(); it != this->manualDirectParents_.end(); ++it)
     82            delete (*it);
     83
     84        // erase this Identifier from all related identifiers
     85        for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
     86            const_cast<Identifier*>(*it)->children_.erase(this);
     87        for (std::list<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
     88            const_cast<Identifier*>(*it)->directChildren_.erase(this);
     89        for (std::set<const Identifier*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it)
     90            const_cast<Identifier*>(*it)->parents_.remove(this);
     91        for (std::set<const Identifier*>::const_iterator it = this->directChildren_.begin(); it != this->directChildren_.end(); ++it)
     92            const_cast<Identifier*>(*it)->directParents_.remove(this);
     93
    7394        for (std::map<std::string, ConfigValueContainer*>::iterator it = this->configValues_.begin(); it != this->configValues_.end(); ++it)
    7495            delete (it->second);
     
    7798        for (std::map<std::string, XMLPortObjectContainer*>::iterator it = this->xmlportObjectContainers_.begin(); it != this->xmlportObjectContainers_.end(); ++it)
    7899            delete (it->second);
    79     }
    80 
    81     /**
    82         @brief Sets the name of the class.
    83     */
    84     void Identifier::setName(const std::string& name)
    85     {
    86         if (name != this->name_)
    87         {
    88             this->name_ = name;
    89             IdentifierManager::getInstance().addIdentifierToLookupMaps(this);
    90         }
    91     }
    92 
    93     void Identifier::setFactory(Factory* factory)
    94     {
    95         if (this->factory_)
    96             delete this->factory_;
    97 
    98         this->factory_ = factory;
    99100    }
    100101
     
    126127    {
    127128        this->networkID_ = id;
    128         IdentifierManager::getInstance().addIdentifierToLookupMaps(this);
     129        IdentifierManager::getInstance().addIdentifier(this);    // add with new id
    129130    }
    130131
     
    132133     * @brief Used to define the direct parents of an Identifier of an abstract class.
    133134     */
    134     Identifier& Identifier::inheritsFrom(Identifier* directParent)
    135     {
    136         if (this->parents_.empty())
    137             this->directParents_.insert(directParent);
    138         else
    139             orxout(internal_error) << "Trying to add " << directParent->getName() << " as a direct parent of " << this->getName() << " after the latter was already initialized" << endl;
     135    Identifier& Identifier::inheritsFrom(InheritsFrom* directParent)
     136    {
     137        if (this->directParents_.empty())
     138            this->manualDirectParents_.push_back(directParent);
     139        else
     140            orxout(internal_error) << "Trying to manually add direct parent of " << this->getName() << " after the latter was already initialized" << endl;
    140141
    141142        return *this;
     
    144145    /**
    145146     * @brief Initializes the parents of this Identifier while creating the class hierarchy.
    146      * @param identifiers All identifiers that were used to create an instance of this class (including this identifier itself)
    147      */
    148     void Identifier::initializeParents(const std::set<const Identifier*>& identifiers)
     147     * @param initializationTrace All identifiers that were recorded while creating an instance of this class (including nested classes and this identifier itself)
     148     */
     149    void Identifier::initializeParents(const std::list<const Identifier*>& initializationTrace)
    149150    {
    150151        if (!IdentifierManager::getInstance().isCreatingHierarchy())
     
    154155        }
    155156
    156         for (std::set<const Identifier*>::const_iterator it = identifiers.begin(); it != identifiers.end(); ++it)
    157             if (*it != this)
    158                 this->parents_.insert(*it);
    159     }
    160 
    161     /**
    162      * @brief Initializes the direct parents of this Identifier while creating the class hierarchy. This is only intended for abstract classes.
    163      */
    164     void Identifier::initializeDirectParentsOfAbstractClass()
     157        if (this->directParents_.empty())
     158        {
     159            for (std::list<const Identifier*>::const_iterator it = initializationTrace.begin(); it != initializationTrace.end(); ++it)
     160                if (*it != this)
     161                    this->parents_.push_back(*it);
     162        }
     163        else
     164            orxout(internal_error) << "Trying to add parents to " << this->getName() << " after it was already initialized with manual calls to inheritsFrom<Class>()." << endl;
     165    }
     166
     167    /**
     168     * @brief Finishes the initialization of this Identifier after creating the class hierarchy by wiring the (direct) parent/child references correctly.
     169     */
     170    void Identifier::finishInitialization()
    165171    {
    166172        if (!IdentifierManager::getInstance().isCreatingHierarchy())
    167173        {
    168             orxout(internal_warning) << "Identifier::initializeDirectParentsOfAbstractClass() created outside of class hierarchy creation" << endl;
     174            orxout(internal_warning) << "Identifier::finishInitialization() created outside of class hierarchy creation" << endl;
    169175            return;
    170176        }
    171177
    172         // only Identifiable is allowed to have no parents (even tough it's currently not abstract)
    173         if (this->directParents_.empty() && !this->isExactlyA(Class(Identifiable)))
    174         {
    175             orxout(internal_error) << "Identifier " << this->getName() << " / " << this->getTypeidName() << " is marked as abstract but has no direct parents defined" << endl;
     178        if (this->isInitialized())
     179            return;
     180
     181        if (!this->parents_.empty())
     182        {
     183            // parents defined -> this class was initialized by creating a sample instance and recording the trace of identifiers
     184
     185            // initialize all parents
     186            for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
     187                const_cast<Identifier*>(*it)->finishInitialization(); // initialize parent
     188
     189            // parents of parents are no direct parents of this identifier
     190            this->directParents_ = this->parents_;
     191            for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
     192                for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     193                    this->directParents_.remove(*it_parent_parent);
     194
     195            this->verifyIdentifierTrace();
     196        }
     197        else if (!this->manualDirectParents_.empty())
     198        {
     199            // no parents defined -> this class was manually initialized by calling inheritsFrom<Class>()
     200
     201            // initialize all direct parents
     202            for (std::list<const InheritsFrom*>::const_iterator it = this->manualDirectParents_.begin(); it != this->manualDirectParents_.end(); ++it)
     203            {
     204                Identifier* directParent = (*it)->getParent();
     205                this->directParents_.push_back(directParent);
     206                directParent->finishInitialization(); // initialize parent
     207            }
     208
     209            // direct parents and their parents are also parents of this identifier (but only add them once)
     210            for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent)
     211            {
     212                for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     213                    this->addIfNotExists(this->parents_, *it_parent_parent);
     214                this->addIfNotExists(this->parents_, *it_parent);
     215            }
     216        }
     217        else if (!this->isExactlyA(Class(Identifiable)))
     218        {
     219            // only Identifiable is allowed to have no parents (even tough it's currently not abstract)
     220            orxout(internal_error) << "Identifier " << this->getName() << " / " << this->getTypeInfo().name() << " is marked as abstract but has no direct parents defined" << endl;
    176221            orxout(internal_error) << "  If this class is not abstract, use RegisterClass(ThisClass);" << endl;
    177222            orxout(internal_error) << "  If this class is abstract, use RegisterAbstractClass(ThisClass).inheritsFrom(Class(BaseClass));" << endl;
    178223        }
    179     }
    180 
    181     /**
    182      * @brief Finishes the initialization of this Identifier after creating the class hierarchy by wiring the (direct) parent/child references correctly.
    183      */
    184     void Identifier::finishInitialization()
    185     {
    186         if (!IdentifierManager::getInstance().isCreatingHierarchy())
    187         {
    188             orxout(internal_warning) << "Identifier::finishInitialization() created outside of class hierarchy creation" << endl;
    189             return;
    190         }
    191 
    192         if (this->isInitialized())
    193             return;
    194 
    195         // if no direct parents were defined, initialize them with the set of all parents
    196         if (this->directParents_.empty())
    197             this->directParents_ = this->parents_;
    198 
    199         // initialize all parents before continuing to initialize this identifier
    200         for (std::set<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
    201         {
    202             Identifier* directParent = const_cast<Identifier*>(*it);
    203             directParent->finishInitialization(); // initialize parent
    204             this->parents_.insert(directParent);  // direct parent is also a parent
    205             this->parents_.insert(directParent->parents_.begin(), directParent->parents_.end()); // parents of direct parent are also parents
    206         }
    207 
    208         // parents of parents are no direct parents of this identifier
    209         for (std::set<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
    210             for (std::set<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
    211                 this->directParents_.erase(*it_parent_parent);
    212224
    213225        // tell all parents that this identifier is a child
    214         for (std::set<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
     226        for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
    215227            const_cast<Identifier*>(*it)->children_.insert(this);
    216228
    217229        // tell all direct parents that this identifier is a direct child
    218         for (std::set<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
     230        for (std::list<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
    219231        {
    220232            const_cast<Identifier*>(*it)->directChildren_.insert(this);
     
    228240
    229241    /**
     242     * Resets all information about the class hierarchy. The identifier is considered uninitialized afterwards.
     243     */
     244    void Identifier::reset()
     245    {
     246        this->directParents_.clear();
     247        this->parents_.clear();
     248        this->directChildren_.clear();
     249        this->children_.clear();
     250        this->bInitialized_ = false;
     251    }
     252
     253    /**
     254     * Verifies if the recorded trace of parent identifiers matches the expected trace according to the class hierarchy. If it doesn't match, the class
     255     * hierarchy is likely wrong, e.g. due to wrong inheritsFrom<>() definitions in abstract classes.
     256     */
     257    void Identifier::verifyIdentifierTrace() const
     258    {
     259
     260        std::list<const Identifier*> expectedIdentifierTrace;
     261
     262        // if any parent class is virtual, it will be instantiated first, so we need to add them first.
     263        for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
     264        {
     265            if ((*it_parent)->isVirtualBase())
     266            {
     267                for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     268                    this->addIfNotExists(expectedIdentifierTrace, *it_parent_parent);
     269                this->addIfNotExists(expectedIdentifierTrace, *it_parent);
     270            }
     271        }
     272
     273        // now all direct parents get created recursively. already added identifiers (e.g. virtual base classes) are not added again.
     274        for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent)
     275        {
     276            for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     277                this->addIfNotExists(expectedIdentifierTrace, *it_parent_parent);
     278            this->addIfNotExists(expectedIdentifierTrace, *it_parent);
     279        }
     280
     281        // check if the expected trace matches the actual trace (which was defined by creating a sample instance)
     282        if (expectedIdentifierTrace != this->parents_)
     283        {
     284            orxout(internal_warning) << this->getName() << " has an unexpected initialization trace:" << endl;
     285
     286            orxout(internal_warning) << "  Actual trace (after creating a sample instance):" << endl << "    ";
     287            for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
     288                orxout(internal_warning) << " " << (*it_parent)->getName();
     289            orxout(internal_warning) << endl;
     290
     291            orxout(internal_warning) << "  Expected trace (according to class hierarchy definitions):" << endl << "    ";
     292            for (std::list<const Identifier*>::const_iterator it_parent = expectedIdentifierTrace.begin(); it_parent != expectedIdentifierTrace.end(); ++it_parent)
     293                orxout(internal_warning) << " " << (*it_parent)->getName();
     294            orxout(internal_warning) << endl;
     295
     296            orxout(internal_warning) << "  Direct parents (according to class hierarchy definitions):" << endl << "    ";
     297            for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent)
     298                orxout(internal_warning) << " " << (*it_parent)->getName();
     299            orxout(internal_warning) << endl;
     300        }
     301    }
     302
     303    /**
     304     * Adds @param identifierToAdd to @param list if this identifier is not already contained in the list.
     305     */
     306    void Identifier::addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const
     307    {
     308        if (std::find(list.begin(), list.end(), identifierToAdd) == list.end())
     309            list.push_back(identifierToAdd);
     310    }
     311
     312    /**
    230313        @brief Returns true, if the Identifier is at least of the given type.
    231314        @param identifier The identifier to compare with
     
    233316    bool Identifier::isA(const Identifier* identifier) const
    234317    {
    235         return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
     318        return (identifier == this || (this->isChildOf(identifier)));
    236319    }
    237320
     
    251334    bool Identifier::isChildOf(const Identifier* identifier) const
    252335    {
    253         return (this->parents_.find(identifier) != this->parents_.end());
     336        return (std::find(this->parents_.begin(), this->parents_.end(),  identifier) != this->parents_.end());
    254337    }
    255338
     
    260343    bool Identifier::isDirectChildOf(const Identifier* identifier) const
    261344    {
    262         return (this->directParents_.find(identifier) != this->directParents_.end());
     345        return (std::find(this->directParents_.begin(), this->directParents_.end(), identifier) != this->directParents_.end());
    263346    }
    264347
Note: See TracChangeset for help on using the changeset viewer.