GME  13
DOMTreeWalkerImpl.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: DOMTreeWalkerImpl.cpp 671894 2008-06-26 13:29:21Z borisk $
00020  */
00021 
00022 #include "DOMTreeWalkerImpl.hpp"
00023 #include "DOMDocumentImpl.hpp"
00024 
00025 #include <xercesc/dom/DOMDocument.hpp>
00026 #include <xercesc/dom/DOMException.hpp>
00027 
00028 XERCES_CPP_NAMESPACE_BEGIN
00029 
00031 DOMTreeWalkerImpl::DOMTreeWalkerImpl (
00032                                 DOMNode* root,
00033                                 DOMNodeFilter::ShowType whatToShow,
00034                                 DOMNodeFilter* nodeFilter,
00035                                 bool expandEntityRef)
00036 :   fWhatToShow(whatToShow),
00037     fNodeFilter(nodeFilter),
00038     fCurrentNode(root),
00039     fRoot(root),
00040     fExpandEntityReferences(expandEntityRef)
00041 {
00042 }
00043 
00044 
00045 DOMTreeWalkerImpl::DOMTreeWalkerImpl (const DOMTreeWalkerImpl& twi)
00046 :   DOMTreeWalker(twi),
00047     fWhatToShow(twi.fWhatToShow),
00048     fNodeFilter(twi.fNodeFilter),
00049     fCurrentNode(twi.fCurrentNode),
00050     fRoot(twi.fRoot),
00051     fExpandEntityReferences(twi.fExpandEntityReferences)
00052 {
00053 }
00054 
00055 
00056 DOMTreeWalkerImpl& DOMTreeWalkerImpl::operator= (const DOMTreeWalkerImpl& twi) {
00057     if (this != &twi)
00058     {
00059         fCurrentNode            = twi.fCurrentNode;
00060         fRoot                   = twi.fRoot;
00061         fWhatToShow             = twi.fWhatToShow;
00062         fNodeFilter             = twi.fNodeFilter;
00063                 fExpandEntityReferences = twi.fExpandEntityReferences;
00064     }
00065 
00066     return *this;
00067 }
00068 
00069 
00070 
00072 DOMNode* DOMTreeWalkerImpl::getRoot () {
00073     return fRoot;
00074 }
00075 
00076 
00078 DOMNodeFilter::ShowType DOMTreeWalkerImpl::getWhatToShow () {
00079     return fWhatToShow;
00080 }
00081 
00082 
00084 DOMNodeFilter* DOMTreeWalkerImpl::getFilter () {
00085     return fNodeFilter;
00086 }
00087 
00089 bool DOMTreeWalkerImpl::getExpandEntityReferences() {
00090     return fExpandEntityReferences;
00091 }
00092 
00093 
00094 
00096 DOMNode* DOMTreeWalkerImpl::getCurrentNode () {
00097 
00098     return fCurrentNode;
00099 }
00100 
00101 
00103 void DOMTreeWalkerImpl::setCurrentNode (DOMNode* node) {
00104 
00105     if (!node)
00106         throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMTreeWalkerMemoryManager);
00107 
00108     fCurrentNode = node;
00109 }
00110 
00111 
00116 DOMNode* DOMTreeWalkerImpl::parentNode () {
00117 
00118     if (!fCurrentNode) return 0;
00119 
00120     DOMNode* node = getParentNode(fCurrentNode);
00121     if (node != 0) {
00122         fCurrentNode = node;
00123     }
00124     return node;
00125 
00126 }
00127 
00128 
00133 DOMNode* DOMTreeWalkerImpl::firstChild () {
00134 
00135     if (!fCurrentNode) return 0;
00136 
00137     if(!fExpandEntityReferences && fCurrentNode->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
00138         return 0;
00139 
00140     DOMNode* node = getFirstChild(fCurrentNode);
00141 
00142     if (node != 0) {
00143         fCurrentNode = node;
00144     }
00145     return node;
00146 }
00147 
00148 
00153 DOMNode* DOMTreeWalkerImpl::lastChild () {
00154 
00155     if (!fCurrentNode) return 0;
00156 
00157     if(!fExpandEntityReferences && fCurrentNode->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
00158         return 0;
00159 
00160     DOMNode* node = getLastChild(fCurrentNode);
00161     if (node != 0) {
00162         fCurrentNode = node;
00163     }
00164     return node;
00165 }
00166 
00167 
00173 DOMNode* DOMTreeWalkerImpl::previousSibling () {
00174 
00175     if (!fCurrentNode) return 0;
00176 
00177     DOMNode* node = getPreviousSibling(fCurrentNode);
00178     if (node != 0) {
00179         fCurrentNode = node;
00180     }
00181     return node;
00182 }
00183 
00184 
00190 DOMNode* DOMTreeWalkerImpl::nextSibling () {
00191 
00192     if (!fCurrentNode) return 0;
00193 
00194     DOMNode* node = getNextSibling(fCurrentNode);
00195     if (node != 0) {
00196         fCurrentNode = node;
00197     }
00198     return node;
00199 }
00200 
00201 
00207 DOMNode* DOMTreeWalkerImpl::previousNode () {
00208 
00209     if (!fCurrentNode) return 0;
00210 
00211     // get sibling
00212     DOMNode* node = getPreviousSibling(fCurrentNode);
00213     if (node == 0) {
00214         node = getParentNode(fCurrentNode);
00215         if ( node != 0) {
00216             fCurrentNode = node;
00217         }
00218         return node;
00219     }
00220     else {
00221 
00222         // get the lastChild of result.
00223         DOMNode* lastChild  = getLastChild(node);
00224 
00225         // if there is a lastChild which passes filters return it.
00226         if (lastChild != 0) {
00227             fCurrentNode = lastChild;
00228         }
00229         else {
00230             fCurrentNode = node;
00231         }
00232         return fCurrentNode;
00233     }
00234 }
00235 
00236 
00242 DOMNode* DOMTreeWalkerImpl::nextNode () {
00243 
00244     if (!fCurrentNode) return 0;
00245 
00246     DOMNode* node = getFirstChild(fCurrentNode);
00247 
00248     if (node != 0) {
00249         fCurrentNode = node;
00250         return node;
00251     }
00252     else {
00253 
00254         node = getNextSibling(fCurrentNode);
00255 
00256         if (node != 0) {
00257             fCurrentNode = node;
00258             return node;
00259         }
00260         else {
00261 
00262             // return parent's 1st sibling.
00263             DOMNode* parent = getParentNode(fCurrentNode);
00264             while ( parent != 0) {
00265                 node = getNextSibling(parent);
00266                 if (node != 0) {
00267                     fCurrentNode = node;
00268                     return node;
00269                 } else {
00270                     parent = getParentNode(parent);
00271                 }
00272             }
00273             return node;
00274         }
00275     }
00276 }
00277 
00278 
00285 DOMNode* DOMTreeWalkerImpl::getParentNode (DOMNode* node) {
00286 
00287     if (!node || node == fRoot) return 0;
00288 
00289     DOMNode* newNode = node->getParentNode();
00290     if (!newNode)  return 0;
00291 
00292     short accept = acceptNode(newNode);
00293 
00294     if (accept == DOMNodeFilter::FILTER_ACCEPT)
00295         return newNode;
00296 
00297     return getParentNode(newNode);
00298 
00299 }
00300 
00301 
00308 DOMNode* DOMTreeWalkerImpl::getNextSibling (DOMNode* node) {
00309 
00310     if (!node || node == fRoot) return 0;
00311 
00312     DOMNode* newNode = node->getNextSibling();
00313     if (!newNode) {
00314 
00315         newNode = node->getParentNode();
00316 
00317         if (!newNode || node == fRoot)  return 0;
00318 
00319         short parentAccept = acceptNode(newNode);
00320 
00321         if (parentAccept == DOMNodeFilter::FILTER_SKIP) {
00322             return getNextSibling(newNode);
00323         }
00324 
00325         return 0;
00326     }
00327 
00328     short accept = acceptNode(newNode);
00329 
00330     if (accept == DOMNodeFilter::FILTER_ACCEPT)
00331         return newNode;
00332     else
00333     if (accept == DOMNodeFilter::FILTER_SKIP) {
00334         DOMNode* fChild =  getFirstChild(newNode);
00335         if (!fChild && !newNode->hasChildNodes()) {
00336             return getNextSibling(newNode);
00337         }
00338         return fChild;
00339     }
00340     return getNextSibling(newNode);
00341 
00342 }
00343 
00344 
00351 DOMNode* DOMTreeWalkerImpl::getPreviousSibling (DOMNode* node) {
00352 
00353     if (!node || node == fRoot) return 0;
00354 
00355     DOMNode* newNode = node->getPreviousSibling();
00356     if (!newNode) {
00357 
00358         newNode = node->getParentNode();
00359         if (!newNode || node == fRoot)  return 0;
00360 
00361         short parentAccept = acceptNode(newNode);
00362 
00363         if (parentAccept == DOMNodeFilter::FILTER_SKIP) {
00364             return getPreviousSibling(newNode);
00365         }
00366 
00367         return 0;
00368     }
00369 
00370     short accept = acceptNode(newNode);
00371 
00372     if (accept == DOMNodeFilter::FILTER_ACCEPT)
00373         return newNode;
00374     else
00375     if (accept == DOMNodeFilter::FILTER_SKIP) {
00376         DOMNode* fChild =  getLastChild(newNode);
00377         if (!fChild && !newNode->hasChildNodes()) {
00378             return getPreviousSibling(newNode);
00379         }
00380         return fChild;
00381     }
00382     return getPreviousSibling(newNode);
00383 
00384 }
00385 
00386 
00393 DOMNode* DOMTreeWalkerImpl::getFirstChild (DOMNode* node) {
00394 
00395     if (!node) return 0;
00396 
00397     if(!fExpandEntityReferences && node->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
00398         return 0;
00399 
00400     DOMNode* newNode = node->getFirstChild();
00401     if (!newNode)  return 0;
00402 
00403     short accept = acceptNode(newNode);
00404 
00405     if (accept == DOMNodeFilter::FILTER_ACCEPT)
00406         return newNode;
00407     else
00408     if (accept == DOMNodeFilter::FILTER_SKIP
00409         && newNode->hasChildNodes())
00410     {
00411         return getFirstChild(newNode);
00412     }
00413     return getNextSibling(newNode);
00414 
00415 }
00416 
00417 
00424 DOMNode* DOMTreeWalkerImpl::getLastChild (DOMNode* node) {
00425 
00426     if (!node) return 0;
00427 
00428     if(!fExpandEntityReferences && node->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
00429         return 0;
00430 
00431     DOMNode* newNode = node->getLastChild();
00432     if (!newNode)  return 0;
00433 
00434     short accept = acceptNode(newNode);
00435 
00436     if (accept == DOMNodeFilter::FILTER_ACCEPT)
00437         return newNode;
00438     else
00439     if (accept == DOMNodeFilter::FILTER_SKIP
00440         && newNode->hasChildNodes())
00441     {
00442         return getLastChild(newNode);
00443     }
00444     return getPreviousSibling(newNode);
00445 
00446 }
00447 
00448 
00451 short DOMTreeWalkerImpl::acceptNode (DOMNode* node) {
00452 
00453     if (fNodeFilter == 0) {
00454         if ( ( fWhatToShow & (1 << (node->getNodeType() - 1))) != 0)
00455         {
00456             return DOMNodeFilter::FILTER_ACCEPT;
00457         }
00458         else
00459         {
00460             return DOMNodeFilter::FILTER_SKIP;
00461         }
00462     } else {
00463         // REVISIT: This logic is unclear from the spec!
00464         if ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0 ) {
00465             return fNodeFilter->acceptNode(node);
00466         } else {
00467             // what to show has failed!
00468             if (fNodeFilter->acceptNode(node) == DOMNodeFilter::FILTER_REJECT) {
00469                 return DOMNodeFilter::FILTER_REJECT;
00470             } else {
00471                 return DOMNodeFilter::FILTER_SKIP;
00472             }
00473         }
00474     }
00475 }
00476 
00477 
00478 void DOMTreeWalkerImpl::release()
00479 {
00480     // for performance reason, do not recycle pointer
00481     // chance that this is allocated again and again is not usual
00482 }
00483 
00484 XERCES_CPP_NAMESPACE_END