/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Class header file.
#include "AttributeListImpl.hpp"



#include <algorithm>
#include <cassert>



#include <xalanc/Include/XalanMemMgrAutoPtr.hpp>
#include <xalanc/Include/STLHelper.hpp>



#include "AttributeVectorEntry.hpp"



namespace XALAN_CPP_NAMESPACE {



AttributeListImpl::AttributeListImpl(MemoryManager&      theManager) :
    AttributeListType(),
    m_AttributeVector(theManager),
    m_cacheVector(theManager)
{
}



AttributeListImpl::~AttributeListImpl()
{
    // Clean up everything...
    clear();

    assert(m_AttributeVector.empty() == true);

    deleteEntries(m_cacheVector);
}



AttributeListImpl::AttributeListImpl(const AttributeListImpl&   theSource,
                                     MemoryManager&      theManager) :
    AttributeListType(),
    m_AttributeVector(theManager),
    m_cacheVector(theManager)
{
    // Use the assignment operator to do the dirty work...
    *this = theSource;

    assert(getLength() == theSource.getLength());
}



AttributeListImpl::AttributeListImpl(const AttributeListType&   theSource,
                                     MemoryManager&      theManager) :
    AttributeListType(),
    m_AttributeVector(theManager),
        m_cacheVector(theManager)

{
    // Use the assignment operator to do the dirty work...
    *this = theSource;

    assert(getLength() == theSource.getLength());
}



void
AttributeListImpl::deleteEntries(AttributeVectorType&   theVector)
{
    // Delete all of the objects in the vector.
    std::for_each(
        theVector.begin(),
        theVector.end(),
        DeleteFunctor<AttributeVectorEntry>(theVector.getMemoryManager()));
}



AttributeListImpl&
AttributeListImpl::operator=(const AttributeListImpl&   theRHS)
{
    if (this != &theRHS)
    {
        // Note that we can't chain up to our base class operator=()
        // because it's private.

        // Some temporary structures to hold everything
        // until we're done.
        AttributeVectorType     tempVector(getMemoryManager());

        const XalanSize_t   theLength = theRHS.getLength();

        if (theLength > 0)
        {
            // Reserve the appropriate capacity right now...
            tempVector.reserve(theLength);

            // This will delete everything in tempVector when we're done...
            CollectionDeleteGuard<AttributeVectorType,
                                  DeleteFunctor<AttributeVectorEntry> >     theGuard(tempVector);

            typedef AttributeVectorType::const_iterator     const_iterator;

            const const_iterator    theEnd = theRHS.m_AttributeVector.end();

            // Copy the vector entries, and build the index map...
            for(const_iterator i = theRHS.m_AttributeVector.begin(); i != theEnd; ++i)
            {
                AttributeVectorEntry* const     theEntry = *i;

                assert(theEntry != 0);

                // Add the item...
                tempVector.push_back(
                    getNewEntry(
                        &*theEntry->m_Name.begin(),
                        &*theEntry->m_Type.begin(),
                        &*theEntry->m_Value.begin()));
            }

            // OK, we're safe, so swap the contents of the
            // containers.  This is guaranteed not to throw.
            m_AttributeVector.swap(tempVector);
        }

        assert(getLength() == theLength);
    }

    return *this;
}



AttributeListImpl&
AttributeListImpl::operator=(const AttributeListType&   theRHS)
{
    if (this != &theRHS)
    {
        // Note that we can't chain up to our base class operator=()
        // because it's private.

        // Add all of the attributes to this temp list,
        // then swap at the end.  This means we're exception
        // safe and don't need any try blocks.
        AttributeListImpl   theTempList(getMemoryManager());

        const XalanSize_t   theLength = theRHS.getLength();

        theTempList.reserve(theLength);

        // Add each attribute.
        for(XalanSize_t i = 0; i < theLength; i++)
        {
            theTempList.addAttribute(
                    theRHS.getName(i),
                    theRHS.getType(i),
                    theRHS.getValue(i));
        }

        // Now that the temp list is built, swap everything. This is
        // guaranteed not to throw.
        swap(theTempList);
    }

    return *this;
}



XalanSize_t
AttributeListImpl::getLength() const
{
    // Make sure the mismatch between Xerces and vector<> doesn't cause a problem...
    assert(m_AttributeVector.size() == unsigned(m_AttributeVector.size()));

    return unsigned(m_AttributeVector.size());
}



const XMLCh*
AttributeListImpl::getName(const XalanSize_t    index) const
{
    assert(index < getLength());

    return &*m_AttributeVector[index]->m_Name.begin();
}



const XMLCh*
AttributeListImpl::getType(const XalanSize_t    index) const
{
    assert(index < getLength());

    return &*m_AttributeVector[index]->m_Type.begin();
}



const XMLCh*
AttributeListImpl::getValue(const XalanSize_t   index) const
{
    assert(index < getLength());

    return &*m_AttributeVector[index]->m_Value.begin();
}



const XMLCh*
AttributeListImpl:: getValue(const char* const /*name*/) const
{
    assert(0);

    return 0;
}



struct NameCompareFunctor
{
    NameCompareFunctor(const XMLCh*     theName) :
        m_name(theName)
    {
    }

    bool
    operator()(const AttributeVectorEntry*  theEntry) const
    {
        return equals(&*theEntry->m_Name.begin(), m_name);
    }

private:

    const XMLCh* const  m_name;
};



const XMLCh*
AttributeListImpl::getType(const XMLCh* const name) const
{
    assert(name != 0);

    const AttributeVectorType::const_iterator   i =
        std::find_if(
            m_AttributeVector.begin(),
            m_AttributeVector.end(),
            NameCompareFunctor(name));

    if (i != m_AttributeVector.end())
    {
        // Found it, so return a pointer to the type.
        return &*(*i)->m_Type.begin();
    }
    else
    {
        return 0;
    }
}


const XMLCh*
AttributeListImpl::getValue(const XMLCh* const name) const
{
    assert(name != 0);

    const AttributeVectorType::const_iterator   i =
        std::find_if(
            m_AttributeVector.begin(),
            m_AttributeVector.end(),
            NameCompareFunctor(name));

    if (i != m_AttributeVector.end())
    {
        // Found it, so return a pointer to the value.
        return &*(*i)->m_Value.begin();
    }
    else
    {
        return 0;
    }
}



void
AttributeListImpl::clear()
{
    m_cacheVector.insert(m_cacheVector.end(), m_AttributeVector.begin(), m_AttributeVector.end());

    // Clear everything out.
    m_AttributeVector.clear();
}



bool
AttributeListImpl::addAttribute(
            const XMLCh*    name,
            const XMLCh*    type,
            const XMLCh*    value)
{
    assert(name != 0);
    assert(type != 0);
    assert(value != 0);

    bool    fResult = false;

    using std::find_if;
    using std::copy;

    typedef AttributeVectorEntry::XMLChVectorType   XMLChVectorType;

    // Update the attribute, if it's already there...
    const AttributeVectorType::const_iterator   i =
        find_if(
            m_AttributeVector.begin(),
            m_AttributeVector.end(),
            NameCompareFunctor(name));

    if (i != m_AttributeVector.end())
    {
        // This is a special optimization for type, since it's (almost) always "CDATA".
        if (equals(type, &*(*i)->m_Type.begin()) == false)
        {
            // If necessary, create the a new vector and swap them.  Otherwise,
            // just copy the new data in.
            const XMLCh* const  theNewTypeEnd = AttributeVectorEntry::endArray(type) + 1;

            if ((*i)->m_Type.capacity() < XMLChVectorType::size_type(theNewTypeEnd - type))
            {
                XMLChVectorType     theNewType(type, theNewTypeEnd, getMemoryManager());

                theNewType.swap((*i)->m_Type);
            }
            else
            {
                copy(type, theNewTypeEnd, (*i)->m_Type.begin());
            }
        }

        const XMLCh* const  theNewValueEnd = AttributeVectorEntry::endArray(value) + 1;

        const XMLChVectorType::size_type    theNewSize =
                        XMLChVectorType::size_type(theNewValueEnd - value);

        // If necessary, create the a new vector and swap them.  Otherwise,
        // just copy the new data in.
        if ((*i)->m_Value.capacity() < theNewSize)
        {
            XMLChVectorType     theNewValue(value, theNewValueEnd, getMemoryManager());

            theNewValue.swap((*i)->m_Value); 
        }
        else
        {
            (*i)->m_Value.resize(theNewSize);

            copy(value, theNewValueEnd, (*i)->m_Value.begin());
        }
    }
    else
    {
        if (m_AttributeVector.capacity() == 0)
        {
            m_AttributeVector.reserve(eDefaultVectorSize);
        }
        
        typedef XalanMemMgrAutoPtr<AttributeVectorEntry>    AutoPtr;

        AutoPtr theEntry(getMemoryManager(), getNewEntry(name, type, value));

        // Add the new one.
        m_AttributeVector.push_back(theEntry.get());


        theEntry.release();

        fResult = true;
    }

    return fResult;
}



AttributeVectorEntry*
AttributeListImpl::getNewEntry(
            const XMLCh*    name,
            const XMLCh*    type,
            const XMLCh*    value)
{
    if (m_cacheVector.empty() == true)
    {
        return AttributeVectorEntry::create(name, value, type,getMemoryManager());
    }
    else
    {
        AttributeVectorEntry* const     theEntry =
            m_cacheVector.back();

        theEntry->clear();

        assert(theEntry->m_Name.empty() == true && theEntry->m_Value.empty() == true && theEntry->m_Type.empty() == true);

        theEntry->m_Name.insert(theEntry->m_Name.begin(), name, AttributeVectorEntry::endArray(name) + 1);
        theEntry->m_Value.insert(theEntry->m_Value.begin(), value, AttributeVectorEntry::endArray(value) + 1);
        theEntry->m_Type.insert(theEntry->m_Type.begin(), type, AttributeVectorEntry::endArray(type) + 1);

        m_cacheVector.pop_back();

        return theEntry;
    }
}



bool
AttributeListImpl::removeAttribute(const XMLCh*     name)
{
    assert(name != 0);

    bool    fResult = false;

    // Update the attribute, if it's already there...
    const AttributeVectorType::iterator     i =
        std::find_if(
            m_AttributeVector.begin(),
            m_AttributeVector.end(),
            NameCompareFunctor(name));

    if (i != m_AttributeVector.end())
    {
        m_cacheVector.push_back(*i);

        m_AttributeVector.erase(i);

        fResult = true;
    }

    return fResult;
}



}
