-
Tinny Ng authored
git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@174151 13f79535-47bb-0310-9956-ffa450edef68
fffb1ef0
DOMTreeWalkerImpl.cpp 12.68 KiB
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Id$
*/
#include "DOMTreeWalkerImpl.hpp"
#include "DOMDocumentImpl.hpp"
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMException.hpp>
/** constructor */
DOMTreeWalkerImpl::DOMTreeWalkerImpl (
DOMNode* root,
unsigned long whatToShow,
DOMNodeFilter* nodeFilter,
bool expandEntityRef)
: fCurrentNode(root),
fRoot(root),
fWhatToShow(whatToShow),
fNodeFilter(nodeFilter),
fExpandEntityReferences(expandEntityRef)
{
}
DOMTreeWalkerImpl::DOMTreeWalkerImpl (const DOMTreeWalkerImpl& twi)
: fCurrentNode(twi.fCurrentNode),
fRoot(twi.fRoot),
fWhatToShow(twi.fWhatToShow),
fNodeFilter(twi.fNodeFilter),
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) {
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;
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;
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;
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;
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
}