/*
 * 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.
 */
#if !defined(XALAN_OBJECTSTACKCACHE_HEADER_GUARD)
#define XALAN_OBJECTSTACKCACHE_HEADER_GUARD



#include <algorithm>



#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/STLHelper.hpp>
#include <xalanc/Include/XalanAutoPtr.hpp>
#include <xalanc/Include/XalanObjectCache.hpp>



namespace XALAN_CPP_NAMESPACE {


template<
class ObjectType,
#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
class CreateFunctorType,
class DeleteFunctorType,
class ResetFunctorType>
#else
class CreateFunctorType = DefaultCacheCreateFunctor<ObjectType>,
class DeleteFunctorType = DeleteFunctor<ObjectType>,
class ResetFunctorType = DefaultCacheResetFunctor<ObjectType> >
#endif
class XalanObjectStackCache
{
public:

    typedef XalanVector<ObjectType*>            VectorType;

    typedef ObjectType  CacheObjectType;

    explicit
    XalanObjectStackCache(
            MemoryManager&  theManager, 
            XalanSize_t         initialListSize = 0) :
        m_createFunctor(),
        m_deleteFunctor(theManager),
        m_stack(theManager),
        m_numObjectsOnStack(0)
    {
        m_stack.reserve(initialListSize);
    }

    ~XalanObjectStackCache()
    {
        using std::for_each;

        for_each(
                m_stack.begin(),
                m_stack.end(),
                m_deleteFunctor);
    }

    ObjectType*
    get()
    {
        
        if (m_stack.size() == m_numObjectsOnStack)
        {
            ObjectType* const   theNewObject = m_createFunctor(m_stack.getMemoryManager());
            m_stack.push_back(theNewObject);
            ++m_numObjectsOnStack;
            return theNewObject;
        }
        else
        {
            return m_stack[m_numObjectsOnStack++];
        }
    }

    ObjectType*
    top()
    {
        assert (m_numObjectsOnStack > 0);

        return m_stack[m_numObjectsOnStack-1];
    }

    ObjectType*
    release()
    {
        assert(m_numObjectsOnStack > 0);

        return m_stack[--m_numObjectsOnStack];
    }

    void
    reset()
    {
        typename VectorType::iterator iterator;

        for (iterator = m_stack.begin(); iterator < m_stack.end(); iterator++)
        {
            m_resetFunctor(*iterator);
        }
    }

    // Functors for various operations...
    CreateFunctorType   m_createFunctor;

    DeleteFunctorType   m_deleteFunctor;

    ResetFunctorType    m_resetFunctor;

private:

    // There are not defined...
    XalanObjectStackCache(const XalanObjectCache<ObjectType, CreateFunctorType, DeleteFunctorType, ResetFunctorType>&   theRHS);

    XalanObjectStackCache<ObjectType, CreateFunctorType, DeleteFunctorType, ResetFunctorType>&
    operator=(const XalanObjectCache<ObjectType, CreateFunctorType, DeleteFunctorType, ResetFunctorType>&   theRHS);


    // Data members...
    VectorType          m_stack;

    typename VectorType::size_type m_numObjectsOnStack;

};




template<class ObjectType>
class XalanObjectStackCacheDefault : public XalanObjectStackCache<ObjectType, DefaultCacheCreateFunctor<ObjectType>, DeleteFunctor<ObjectType>, DefaultCacheResetFunctor<ObjectType> >
{
public:

    typedef XalanObjectStackCache<ObjectType, DefaultCacheCreateFunctor<ObjectType>, DeleteFunctor<ObjectType>, DefaultCacheResetFunctor<ObjectType> >      BaseClassType;

    explicit
    XalanObjectStackCacheDefault(XalanSize_t    initialListSize = 0) :
        BaseClassType(initialListSize)
    {
    }
};



}



#endif
