/*
 * 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(EXSLT_COMMONIMPL_HEADER_GUARD_1357924680)
#define EXSLT_COMMONIMPL_HEADER_GUARD_1357924680



#include "XalanEXSLTDefinitions.hpp"



#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



#include <xalanc/XPath/Function.hpp>



#include <xalanc/XalanExtensions/FunctionNodeSet.hpp>



namespace XALAN_CPP_NAMESPACE {



class XALAN_EXSLT_EXPORT XalanEXSLTFunctionNodeSet : public FunctionNodeSet
{
public:

    XalanEXSLTFunctionNodeSet() :
        FunctionNodeSet(true)
    {
    }

    virtual
    ~XalanEXSLTFunctionNodeSet()
    {
    }

    virtual XalanEXSLTFunctionNodeSet*
    clone(MemoryManager& theManager) const
    {
        return XalanCopyConstruct(theManager, *this);
    }

protected:

    virtual const XalanDOMString&
    getError(XalanDOMString&    theBuffer) const
    {
        XalanMessageLoader::getMessage(
            theBuffer,
            XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
            "node-set()");

        return theBuffer;
    }


    virtual const XalanDOMString&
    getInvalidArgumentTypeError(XalanDOMString& theResult) const 
    {
         XalanMessageLoader::getMessage(
             theResult,
             XalanMessages::InvalidArgumentType_1Param,
             "node-set()");
         
         return theResult;
    }

private:

    // Not implemented...
    XalanEXSLTFunctionNodeSet&
    operator=(const XalanEXSLTFunctionNodeSet&);

    bool
    operator==(const XalanEXSLTFunctionNodeSet&) const;
};



class XALAN_EXSLT_EXPORT XalanEXSLTFunctionObjectType : public Function
{
public:

    typedef Function    ParentType;

    XalanEXSLTFunctionObjectType(MemoryManager& theManager) :
        Function(),
        m_boolean(s_booleanString, theManager),
        m_external(s_externalString, theManager),
        m_nodeSet(s_nodeSetString, theManager),
        m_number(s_numberString, theManager),
        m_rtf(s_rtfString, theManager),
        m_string(s_stringString, theManager)
    {
    }

    // A dummy constructor for use internally.  Do not use this one!!!!
    XalanEXSLTFunctionObjectType(MemoryManager& theManager, int /* theDummy */) :
        Function(),
        m_boolean(theManager),
        m_external(theManager),
        m_nodeSet(theManager),
        m_number(theManager),
        m_rtf(theManager),
        m_string(theManager)
    {
    }

    virtual
    ~XalanEXSLTFunctionObjectType()
    {
    }

    // These methods are inherited from Function ...

    virtual XObjectPtr
    execute(
            XPathExecutionContext&          executionContext,
            XalanNode*                      context,
            const XObjectArgVectorType&     args,
            const Locator*                  locator) const;

    using ParentType::execute;

    virtual XalanEXSLTFunctionObjectType*
    clone(MemoryManager& theManager) const
    {
        typedef XalanEXSLTFunctionObjectType    ThisType;

        XalanAllocationGuard    theGuard(theManager, theManager.allocate(sizeof(ThisType)));

        ThisType* const     theResult =
            new (theGuard.get()) ThisType(theManager);

        theGuard.release();

        return theResult;
    }

protected:



    const XalanDOMString&
    getError(XalanDOMString& theResult) const;

private:

    // Not implemented...
    XalanEXSLTFunctionObjectType(const XalanEXSLTFunctionObjectType&);

    XalanEXSLTFunctionObjectType&
    operator=(const XalanEXSLTFunctionObjectType&);

    bool
    operator==(const XalanEXSLTFunctionObjectType&) const;


    // Data members...
    const XalanDOMString    m_boolean;
    const XalanDOMString    m_external;
    const XalanDOMString    m_nodeSet;
    const XalanDOMString    m_number;
    const XalanDOMString    m_rtf;
    const XalanDOMString    m_string;

    static const XalanDOMChar   s_booleanString[];
    static const XalanDOMChar   s_externalString[];
    static const XalanDOMChar   s_nodeSetString[];
    static const XalanDOMChar   s_numberString[];
    static const XalanDOMChar   s_rtfString[];
    static const XalanDOMChar   s_stringString[];
};



}



#endif  // EXSLT_COMMONIMPL_HEADER_GUARD_1357924680
