/*
 * 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: DOMTreeWalkerImpl.cpp 568078 2007-08-21 11:43:25Z amassari $
 */

#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,
                                unsigned long 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 */
unsigned long 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

