/*
 * 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.
 */
#include "XercesDocumentWrapper.hpp"



#include <algorithm>
#include <cassert>



#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMCDATASection.hpp>
#include <xercesc/dom/DOMComment.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMEntity.hpp>
#include <xercesc/dom/DOMEntityReference.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMNotation.hpp>
#include <xercesc/dom/DOMProcessingInstruction.hpp>
#include <xercesc/dom/DOMText.hpp>



#include <xalanc/Include/STLHelper.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include <xalanc/XalanDOM/XalanDocumentType.hpp>
#include <xalanc/XalanDOM/XalanElement.hpp>



#include "XercesAttrWrapper.hpp"
#include "XercesWrapperHelper.hpp"
#include "XercesCommentWrapper.hpp"
#include "XercesCDATASectionWrapper.hpp"
#include "XercesDOMWrapperException.hpp"
#include "XercesDOMImplementationWrapper.hpp"
#include "XercesDocumentTypeWrapper.hpp"
#include "XercesElementWrapper.hpp"
#include "XercesEntityWrapper.hpp"
#include "XercesEntityReferenceWrapper.hpp"
#include "XercesLiaisonXalanDOMStringPool.hpp"
#include "XercesNodeListWrapper.hpp"
#include "XercesNotationWrapper.hpp"
#include "XercesProcessingInstructionWrapper.hpp"
#include "XercesTextWrapper.hpp"



namespace XALAN_CPP_NAMESPACE {



XercesDocumentWrapper::XercesDocumentWrapper(
            MemoryManager&              theManager,
            const DOMDocument_Type*     theXercesDocument,
            bool                        threadSafe,
            bool                        buildWrapper,
            bool                        buildMaps) :
    XalanDocument(),
    m_xercesDocument(theXercesDocument),
    m_documentElement(0),
    m_nodeMap(theManager),
    m_navigatorAllocator(theManager, 25),
    m_navigator(0),
    m_children(theXercesDocument->getChildNodes(),
               *m_navigator),
    m_nodes(theManager),
    m_doctype(0),
    m_mappingMode(threadSafe == true ? false : !buildWrapper),
    m_indexValid(false),
    m_buildMaps(m_mappingMode == true ? true : buildMaps),
    m_elementAllocator(theManager, 25),
    m_textAllocator(theManager, 25),
    m_attributeAllocator(theManager, 25),
    m_stringPool(theManager, threadSafe == true ? XercesLiaisonXalanDOMStringPool::create(theManager) : XalanDOMStringPool::create(theManager))
{
    assert(theXercesDocument != 0);

    m_navigator = m_navigatorAllocator.create(this);

    if (m_mappingMode == false)
    {
        // The document index is always 1...
        m_navigator->setIndex(1);

        // OK, let's build the nodes.  This makes things
        // thread-safe, so the document can be shared...
        buildWrapperNodes();
    }
    else
    {
        m_nodeMap.addAssociation(theXercesDocument, this);
    }
}



XercesDocumentWrapper*
XercesDocumentWrapper::create( 
            MemoryManager&              theManager,
            const DOMDocument_Type*     theXercesDocument,
            bool                        threadSafe,
            bool                        buildWrapper,
            bool                        buildMaps)
{
    typedef XercesDocumentWrapper   ThisType;

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

    ThisType* const     theResult =
        new (theGuard.get()) ThisType(
                                theManager,
                                theXercesDocument,
                                threadSafe,
                                buildWrapper,
                                buildMaps);

    theGuard.release();

    return theResult;
}



XercesDocumentWrapper::~XercesDocumentWrapper()
{
    destroyWrapper();
}



XalanNode*
XercesDocumentWrapper::mapNode(const DOMNodeType*   theXercesNode) const
{
    XalanNode*  theXalanNode = 0;

    if (theXercesNode != 0)
    {
        theXalanNode = m_nodeMap.getNode(theXercesNode);

        if (theXalanNode == 0)
        {
            if (theXercesNode != m_xercesDocument &&
                    theXercesNode->getOwnerDocument() != m_xercesDocument &&
                theXercesNode->getParentNode() != static_cast<const DOMNodeType*>(m_xercesDocument))
            {
                throw XercesDOMWrapperException(XercesDOMWrapperException::WRONG_DOCUMENT_ERR);
            }
            else if (m_mappingMode == true)
            {
                // OK, we haven't yet created a wrapper, so go ahead and
                // create one.
                theXalanNode = createWrapperNode(theXercesNode, 0, true);
                assert(theXalanNode != 0);
            }
        }
    }

    return theXalanNode;
}



const DOMNodeType*
XercesDocumentWrapper::mapNode(XalanNode*   theXalanNode) const
{
    if (static_cast<const XalanNode*>(this) == theXalanNode)
    {
        return m_xercesDocument;
    }
    else if (theXalanNode == 0 ||
             static_cast<const XalanNode*>(this) != theXalanNode->getOwnerDocument())
    {
        throw XercesDOMWrapperException(XercesDOMWrapperException::WRONG_DOCUMENT_ERR);
    }
    else
    {
        switch(theXalanNode->getNodeType())
        {
        case XalanNode::ATTRIBUTE_NODE:
            return static_cast<const XercesAttrWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::CDATA_SECTION_NODE:
            return static_cast<const XercesCDATASectionWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::COMMENT_NODE:
            return static_cast<const XercesCommentWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::DOCUMENT_FRAGMENT_NODE:
            throw XercesDOMWrapperException(XercesDOMWrapperException::NOT_SUPPORTED_ERR);
            break;

        case XalanNode::ELEMENT_NODE:
            return static_cast<const XercesElementWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::ENTITY_NODE:
            return static_cast<const XercesEntityWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::ENTITY_REFERENCE_NODE:
            return static_cast<const XercesEntityReferenceWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::NOTATION_NODE:
            return static_cast<const XercesNotationWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::PROCESSING_INSTRUCTION_NODE:
            return static_cast<const XercesProcessingInstructionWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::TEXT_NODE:
            return static_cast<const XercesTextWrapper*>(theXalanNode)->getXercesNode();
            break;

        case XalanNode::DOCUMENT_TYPE_NODE:
            return static_cast<const XercesDocumentTypeWrapper*>(theXalanNode)->getXercesNode();
            break;

        default:
            assert(false);
            break;
        }

        return 0;
    }
}



XalanAttr*
XercesDocumentWrapper::mapNode(const DOMAttrType*   theXercesNode) const
{
    return static_cast<XalanAttr*>(mapNode(static_cast<const DOMNodeType*>(theXercesNode)));
}



XalanElement*
XercesDocumentWrapper::mapNode(const DOMElementType*    theXercesNode) const
{
    return static_cast<XercesElementWrapper*>(mapNode(static_cast<const DOMNodeType*>(theXercesNode)));
}



void
XercesDocumentWrapper::destroyWrapper()
{
    using std::for_each;

    // Set this to null, since it will be deleted
    // by the next for_each...
    m_doctype = 0;

    // m_bridgeMap contains all of the nodes that
    // are still alive...
    for_each(
            m_nodes.begin(),
            m_nodes.end(),
            DeleteFunctor<XalanNode>(m_nodes.getMemoryManager()));

    // Clear everything out, since we just delete everything...
    m_nodes.clear();

    // Clear out all of the navigators, except ours...
    m_navigatorAllocator.reset();

    m_navigator = m_navigatorAllocator.create(this);

    // Clear the node map...
    m_nodeMap.clear();

    m_indexValid = false;

    m_mappingMode = true;

    m_stringPool->clear();
}



void
XercesDocumentWrapper::rebuildWrapper()
{
    destroyWrapper();

    buildWrapperNodes();
}



XercesWrapperNavigator&
XercesDocumentWrapper::createNavigator() const
{
    return *m_navigatorAllocator.create(const_cast<XercesDocumentWrapper*>(this));
}



XercesDocumentTypeWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMDocumentType_Type*     theDoctype,
            IndexType                       theIndex,
            bool                            mapNode,
            XercesWrapperNavigator**        theWrapperNodeNavigator) const
{
    // This is a special case, since there is only one
    // doctype node allowed...
    assert(m_doctype == 0);
    assert(m_xercesDocument->getDoctype() != 0 &&
           m_xercesDocument->getDoctype() == theDoctype);

    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    // Update the member variable for the new instance.
    m_doctype =  XercesDocumentTypeWrapper::create(getMemoryManager(), theDoctype, theNavigator);

    if (mapNode == true)
    {
        m_nodeMap.addAssociation(theDoctype, m_doctype);
    }

    m_nodes.push_back(m_doctype);

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return m_doctype;
}



XercesElementWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMElementType*       theXercesNode,
            IndexType                   theIndex,
            bool                        mapNode,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesElementWrapper* const theWrapper =
        m_elementAllocator.create(theXercesNode, theNavigator);

    if (m_doctype != 0 || mapNode == true)
    {
        // Add it to the node map, since we my need it for getting
        // elements by ID, or we're in mapping mode.
        m_nodeMap.addAssociation(theXercesNode, theWrapper);
    }

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesTextWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMTextType*          theXercesNode,
            IndexType                   theIndex,
            bool                        mapNode,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesTextWrapper* const        theWrapper =
        m_textAllocator.create(theXercesNode, theNavigator);

    if (mapNode == true)
    {
        // Add it to the node map...
        m_nodeMap.addAssociation(theXercesNode, theWrapper);
    }

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesCommentWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMCommentType*       theXercesNode,
            IndexType                   theIndex,
            bool                        mapNode,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesCommentWrapper* const theWrapper =
        XercesCommentWrapper::create(
                                getMemoryManager(),
                                theXercesNode,
                                theNavigator);

    m_nodes.push_back(theWrapper);

    if (mapNode == true)
    {
        // Add it to the node map...
        m_nodeMap.addAssociation(theXercesNode, theWrapper);
    }

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesCDATASectionWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMCDATASectionType*  theXercesNode,
            IndexType                   theIndex,
            bool                        mapNode,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesCDATASectionWrapper* const        theWrapper =
        XercesCDATASectionWrapper::create(
                                     getMemoryManager(),
                                     theXercesNode,
                                     theNavigator);

    m_nodes.push_back(theWrapper);

    if (mapNode == true)
    {
        // Add it to the node map...
        m_nodeMap.addAssociation(theXercesNode, theWrapper);
    }

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesProcessingInstructionWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMProcessingInstructionType*     theXercesNode,
            IndexType                               theIndex,
            bool                                    mapNode,
            XercesWrapperNavigator**                theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesProcessingInstructionWrapper* const   theWrapper =
        XercesProcessingInstructionWrapper::create(
                                              getMemoryManager(),
                                              theXercesNode,
                                              theNavigator);

    m_nodes.push_back(theWrapper);

    if (mapNode == true)
    {
        // Add it to the node map...
        m_nodeMap.addAssociation(theXercesNode, theWrapper);
    }

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesAttrWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMAttrType*          theXercesNode,
            IndexType                   theIndex,
            bool                        /* mapNode */,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesAttrWrapper* const        theWrapper =
        m_attributeAllocator.create(theXercesNode, theNavigator);

    // Add it to the node map -- attributes ALWAYS go in the map
    // for now...
    m_nodeMap.addAssociation(theXercesNode, theWrapper);

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesEntityWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMEntityType*        theXercesNode,
            IndexType                   theIndex,
            bool                        /* mapNode */,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesEntityWrapper* const  theWrapper =
        XercesEntityWrapper::create(
                               getMemoryManager(),
                               theXercesNode,
                               theNavigator);

    m_nodes.push_back(theWrapper);

    // Add it to the node map -- entities ALWAYS go in the map
    // for now...
    m_nodeMap.addAssociation(theXercesNode, theWrapper);

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesEntityReferenceWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMEntityReferenceType*   theXercesNode,
            IndexType                       theIndex,
            bool                            mapNode,
            XercesWrapperNavigator**        theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesEntityReferenceWrapper* const theWrapper =
        XercesEntityReferenceWrapper::create(
                                        getMemoryManager(),
                                        theXercesNode,
                                        theNavigator);

    m_nodes.push_back(theWrapper);

    if (mapNode == true)
    {
        // Add it to the node map...
        m_nodeMap.addAssociation(theXercesNode, theWrapper);
    }

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XercesNotationWrapper*
XercesDocumentWrapper::createWrapperNode(
            const DOMNotationType*      theXercesNode,
            IndexType                   theIndex,
            bool                        /* mapNode */,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    // Create a navigator...
    XercesWrapperNavigator& theNavigator = createNavigator();

    theNavigator.setIndex(theIndex);

    XercesNotationWrapper* const        theWrapper =
        XercesNotationWrapper::create(
                                 getMemoryManager(),
                                 theXercesNode,
                                 theNavigator);

    m_nodes.push_back(theWrapper);

    // Add it to the node map -- notations ALWAYS go in the map
    // for now...
    m_nodeMap.addAssociation(theXercesNode, theWrapper);

    if (theWrapperNodeNavigator != 0)
    {
        *theWrapperNodeNavigator = &theNavigator;
    }

    return theWrapper;
}



XalanNode*
XercesDocumentWrapper::createWrapperNode(
            const DOMNodeType*          theXercesNode,
            IndexType                   theIndex,
            bool                        mapNode,
            XercesWrapperNavigator**    theWrapperNodeNavigator) const
{
    assert(theXercesNode != 0);

    XalanNode*              theNewNode = 0;

    switch(theXercesNode->getNodeType())
    {
    case DOMNodeType::ATTRIBUTE_NODE:
        {
            const DOMAttrType*      theAttrNode =
                        static_cast<const DOMAttrType*>(theXercesNode);

            theNewNode = createWrapperNode(theAttrNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::CDATA_SECTION_NODE:
        {
            const DOMCDATASectionType*  theCDATASectionNode =
                        static_cast<const DOMCDATASectionType*>(theXercesNode);

            theNewNode = createWrapperNode(theCDATASectionNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);

        }
        break;

    case DOMNodeType::COMMENT_NODE:
        {
            const DOMCommentType*   theCommentNode =
                        static_cast<const DOMCommentType*>(theXercesNode);

            theNewNode = createWrapperNode(theCommentNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::DOCUMENT_FRAGMENT_NODE:
        throw XercesDOMWrapperException(XercesDOMWrapperException::NOT_SUPPORTED_ERR);
        break;

    case DOMNodeType::ELEMENT_NODE:
        {
            const DOMElementType*   theElementNode =
                        static_cast<const DOMElementType*>(theXercesNode);

            theNewNode = createWrapperNode(theElementNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::ENTITY_NODE:
        {
            const DOMEntityType*    theEntityNode =
                        static_cast<const DOMEntityType*>(theXercesNode);

            theNewNode = createWrapperNode(theEntityNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::ENTITY_REFERENCE_NODE:
        {
            const DOMEntityReferenceType*   theEntityReferenceNode =
                        static_cast<const DOMEntityReferenceType*>(theXercesNode);

            theNewNode = createWrapperNode(theEntityReferenceNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::NOTATION_NODE:
        {
            const DOMNotationType*  theNotationNode =
                        static_cast<const DOMNotationType*>(theXercesNode);

            theNewNode = createWrapperNode(theNotationNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::PROCESSING_INSTRUCTION_NODE:
        {
            const DOMProcessingInstructionType*     thePINode =
                        static_cast<const DOMProcessingInstructionType*>(theXercesNode);

            theNewNode = createWrapperNode(thePINode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::TEXT_NODE:
        {
            const DOMTextType*  theTextNode =
                        static_cast<const DOMTextType*>(theXercesNode);

            theNewNode = createWrapperNode(theTextNode, theIndex, mapNode, theWrapperNodeNavigator);
            assert(theNewNode != 0);
        }
        break;

    case DOMNodeType::DOCUMENT_TYPE_NODE:
        {
            const DOMDocumentType_Type*     theDoctypeNode =
                        static_cast<const DOMDocumentType_Type*>(theXercesNode);

            theNewNode = createWrapperNode(theDoctypeNode, theIndex, mapNode, theWrapperNodeNavigator);

            assert(theNewNode != 0);
        }
        break;

    default:
        assert(false);
        break;
    }

    return theNewNode;
}



void
XercesDocumentWrapper::destroyNode(XalanNode*   theNode)
{
    using std::find;

    const NodeVectorType::iterator  i =
        find(m_nodes.begin(), m_nodes.end(), theNode);

    if (i == m_nodes.end())
    {
        // Doesn't belong to this doc, so throw...
        throw XercesDOMWrapperException(XercesDOMWrapperException::WRONG_DOCUMENT_ERR);
    }
    else
    {
        assert(*i != 0);

        // Delete the node...
        XalanDestroy(
            m_nodes.getMemoryManager(),
            **i);

        // Erase it from the map...
        m_nodes.erase(i);
    }
}



const XalanDOMString&
XercesDocumentWrapper::getNodeName() const
{
    assert(m_navigator != 0);

    return m_navigator->getPooledString(m_xercesDocument->getNodeName());
}



const XalanDOMString&
XercesDocumentWrapper::getNodeValue() const
{
    assert(m_navigator != 0);

    return m_navigator->getPooledString(m_xercesDocument->getNodeValue());
}



XercesDocumentWrapper::NodeType
XercesDocumentWrapper::getNodeType() const
{
    return DOCUMENT_NODE;
}



XalanNode*
XercesDocumentWrapper::getParentNode() const
{
    return 0;
}



const XalanNodeList*
XercesDocumentWrapper::getChildNodes() const
{
    return &m_children;
}



XalanNode*
XercesDocumentWrapper::getFirstChild() const
{
    assert(m_navigator != 0);

    return m_navigator->getFirstChild(m_xercesDocument);
}



XalanNode*
XercesDocumentWrapper::getLastChild() const
{
    assert(m_navigator != 0);

    return m_navigator->getLastChild(m_xercesDocument);
}



XalanNode*
XercesDocumentWrapper::getPreviousSibling() const
{
    return 0;
}



XalanNode*
XercesDocumentWrapper::getNextSibling() const
{
    return 0;
}



const XalanNamedNodeMap*
XercesDocumentWrapper::getAttributes() const
{
    return 0;
}



XalanDocument*
XercesDocumentWrapper::getOwnerDocument() const
{
    return 0;
}



const XalanDOMString&
XercesDocumentWrapper::getNamespaceURI() const
{
    assert(m_navigator != 0);

    return m_navigator->getPooledString(m_xercesDocument->getNamespaceURI());
}



const XalanDOMString&
XercesDocumentWrapper::getPrefix() const
{
    assert(m_navigator != 0);

    return m_navigator->getPooledString(m_xercesDocument->getPrefix());
}



const XalanDOMString&
XercesDocumentWrapper::getLocalName() const
{
    assert(m_navigator != 0);

    return m_navigator->getPooledString(m_xercesDocument->getLocalName());
}



bool
XercesDocumentWrapper::isIndexed() const
{
    return m_indexValid;
}



XercesDocumentWrapper::IndexType
XercesDocumentWrapper::getIndex() const
{
    assert(m_navigator != 0);
    assert(m_navigator->getIndex() == 1);

    return m_navigator->getIndex();
}



XalanElement*
XercesDocumentWrapper::getDocumentElement() const
{
    // If we're working in mapping mode, m_documentElement will
    // be null, so we'll have to map the node...
    return m_documentElement != 0 ? m_documentElement : mapNode(m_xercesDocument->getDocumentElement());
}



XalanElement*
XercesDocumentWrapper::getElementById(const XalanDOMString&     elementId) const
{
    const DOMNodeType* const    theXercesNode =
        m_xercesDocument->getElementById(elementId.c_str());

    if (theXercesNode == 0)
    {
        return 0;
    }
    else
    {
        return static_cast<XalanElement*>(mapNode(theXercesNode));
    }
}



void
XercesDocumentWrapper::buildWrapperNodes()
{
    const DOMNodeType*  theStartChild = m_xercesDocument->getFirstChild();

    if (theStartChild != 0)
    {
        assert(m_navigator != 0);

        m_navigator->setIndex(1);
        m_navigator->setFirstChild(0);

        BuildWrapperTreeWalker  theTreeWalker(
                this,
                m_navigator,
                2,
                m_buildMaps);

        theTreeWalker.traverse(theStartChild, m_xercesDocument);
    }

    // OK, now set m_documentElement...
    XalanNode*  theChild = m_navigator->getFirstChild();

    while(theChild != 0 && theChild->getNodeType() != XalanNode::ELEMENT_NODE)
    {
        theChild = theChild->getNextSibling();
    }

    m_documentElement = static_cast<XalanElement*>(theChild);

    m_indexValid = true;

    m_mappingMode = false;
}



XercesDocumentWrapper::BuildWrapperTreeWalker::BuildWrapperTreeWalker(
            XercesDocumentWrapper*              theDocument,
            XercesWrapperNavigator*             theDocumentNavigator,
            IndexType                           theStartIndex,
            bool                                theBuildMapsFlag) :
    m_document(theDocument),
    m_currentIndex(theStartIndex),
    m_parentNavigatorStack(theDocument->getMemoryManager()),
    m_siblingNavigatorStack(theDocument->getMemoryManager()),
    m_buildMaps(theBuildMapsFlag)
{
    assert(theDocument != 0 && theDocumentNavigator != 0);

    // Reserve some space...
    m_parentNavigatorStack.reserve(100);
    m_parentNavigatorStack.reserve(100);

    // The document navigator is the last navigator on the stack...
    m_parentNavigatorStack.push_back(NavigatorStackEntryType(theDocumentNavigator, theDocument));

    // There is no previous sibling...
    m_siblingNavigatorStack.push_back(NavigatorStackEntryType(0, 0));
}



XercesDocumentWrapper::BuildWrapperTreeWalker::~BuildWrapperTreeWalker()
{
}



bool
XercesDocumentWrapper::BuildWrapperTreeWalker::startNode(const DOMNodeType*     node)
{
    XercesWrapperNavigator*     theWrapperNodeNavigator;

    XalanNode* const    theWrapperNode =
        m_document->createWrapperNode(
                node,
                m_currentIndex,
                m_buildMaps,
                &theWrapperNodeNavigator);
    assert(theWrapperNodeNavigator != 0);

    assert(m_parentNavigatorStack.empty() == false);
    assert(m_siblingNavigatorStack.empty() == false);

    // Get the two navigators...
    NavigatorStackEntryType&    theParentEntry = m_parentNavigatorStack.back();
    NavigatorStackEntryType&    theSiblingEntry = m_siblingNavigatorStack.back();

    theWrapperNodeNavigator->setParentNode(theParentEntry.m_node);

    // If the first child has not been set, then set it
    // now...
    if (theParentEntry.m_navigator->getFirstChild() == 0)
    {
        assert(theSiblingEntry.m_node == 0);

        theParentEntry.m_navigator->setFirstChild(theWrapperNode);
    }

    // Always set the last child...
    theParentEntry.m_navigator->setLastChild(theWrapperNode);

    theWrapperNodeNavigator->setPreviousSibling(theSiblingEntry.m_node);

    if (theSiblingEntry.m_navigator != 0)
    {
        theSiblingEntry.m_navigator->setNextSibling(theWrapperNode);
    }

    // Build an entry for the stacks...
    const NavigatorStackEntryType   theCurrentEntry(theWrapperNodeNavigator, theWrapperNode);

    // My child nodes will now be visited, so push the current
    // context on the parent stack...
    m_parentNavigatorStack.push_back(theCurrentEntry);

    // My siblings will also need to know about me as well...
    m_siblingNavigatorStack.push_back(theCurrentEntry);

    // This will serve to mark the sibling context for my first child,
    // since it has no previous sibling.  This will be popped off
    // when endNode() is called.
    m_siblingNavigatorStack.push_back(NavigatorStackEntryType(0, 0));

    // Finally, increment the index counter...
    ++m_currentIndex;

    if (node->getNodeType() == DOMNodeType::DOCUMENT_TYPE_NODE)
    {
        // Special case for doctype -- we have to build its entities...
        const DOMDocumentType_Type* const   theDoctype =
            static_cast<const DOMDocumentType_Type*>(node);

        const DOMNamedNodeMapType* const    theEntities =
            theDoctype->getEntities();

        const XalanSize_t   theLength =
            theEntities->getLength();

        for (XalanSize_t i = 0; i < theLength; ++i)
        {
            // Build it, but don't index it...
            m_document->createWrapperNode(theEntities->item(i), m_currentIndex++, true);
        }
    }
    else if (node->getNodeType() == DOMNodeType::ELEMENT_NODE)
    {
        // Special case for element nodes -- we have to build the attributes...
        const DOMElementType* const     theElement =
            static_cast<const DOMElementType*>(node);

        const DOMNamedNodeMapType* const    theAttributes =
            theElement->getAttributes();
        assert(theAttributes != 0);

        const XalanSize_t   theLength =
            theAttributes->getLength();

        XercesWrapperNavigator* thePreviousAttrNavigator = 0;
        XalanNode*              thePreviousAttr = 0;

        for (XalanSize_t i = 0; i < theLength; ++i)
        {
            // Get the attribute from the node map...
            const DOMNodeType* const    theAttr = theAttributes->item(i);
            assert(theAttr != 0);

            XercesWrapperNavigator*     theCurrentAttrNavigator;

            // Create a wrapper node.
            XalanNode* const    theCurrentAttr =
                m_document->createWrapperNode(
                    theAttr,
                    m_currentIndex,
                    m_buildMaps,
                    &theCurrentAttrNavigator);
            assert(theCurrentAttr != 0 && theCurrentAttrNavigator != 0);

            // Set the parent node...
            theCurrentAttrNavigator->setParentNode(theWrapperNode);

            if (thePreviousAttr != 0)
            {
                assert(thePreviousAttrNavigator != 0);

                // Link in the previous attribute...
                theCurrentAttrNavigator->setPreviousSibling(thePreviousAttr);

                thePreviousAttrNavigator->setNextSibling(theCurrentAttr);
            }

            // Update the pointers so they point to this attribute...
            thePreviousAttr = theCurrentAttr;
            thePreviousAttrNavigator = theCurrentAttrNavigator;

            // Finally, increment the index...
            ++m_currentIndex;
        }
    }

    return false;
}



bool
XercesDocumentWrapper::BuildWrapperTreeWalker::endNode(const DOMNodeType*   /* node */)
{
    assert(m_parentNavigatorStack.empty() == false);
    assert(m_siblingNavigatorStack.empty() == false);

    // I have to pop my entry, since my children are finished...
    m_parentNavigatorStack.pop_back();

    // Pop any sibling navigators my child pushed...
    while(m_siblingNavigatorStack.back().m_navigator != 0)
    {
        assert(m_siblingNavigatorStack.back().m_node != 0);

        m_siblingNavigatorStack.pop_back();
    }

    // There must be a context marker...
    assert(m_siblingNavigatorStack.back().m_navigator == 0 &&
           m_siblingNavigatorStack.back().m_node == 0);

    // Pop the context marker...
    m_siblingNavigatorStack.pop_back();

    return false;
}



const XalanDOMString&
XercesDocumentWrapper::getPooledString(const XalanDOMString&    theString) const
{
    return m_stringPool->get(theString);
}



const XalanDOMString&
XercesDocumentWrapper::getPooledString(
            const XalanDOMChar*         theString,
            XalanDOMString::size_type   theLength) const
{
    return m_stringPool->get(theString, theLength);
}



}
