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



// Base include file.  Must be first.
#include <xalanc/XPath/XPathDefinitions.hpp>



#include <xalanc/XalanDOM/XalanDOMString.hpp>



#include <xalanc/PlatformSupport/DoubleSupport.hpp>
#include <xalanc/PlatformSupport/FormatterListener.hpp>
#include <xalanc/PlatformSupport/XalanReferenceCountedObject.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include <xalanc/XPath/NodeRefListBase.hpp>
#include <xalanc/XPath/XalanXPathException.hpp>
#include <xalanc/XPath/XPathExecutionContext.hpp>



namespace XALAN_CPP_NAMESPACE {



class MutableNodeRefList;
class NodeRefListBase;
class XalanDocumentFragment;
class XObjectFactory;
class XObjectTypeCallback;



/**
 * Class to hold XPath return types.
 */
class XALAN_XPATH_EXPORT XObject : protected XalanReferenceCountedObject
{
public:

    friend class XObjectPtr;

    typedef XPathExecutionContext::GetCachedString  GetCachedString;

    /**
     * Enumeration of possible object types
     */
    enum    eObjectType { eTypeNull = 0,
                          eTypeUnknown = 1,
                          eTypeBoolean = 2,
                          eTypeNumber = 3,
                          eTypeString = 4,
                          eTypeNodeSet = 5,
                          eTypeResultTreeFrag = 6,
                          eTypeUserDefined = 7,
                          // These next types are implementation-specific, and
                          // are never returned by getType().
                          eTypeStringReference = 8,
                          eTypeStringAdapter = 9,
                          eTypeStringCached = 10,
                          eTypeXTokenNumberAdapter = 11,
                          eTypeXTokenStringAdapter = 12,
                          eTypeNodeSetNodeProxy = 13,
                          eUnknown
                        };

    /**
     * Perform static initialization.  See class XPathInit.
     *
     * @param theMemoryManager The MemoryManager instance.
     */
    static void
    initialize(MemoryManager&   theMemoryManager);

    /**
     * Perform static shut down.  See class XPathInit.
     */
    static void
    terminate();

    /**
     * Create an XObject.
     *
     * @param theObjectType The enum for the type of the object.
     * @param theMemoryManager The MemoryManager instance.
     */
    XObject(
            eObjectType     theObjectType,
            MemoryManager&  theMemoryManager);

    /**
     * Given a request type, return the equivalent string. 
     * For diagnostic purposes.
     *
     * @return string for type
     */
    virtual const XalanDOMString&
    getTypeString() const = 0;

    /**
     * Cast result object to a number.
     *
     * @param executionContext The current XPathExecutionContext
     * @return numeric value
     */
    virtual double
    num(XPathExecutionContext&  executionContext) const;

    /**
     * Cast result object to a number.
     *
     * This function does not have access to the current
     * XPathExecutionContext, so the result may contain data
     * from whitespace text nodes that might have been stripped
     * otherwise.
     *
     * @return numeric value
     */
    virtual double
    num() const;

    /**
     * Cast result object to a boolean.
     *
     * @param executionContext The current XPathExecutionContext
     * @return boolean value
     */
    virtual bool
    boolean(XPathExecutionContext&  executionContext) const = 0;

    /**
     * Cast result object to a string.
     *
     * @param executionContext The current XPathExecutionContext
     * @return string value
     */
    virtual const XalanDOMString&
    str(XPathExecutionContext&  executionContext) const = 0;

    /**
     * Cast result object to a string.
     *
     * This function does not have access to the current
     * XPathExecutionContext, so the result may contain data
     * from whitespace text nodes that might have been stripped
     * otherwise.
     *
     * @param executionContext The current XPathExecutionContext
     * @return string value
     */
    virtual const XalanDOMString&
    str() const = 0;

    typedef void (FormatterListener::*MemberFunctionPtr)(const XMLCh* const, const FormatterListener::size_type);

    /**
     * Send the string value to a FormatterListener instance.
     *
     * @param executionContext The current XPathExecutionContext
     * @param formatterListener The FormatterListener instance
     * @param function A pointer to the member function of FormatterListener to call
     */
    virtual void
    str(
            XPathExecutionContext&  executionContext,
            FormatterListener&      formatterListener,
            MemberFunctionPtr       function) const = 0;

    /**
     * Send the string value to a FormatterListener instance.
     *
     * This function does not have access to the current
     * XPathExecutionContext, so the result may contain data
     * from whitespace text nodes that might have been stripped
     * otherwise.
     *
     * @param formatterListener The FormatterListener instance
     * @param function A pointer to the member function of FormatterListener to call
     */
    virtual void
    str(
            FormatterListener&      formatterListener,
            MemberFunctionPtr       function) const = 0;

    /**
     * Append the string value directly a string
     *
     * @param executionContext The current XPathExecutionContext
     * @param theBuffer The buffer for the data
     */
    virtual void
    str(
            XPathExecutionContext&  executionContext,
            XalanDOMString&         theBuffer) const = 0;

    /**
     * Append the string value directly a string
     *
     * This function does not have access to the current
     * XPathExecutionContext, so the result may contain data
     * from whitespace text nodes that might have been stripped
     * otherwise.
     *
     * @param theBuffer The buffer for the data
     */
    virtual void
    str(XalanDOMString&     theBuffer) const = 0;

    /**
     * Get the length of the string value of the instance.
     *
     * @return The length of the string value
     */
    virtual double
    stringLength(XPathExecutionContext&     executionContext) const = 0;

    /**
     * Cast result object to a result tree fragment.
     *
     * @param executionContext The current XPathExecutionContext
     * @return result tree fragment
     */
    virtual const XalanDocumentFragment&
    rtree() const;

    /**
     * Cast result object to a nodelist 
     *
     * This function does not have access to the current
     * XPathExecutionContext, so the result may contain data
     * from whitespace text nodes that might have been stripped
     * otherwise.
     *
     * @param executionContext The current XPathExecutionContext
     * @return node list
     */
    virtual const NodeRefListBase&
    nodeset() const;

    /**
     * Process a callback request for preferred type information.
     *
     * @param theCallbackObject object to call back
     */
    virtual void
    ProcessXObjectTypeCallback(XObjectTypeCallback&     theCallbackObject) = 0;

    /**
     * Process a callback request for preferred type information.
     *
     * @param theCallbackObject object to call back
     */
    virtual void
    ProcessXObjectTypeCallback(XObjectTypeCallback&     theCallbackObject) const = 0;

    /**
     * Tell if two objects are functionally equal.
     *
     * @param theRHS object to compare
     * @param executionContext the current execution context
     * @return true if they are equal
     */
    bool
    equals(
            const XObject&          theRHS,
            XPathExecutionContext&  executionContext) const;

    /**
     * Tell if two objects are functionally not equal.
     *
     * @param theRHS object to compare
     * @param executionContext the current execution context
     * @return true if they are equal
     */
    bool
    notEquals(
            const XObject&          theRHS,
            XPathExecutionContext&  executionContext) const;

    /**
     * Tell if one object is less than the other.
     *
     * @param theRHS object to compare
     * @return true if they are equal
     */
    bool
    lessThan(
            const XObject&          theRHS,
            XPathExecutionContext&  executionContext) const;

    /**
     * Tell if one object is less than or equal
     * the other.
     *
     * @param theRHS object to compare
     * @return true if they are equal
     */
    bool
    lessThanOrEquals(
            const XObject&          theRHS,
            XPathExecutionContext&  executionContext) const;

    /**
     * Tell if one object is greater than the other.
     *
     * @param theRHS object to compare
     * @return true if they are equal
     */
    bool
    greaterThan(
            const XObject&          theRHS,
            XPathExecutionContext&  executionContext) const;

    /**
     * Tell if one object is greater than or equal
     * the other.
     *
     * @param theRHS object to compare
     * @return true if they are equal
     */
    bool
    greaterThanOrEquals(
            const XObject&          theRHS,
            XPathExecutionContext&  executionContext) const;

    /**
     * Tell what kind of class this is.
     *
     * @return numeric type value
     */
    eObjectType
    getType() const
    {
        return m_objectType;
    }

    /**
     * Static conversion function.  Returns the boolean value
     * of the supplied double.
     *
     * @param theString The double to convert.
     *
     * @return bool value
     */
    static bool
    boolean(double  theNumber)
    {
        return !DoubleSupport::isNaN(theNumber) && !DoubleSupport::equal(theNumber, 0.0);
    }

    /**
     * Static conversion function.  Returns the boolean value
     * of the supplied XalanDOMString.
     *
     * @param theString The XalanDOMString to convert.
     * @return bool value
     */
    static bool
    boolean(const XalanDOMString&   theString)
    {
        return theString.length() == 0 ? false : true;
    }

    /**
     * Static conversion function.  Returns the boolean value
     * of the supplied NodeRefListBase.
     *
     * @param theNodeList The NodeRefListBase to convert.
     * @return bool value
     */
    static bool
    boolean(const NodeRefListBase&  theNodeList)
    {
        return theNodeList.getLength() == 0 ? false : true;
    }

    /**
     * Static conversion function.  Returns a reference to a
     * XalanDOMString instance with the string value of the
     * boolean.
     *
     * @param theBool The boolean value to convert.
     * @return The string value of the boolean
     */
    static const XalanDOMString&
    string(bool     theBool)
    {
        return theBool == true ? s_trueString : s_falseString;
    }

    /**
     * Static conversion function. Appends the supplied boolean
     * value to a string.
     *
     * @param theBool The boolean value to convert.
     * @param theString The string value of the provided boolean value.
     */
    static void
    string(
            bool                theBool,
            XalanDOMString&     theString)
    {
        theString.append(theBool == true ? s_trueString : s_falseString);
    }

    /**
     * Static conversion function.  Calls the supplied FormatterListener
     * member function with the string value of the boolean.
     *
     * @param theBool The boolean value to convert.
     * @param formatterListener The FormatterListener instance.
     * @param function The FormatterListener member function to call.
     */
    static void
    string(
            bool                theBool,
            FormatterListener&  formatterListener,
            MemberFunctionPtr   function)
    {
        if(theBool == true)
        {
            (formatterListener.*function)(s_trueString.c_str(), s_trueString.length());
        }
        else
        {
            (formatterListener.*function)(s_falseString.c_str(), s_falseString.length());
        }
    }

    /**
     * Static conversion function.  Append the string value of the
     * double to the supplied XalanDOMString parameter.
     *
     * @param theNumber The double to convert.
     * @param theString The output XalanDOMString.
     */
    static void
    string(
            double              theNumber,
            XalanDOMString&     theString)
    {
        NumberToDOMString(theNumber, theString);
    }

    /**
     * Static conversion function.  Calls the supplied FormatterListener
     * member function with the string value of the double.
     *
     * @param theNumber The double to convert.
     * @param formatterListener The FormatterListener instance.
     * @param function The FormatterListener member function to call.
     */
    static void
    string(
            double              theNumber,
            FormatterListener&  formatterListener,
            MemberFunctionPtr   function)
    {
        DOMStringHelper::NumberToCharacters(theNumber, formatterListener, function);
    }

    /**
     * Static conversion function.  Append the string value of the
     * XalanNode to the supplied XalanDOMString parameter.
     *
     * @deprecated This function is deprecated and should not be used.
     *
     * @param theNode The XalanNode to convert.
     * @param theString The output XalanDOMString.
     */
    static void
    string(
            const XalanNode&    theNode,
            XalanDOMString&     theString)
    {
        DOMServices::getNodeData(theNode, theString);
    }

    /**
     * Static conversion function.  Calls the supplied FormatterListener
     * member function with the string value of the XalanNode.
     *
     * @deprecated This function is deprecated and should not be used.
     *
     * @param theNode The XalanNode to convert.
     * @param formatterListener The FormatterListener instance.
     * @param function The FormatterListener member function to call.
     */
    static void
    string(
            const XalanNode&    theNode,
            FormatterListener&  formatterListener,
            MemberFunctionPtr   function)
    {
        DOMServices::getNodeData(theNode, formatterListener, function);
    }

    /**
     * Static conversion function.  Append the string value of the
     * NodeRefListBase to the supplied XalanDOMString parameter.
     *
     * @deprecated This function is deprecated and should not be used.
     *
     * @param theNodeList The NodeRefListBase to convert.
     * @param theString The output XalanDOMString.
     */
    static void
    string(
            const NodeRefListBase&  theNodeList,
            XalanDOMString&         theString)
    {
        if (theNodeList.getLength() > 0)
        {
            assert(theNodeList.item(0) != 0);

            string(*theNodeList.item(0), theString);
        }
    }

    /**
     * Static conversion function.  Calls the supplied FormatterListener
     * member function with the string value of the NodeRefListBase.
     *
     * @deprecated This function is deprecated and should not be used.
     *
     * @param theNodeList The NodeRefListBase to convert.
     * @param formatterListener The FormatterListener instance.
     * @param function The FormatterListener member function to call.
     */
    static void
    string(
            const NodeRefListBase&  theNodeList,
            FormatterListener&      formatterListener,
            MemberFunctionPtr       function)
    {
        if (theNodeList.getLength() > 0)
        {
            assert(theNodeList.item(0) != 0);

            DOMServices::getNodeData(*theNodeList.item(0), formatterListener, function);
        }
    }

    /**
     * Static conversion function.  Append the string value of the
     * XalanNode to the supplied XalanDOMString parameter.
     *
     * @param theNode The XalanNode to convert.
     * @param theExecutionContext The current XPathExecutionContext.
     * @param theString The output XalanDOMString.
     */
    static void
    string(
            const XalanNode&        theNode,
            XPathExecutionContext&  theExecutionContext,
            XalanDOMString&         theString)
    {
        DOMServices::getNodeData(theNode, theExecutionContext, theString);
    }

    /**
     * Static conversion function.  Calls the supplied FormatterListener
     * member function with the string value of the XalanNode.
     *
     * @param theNode The XalanNode to convert.
     * @param theExecutionContext The current XPathExecutionContext.
     * @param formatterListener The FormatterListener instance.
     * @param function The FormatterListener member function to call.
     */
    static void
    string(
            const XalanNode&        theNode,
            XPathExecutionContext&  theExecutionContext,
            FormatterListener&      formatterListener,
            MemberFunctionPtr       function)
    {
        DOMServices::getNodeData(
            theNode,
            theExecutionContext,
            formatterListener,
            function);
    }

    /**
     * Static conversion function.  Append the string value of the
     * NodeRefListBase to the supplied XalanDOMString parameter.
     *
     * @param theNodeList The NodeRefListBase to convert.
     * @param theExecutionContext The current XPathExecutionContext.
     * @param theString The output XalanDOMString.
     */
    static void
    string(
            const NodeRefListBase&  theNodeList,
            XPathExecutionContext&  theExecutionContext,
            XalanDOMString&         theString)
    {
        if (theNodeList.getLength() > 0)
        {
            assert(theNodeList.item(0) != 0);

            string(*theNodeList.item(0), theExecutionContext, theString);
        }
    }

    /**
     * Static conversion function.  Calls the supplied FormatterListener
     * member function with the string value of the NodeRefListBase.
     *
     * @param theNodeList The NodeRefListBase to convert.
     * @param theExecutionContext The current XPathExecutionContext.
     * @param formatterListener The FormatterListener instance.
     * @param function The FormatterListener member function to call.
     */
    static void
    string(
            const NodeRefListBase&  theNodeList,
            XPathExecutionContext&  theExecutionContext,
            FormatterListener&      formatterListener,
            MemberFunctionPtr       function)
    {
        if (theNodeList.getLength() > 0)
        {
            assert(theNodeList.item(0) != 0);

            DOMServices::getNodeData(
                *theNodeList.item(0),
                theExecutionContext,
                formatterListener,
                function);
        }
    }

    /**
     * Calls the supplied FormatterListener member function with
     * the string.
     *
     * @param theString The XalanDOMString to convert.
     * @param formatterListener The FormatterListener instance.
     * @param function The FormatterListener member function to call.
     */
    static void
    string(
            const XalanDOMString&   theString,
            FormatterListener&      formatterListener,
            MemberFunctionPtr       function)
    {
        const XalanDOMString::size_type     theLength =
            theString.length();

        if (theLength != 0)
        {
            assert(theLength == static_cast<FormatterListener::size_type>(theLength));

            (formatterListener.*function)(
                theString.c_str(),
                static_cast<FormatterListener::size_type>(theLength));
        }
    }

    /**
     * Static conversion function.
     *
     * @return bool value
     */
    static double
    number(bool     theBoolean)
    {
        return theBoolean == true ? 1.0 : 0.0;
    }

    static double
    number(
            const XalanDOMString&   theString,
            MemoryManager&          theManager)
    {
        return DoubleSupport::toDouble(theString, theManager);
    }

    /**
     * Static conversion function.
     *
     * @return The number value of the node list
     */
    static double
    number(
            XPathExecutionContext&  executionContext,
            const NodeRefListBase&  theNodeList);

    /**
     * Static conversion function.
     *
     * @return The number value of the node
     */
    static double
    number(
            XPathExecutionContext&  executionContext,
            const XalanNode&        theNode);


    // All XObject instances are controlled by an instance of an XObjectFactory.
    friend class XObjectFactory;

    void
    setFactory(XObjectFactory*  theFactory)
    {
        m_factory = theFactory;
    }

    // Base class for all XObject exceptions...
    class XObjectException : public XalanXPathException
    {
    public:

        XObjectException(
                const XalanDOMString&   theMessage,
                MemoryManager&          theManager);

        XObjectException(
                const XalanDOMString&   theMessage,
                MemoryManager&          theManager,
                const Locator*          theLocator);

        XObjectException(const XObjectException&    other) ;

        virtual
        ~XObjectException();

        virtual const XalanDOMChar*
        getType() const;

    private:

        static const XalanDOMChar   s_type[];
    };

    class XObjectInvalidConversionException : public XObjectException
    {
    public:

        XObjectInvalidConversionException(
                    MemoryManager&          memoryManager,
                    const XalanDOMString&   fromType,
                    const XalanDOMString&   toType,
                    XalanDOMString&         buffer);

        XObjectInvalidConversionException(const XObjectInvalidConversionException&  other);

        virtual
        ~XObjectInvalidConversionException();

        virtual const XalanDOMChar*
        getType() const;

    private:

        static const XalanDOMChar   s_type[];

        static const XalanDOMString&
        formatErrorString(
                const XalanDOMString&   fromType,
                const XalanDOMString&   toType,
                XalanDOMString&         theResult);
    };

protected:

    /**
     * Create an XObject from another XObject.
     * 
     * The recommended copy constructor is the next
     * overload, that accepts an explicit MemoryManager
     * instance.
     *
     * @param source The source for the copy
     */
    XObject(const XObject&);

    /**
     * Create an XObject from another XObject.
     *
     * @param source The source for the copy
     * @param theMemoryManager The MemoryManager instance.
     */
    XObject(
            const XObject&  source,
            MemoryManager&  theManager);

    /**
     * Get the MemoryManager for this instance.
     *
     * @return The MemoryManager.
     */
    MemoryManager&
    getMemoryManager() const
    {
        assert(m_memoryManager != 0);

        return *m_memoryManager;
    }

    void
    throwInvalidConversionException(const XalanDOMString&   theTargetType) const;

    /**
     * Tell what kind of class this is.
     *
     * @return numeric type value
     */
    virtual eObjectType
    getRealType() const;

    virtual void 
    referenced();

    virtual void 
    dereferenced();

    virtual
    ~XObject();

    static const XalanDOMString     s_emptyString;

    static const XalanDOMString&    s_booleanString;

    static const XalanDOMString&    s_falseString;

    static const XalanDOMString&    s_nodesetString;

    static const XalanDOMString&    s_numberString;

    static const XalanDOMString&    s_resultTreeFragmentString;

    static const XalanDOMString&    s_stringString;

    static const XalanDOMString&    s_trueString;

private:

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


    eObjectType             m_objectType;

    XObjectFactory*         m_factory;

    mutable MemoryManager*  m_memoryManager;
};



/**
 * Class to hold XObjectPtr return types.
 */
class XALAN_XPATH_EXPORT XObjectPtr
{
public:

    friend bool operator==(const XObjectPtr&, const XObjectPtr&);
    friend bool operator<(const XObjectPtr&, const XObjectPtr&);

    /**
     * Create an XObjectPtr.
     */
    explicit
    XObjectPtr(XObject*     theXObject = 0) :
        m_xobjectPtr(theXObject)
    {
        XalanReferenceCountedObject::addReference(theXObject);
    }
    
    XObjectPtr(const XObjectPtr&    theSource) :
        m_xobjectPtr(theSource.m_xobjectPtr)
    { 
        XalanReferenceCountedObject::addReference(m_xobjectPtr);
    };

    XObjectPtr&
    operator=(const XObjectPtr&     theRHS)
    { 
        if (m_xobjectPtr != theRHS.m_xobjectPtr)
        {
            XalanReferenceCountedObject::removeReference(m_xobjectPtr);

            m_xobjectPtr = theRHS.m_xobjectPtr;

            XalanReferenceCountedObject::addReference(m_xobjectPtr);
        }

        return *this;
    }

    ~XObjectPtr()
    {
        XalanReferenceCountedObject::removeReference(m_xobjectPtr);
    };  

    void
    release()
    {
        XObject* const  xobjectPtr = m_xobjectPtr;

        m_xobjectPtr = 0;

        XalanReferenceCountedObject::removeReference(xobjectPtr);
    }

    bool
    null() const
    {
        return m_xobjectPtr == 0 ? true : false;
    }

    const XObject&
    operator*() const
    {
        return *m_xobjectPtr;
    };

    XObject&
    operator*() 
    {
        return *m_xobjectPtr;
    };

    const XObject*
    operator->() const
    {
        return m_xobjectPtr;
    };

    XObject*
    operator->()
    {
        return m_xobjectPtr;
    };

    const XObject*
    get() const
    {
        return m_xobjectPtr;
    };

    XObject*
    get()
    {
        return m_xobjectPtr;
    };

private:

    XObject*    m_xobjectPtr;
};



inline bool
operator==(
            const XObjectPtr&   theLHS,
            const XObjectPtr&   theRHS)
{
    return theLHS.m_xobjectPtr == theRHS.m_xobjectPtr;
}



inline bool
operator!=(
            const XObjectPtr&   theLHS,
            const XObjectPtr&   theRHS)
{
    return !(theLHS == theRHS);
}



inline bool
operator<(
            const XObjectPtr&   theLHS,
            const XObjectPtr&   theRHS)
{
    return theLHS.m_xobjectPtr < theRHS.m_xobjectPtr;
}



}



#endif  // XOBJECT_HEADER_GUARD_1357924680
