bool ComponentCollection::ValidateComponent( const ComponentPtr &component, std::string& error ) const
{
    HELIUM_ASSERT( component->GetSlot() != NULL );

    // Check for duplicates.
    if ( ContainsComponent( component->GetSlot() ) )
    {
        std::string name;
        Helium::ConvertString( component->GetMetaClass()->m_Name, name );
        error = std::string( TXT( "The component '" ) )+ name + TXT( "' is a duplicate (a component already occupies that slot in the collection)." );
        return false;
    }

    // Check to make sure this type of collection accepts this type of component.
    if ( !ValidateCompatible( component, error ) )
    {
        return false;
    }

    // Check to make sure that each component already within the collection is valid with the new one.
    M_Component::const_iterator itr = m_Components.begin();
    M_Component::const_iterator end = m_Components.end();
    for ( ; itr != end; ++itr )
    {
        // Check both directions so that the validation rule only has to be implemented in one place.
        if ( !itr->second->ValidateSibling( component, error ) || !component->ValidateSibling( itr->second.Ptr(), error ) )
        {
            return false;
        }
    }

    return true;
}
bool ComponentCollection::ValidateCompatible( const ComponentPtr& component, std::string& error ) const
{
    HELIUM_ASSERT( component->GetSlot() != NULL );

    if ( component->GetComponentBehavior() == ComponentBehaviors::Exclusive )
    {
        error = *component->GetMetaClass()->m_Name;
        error += TXT( " cannot be added to a(n) " );
        error += *GetMetaClass()->m_Name;
        error += TXT( " because it is an exclusive component." );
        return false;
    }

    return true;
}
bool ComponentCollection::SetComponent(const ComponentPtr& component, bool validate, std::string* error )
{
    HELIUM_ASSERT( component->GetSlot() != NULL );

    M_Component::const_iterator found = m_Components.find( component->GetSlot() );
    if (found != m_Components.end() && found->second == component)
    {
        return true; // nothing to do, this is already in the collection
    }

    std::string errorMessage;
    if ( validate && !ValidateComponent( component, errorMessage ) )
    {
        if ( error )
        {
            std::string componentName;
            Helium::ConvertString( component->GetMetaClass()->m_Name, componentName );

            std::string collectionName;
            Helium::ConvertString( GetMetaClass()->m_Name, collectionName );

            *error = std::string( TXT( "Component '" ) ) + componentName + TXT( "' is not valid for collection '" ) + collectionName + TXT( "': " ) + errorMessage;
        }

        return false;
    }

    // Event args
    ComponentCollectionChanged args ( this, component );

    // Set the component and connect the collection
    m_Components[ component->GetSlot() ] = component;
    component->SetCollection( this );

    // Start caring about change to the component
    component->e_Changed.Add( ObjectChangeSignature::Delegate::Create<ComponentCollection, void (ComponentCollection::*)( const Reflect::ObjectChangeArgs& )> ( this, &ComponentCollection::ComponentChanged ) );

    // Raise event
    m_Modified = true;
    m_ComponentAdded.Raise( args );
    return true;
}