/*
 * 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.
 */

/*
 * $Id$
 */

#include "DOMTreeWalkerImpl.hpp"
#include "DOMDocumentImpl.hpp"

#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMException.hpp>

XERCES_CPP_NAMESPACE_BEGIN

/** constructor */
DOMTreeWalkerImpl::DOMTreeWalkerImpl (
                                DOMNode* root,
                                DOMNodeFilter::ShowType whatToShow,
                                DOMNodeFilter* nodeFilter,
                                bool expandEntityRef)
:   fWhatToShow(whatToShow),
    fNodeFilter(nodeFilter),
    fCurrentNode(root),
    fRoot(root),
    fExpandEntityReferences(expandEntityRef)
{
}


DOMTreeWalkerImpl::DOMTreeWalkerImpl (const DOMTreeWalkerImpl& twi)
:   DOMTreeWalker(twi),
    fWhatToShow(twi.fWhatToShow),
    fNodeFilter(twi.fNodeFilter),
    fCurrentNode(twi.fCurrentNode),
    fRoot(twi.fRoot),
    fExpandEntityReferences(twi.fExpandEntityReferences)
{
}


DOMTreeWalkerImpl& DOMTreeWalkerImpl::operator= (const DOMTreeWalkerImpl& twi) {
    if (this != &twi)
    {
        fCurrentNode            = twi.fCurrentNode;
        fRoot                   = twi.fRoot;
        fWhatToShow             = twi.fWhatToShow;
        fNodeFilter             = twi.fNodeFilter;
		fExpandEntityReferences = twi.fExpandEntityReferences;
    }

    return *this;
}



/** Return the root node */
DOMNode* DOMTreeWalkerImpl::getRoot () {
    return fRoot;
}


/** Return the whatToShow value */
DOMNodeFilter::ShowType DOMTreeWalkerImpl::getWhatToShow () {
    return fWhatToShow;
}


/** Return the NodeFilter */
DOMNodeFilter* DOMTreeWalkerImpl::getFilter () {
    return fNodeFilter;
}

/** Get the expandEntity reference flag. */
bool DOMTreeWalkerImpl::getExpandEntityReferences() {
    return fExpandEntityReferences;
}



/** Return the current Node. */
DOMNode* DOMTreeWalkerImpl::getCurrentNode () {

    return fCurrentNode;
}


/** Return the current Node. */
void DOMTreeWalkerImpl::setCurrentNode (DOMNode* node) {

    if (!node)
        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMTreeWalkerMemoryManager);

    fCurrentNode = node;
}


/** Return the parent Node from the current node,
 *  after applying filter, whatToshow.
 *  If result is not null, set the current Node.
 */
DOMNode* DOMTreeWalkerImpl::parentNode () {

    if (!fCurrentNode) return 0;

    DOMNode* node = getParentNode(fCurrentNode);
    if (node != 0) {
        fCurrentNode = node;
    }
    return node;

}


/** Return the first child Node from the current node,
 *  after applying filter, whatToshow.
 *  If result is not null, set the current Node.
 */
DOMNode* DOMTreeWalkerImpl::firstChild () {

    if (!fCurrentNode) return 0;

    if(!fExpandEntityReferences && fCurrentNode->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
        return 0;

    DOMNode* node = getFirstChild(fCurrentNode);

    if (node != 0) {
        fCurrentNode = node;
    }
    return node;
}


/** Return the last child Node from the current node,
 *  after applying filter, whatToshow.
 *  If result is not null, set the current Node.
 */
DOMNode* DOMTreeWalkerImpl::lastChild () {

    if (!fCurrentNode) return 0;

    if(!fExpandEntityReferences && fCurrentNode->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
        return 0;

    DOMNode* node = getLastChild(fCurrentNode);
    if (node != 0) {
        fCurrentNode = node;
    }
    return node;
}


/** Return the previous sibling Node from the current node,
 *  after applying filter, whatToshow.
 *  If result is not null, set the current Node.
 */

DOMNode* DOMTreeWalkerImpl::previousSibling () {

    if (!fCurrentNode) return 0;

    DOMNode* node = getPreviousSibling(fCurrentNode);
    if (node != 0) {
        fCurrentNode = node;
    }
    return node;
}


/** Return the next sibling Node from the current node,
 *  after applying filter, whatToshow.
 *  If result is not null, set the current Node.
 */

DOMNode* DOMTreeWalkerImpl::nextSibling () {

    if (!fCurrentNode) return 0;

    DOMNode* node = getNextSibling(fCurrentNode);
    if (node != 0) {
        fCurrentNode = node;
    }
    return node;
}


/** Return the previous Node from the current node,
 *  after applying filter, whatToshow.
 *  If result is not null, set the current Node.
 */

DOMNode* DOMTreeWalkerImpl::previousNode () {

    if (!fCurrentNode) return 0;

    // get sibling
    DOMNode* node = getPreviousSibling(fCurrentNode);
    if (node == 0) {
        node = getParentNode(fCurrentNode);
        if ( node != 0) {
            fCurrentNode = node;
        }
        return node;
    }
    else {

        // get the lastChild of result.
        DOMNode* lastChild  = getLastChild(node);

        // if there is a lastChild which passes filters return it.
        if (lastChild != 0) {
            fCurrentNode = lastChild;
        }
        else {
            fCurrentNode = node;
        }
        return fCurrentNode;
    }
}


/** Return the next Node from the current node,
 *  after applying filter, whatToshow.
 *  If result is not null, set the current Node.
 */

DOMNode* DOMTreeWalkerImpl::nextNode () {

    if (!fCurrentNode) return 0;

    DOMNode* node = getFirstChild(fCurrentNode);

    if (node != 0) {
        fCurrentNode = node;
        return node;
    }
    else {

        node = getNextSibling(fCurrentNode);

        if (node != 0) {
            fCurrentNode = node;
            return node;
        }
        else {

            // return parent's 1st sibling.
            DOMNode* parent = getParentNode(fCurrentNode);
            while ( parent != 0) {
                node = getNextSibling(parent);
                if (node != 0) {
                    fCurrentNode = node;
                    return node;
                } else {
                    parent = getParentNode(parent);
                }
            }
            return node;
        }
    }
}


/** Internal function.
 *  Return the parent Node, from the input node
 *  after applying filter, whatToshow.
 *  The current node is not consulted or set.
 */

DOMNode* DOMTreeWalkerImpl::getParentNode (DOMNode* node) {

    if (!node || node == fRoot) return 0;

    DOMNode* newNode = node->getParentNode();
    if (!newNode)  return 0;

    short accept = acceptNode(newNode);

    if (accept == DOMNodeFilter::FILTER_ACCEPT)
        return newNode;

    return getParentNode(newNode);

}


/** Internal function.
 *  Return the nextSibling Node, from the input node
 *  after applying filter, whatToshow.
 *  The current node is not consulted or set.
 */

DOMNode* DOMTreeWalkerImpl::getNextSibling (DOMNode* node) {

    if (!node || node == fRoot) return 0;

    DOMNode* newNode = node->getNextSibling();
    if (!newNode) {

        newNode = node->getParentNode();

        if (!newNode || node == fRoot)  return 0;

        short parentAccept = acceptNode(newNode);

        if (parentAccept == DOMNodeFilter::FILTER_SKIP) {
            return getNextSibling(newNode);
        }

        return 0;
    }

    short accept = acceptNode(newNode);

    if (accept == DOMNodeFilter::FILTER_ACCEPT)
        return newNode;
    else
    if (accept == DOMNodeFilter::FILTER_SKIP) {
        DOMNode* fChild =  getFirstChild(newNode);
        if (!fChild && !newNode->hasChildNodes()) {
            return getNextSibling(newNode);
        }
        return fChild;
    }
    return getNextSibling(newNode);

}


/** Internal function.
 *  Return the previous sibling Node, from the input node
 *  after applying filter, whatToshow.
 *  The current node is not consulted or set.
 */

DOMNode* DOMTreeWalkerImpl::getPreviousSibling (DOMNode* node) {

    if (!node || node == fRoot) return 0;

    DOMNode* newNode = node->getPreviousSibling();
    if (!newNode) {

        newNode = node->getParentNode();
        if (!newNode || node == fRoot)  return 0;

        short parentAccept = acceptNode(newNode);

        if (parentAccept == DOMNodeFilter::FILTER_SKIP) {
            return getPreviousSibling(newNode);
        }

        return 0;
    }

    short accept = acceptNode(newNode);

    if (accept == DOMNodeFilter::FILTER_ACCEPT)
        return newNode;
    else
    if (accept == DOMNodeFilter::FILTER_SKIP) {
        DOMNode* fChild =  getLastChild(newNode);
        if (!fChild && !newNode->hasChildNodes()) {
            return getPreviousSibling(newNode);
        }
        return fChild;
    }
    return getPreviousSibling(newNode);

}


/** Internal function.
 *  Return the first child Node, from the input node
 *  after applying filter, whatToshow.
 *  The current node is not consulted or set.
 */

DOMNode* DOMTreeWalkerImpl::getFirstChild (DOMNode* node) {

    if (!node) return 0;

    if(!fExpandEntityReferences && node->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
        return 0;

    DOMNode* newNode = node->getFirstChild();
    if (!newNode)  return 0;

    short accept = acceptNode(newNode);

    if (accept == DOMNodeFilter::FILTER_ACCEPT)
        return newNode;
    else
    if (accept == DOMNodeFilter::FILTER_SKIP
        && newNode->hasChildNodes())
    {
        return getFirstChild(newNode);
    }
    return getNextSibling(newNode);

}


/** Internal function.
 *  Return the last child Node, from the input node
 *  after applying filter, whatToshow.
 *  The current node is not consulted or set.
 */

DOMNode* DOMTreeWalkerImpl::getLastChild (DOMNode* node) {

    if (!node) return 0;

    if(!fExpandEntityReferences && node->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
        return 0;

    DOMNode* newNode = node->getLastChild();
    if (!newNode)  return 0;

    short accept = acceptNode(newNode);

    if (accept == DOMNodeFilter::FILTER_ACCEPT)
        return newNode;
    else
    if (accept == DOMNodeFilter::FILTER_SKIP
        && newNode->hasChildNodes())
    {
        return getLastChild(newNode);
    }
    return getPreviousSibling(newNode);

}


/** The node is accepted if it passes the whatToShow and the filter. */

short DOMTreeWalkerImpl::acceptNode (DOMNode* node) {

    if (fNodeFilter == 0) {
        if ( ( fWhatToShow & (1 << (node->getNodeType() - 1))) != 0)
        {
            return DOMNodeFilter::FILTER_ACCEPT;
        }
        else
        {
            return DOMNodeFilter::FILTER_SKIP;
        }
    } else {
        // REVISIT: This logic is unclear from the spec!
        if ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0 ) {
            return fNodeFilter->acceptNode(node);
        } else {
            // what to show has failed!
            if (fNodeFilter->acceptNode(node) == DOMNodeFilter::FILTER_REJECT) {
                return DOMNodeFilter::FILTER_REJECT;
            } else {
                return DOMNodeFilter::FILTER_SKIP;
            }
        }
    }
}


void DOMTreeWalkerImpl::release()
{
    // for performance reason, do not recycle pointer
    // chance that this is allocated again and again is not usual
}

XERCES_CPP_NAMESPACE_END
