GME
13
|
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: DOMNodeIteratorImpl.cpp 671894 2008-06-26 13:29:21Z borisk $ 00020 */ 00021 00023 // DOMNodeIteratorImpl.cpp: implementation of the DOMNodeIteratorImpl class. 00024 // 00026 00027 #include "DOMNodeIteratorImpl.hpp" 00028 #include "DOMDocumentImpl.hpp" 00029 #include <xercesc/dom/DOMDocument.hpp> 00030 #include <xercesc/dom/DOMException.hpp> 00031 00032 XERCES_CPP_NAMESPACE_BEGIN 00033 00035 // Construction/Destruction 00037 00038 DOMNodeIteratorImpl::DOMNodeIteratorImpl (DOMDocument* doc, 00039 DOMNode* root, 00040 DOMNodeFilter::ShowType whatToShow, 00041 DOMNodeFilter* nodeFilter, 00042 bool expandEntityRef) 00043 : fRoot(root), 00044 fDocument(doc), 00045 fWhatToShow(whatToShow), 00046 fNodeFilter(nodeFilter), 00047 fExpandEntityReferences(expandEntityRef), 00048 fDetached(false), 00049 fCurrentNode(0), 00050 fForward(true) 00051 { 00052 00053 } 00054 00055 00056 DOMNodeIteratorImpl::DOMNodeIteratorImpl ( const DOMNodeIteratorImpl& toCopy) 00057 : DOMNodeIterator(toCopy), 00058 fRoot(toCopy.fRoot), 00059 fDocument(toCopy.fDocument), 00060 fWhatToShow(toCopy.fWhatToShow), 00061 fNodeFilter(toCopy.fNodeFilter), 00062 fExpandEntityReferences(toCopy.fExpandEntityReferences), 00063 fDetached(toCopy.fDetached), 00064 fCurrentNode(toCopy.fCurrentNode), 00065 fForward(toCopy.fForward) 00066 { 00067 } 00068 00069 00070 DOMNodeIteratorImpl& DOMNodeIteratorImpl::operator= (const DOMNodeIteratorImpl& other) { 00071 fRoot = other.fRoot; 00072 fCurrentNode = other.fRoot; 00073 fWhatToShow = other.fWhatToShow; 00074 fNodeFilter = other.fNodeFilter; 00075 fForward = other.fForward; 00076 fDetached = other.fDetached; 00077 fExpandEntityReferences = other.fExpandEntityReferences; 00078 fDocument = other.fDocument; 00079 return *this; 00080 } 00081 00082 DOMNodeIteratorImpl::~DOMNodeIteratorImpl () 00083 { 00084 fDetached = false; 00085 } 00086 00087 00088 void DOMNodeIteratorImpl::detach () 00089 { 00090 fDetached = true; 00091 ((DOMDocumentImpl *)fDocument)->removeNodeIterator(this); 00092 } 00093 00094 00095 DOMNode* DOMNodeIteratorImpl::getRoot() { 00096 return fRoot; 00097 } 00098 00099 00100 // Implementation Note: Note that the iterator looks at whatToShow 00101 // and filter values at each call, and therefore one _could_ add 00102 // setters for these values and alter them while iterating! 00103 00106 DOMNodeFilter::ShowType DOMNodeIteratorImpl::getWhatToShow () { 00107 return fWhatToShow; 00108 } 00109 00110 00113 DOMNodeFilter* DOMNodeIteratorImpl::getFilter () { 00114 return fNodeFilter; 00115 } 00116 00118 bool DOMNodeIteratorImpl::getExpandEntityReferences() 00119 { 00120 return fExpandEntityReferences; 00121 } 00122 00128 DOMNode* DOMNodeIteratorImpl::nextNode () { 00129 if (fDetached) 00130 throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); 00131 00132 // if root is 0 there is no next node-> 00133 if (!fRoot) 00134 return 0; 00135 00136 DOMNode* aNextNode = fCurrentNode; 00137 bool accepted = false; // the next node has not been accepted. 00138 00139 while (!accepted) { 00140 00141 // if last direction is not forward, repeat node-> 00142 if (!fForward && (aNextNode != 0)) { 00143 //System.out.println("nextNode():!fForward:"+fCurrentNode.getNodeName()); 00144 aNextNode = fCurrentNode; 00145 } else { 00146 // else get the next node via depth-first 00147 aNextNode = nextNode(aNextNode, true); 00148 } 00149 00150 fForward = true; //REVIST: should direction be set forward before 0 check? 00151 00152 // nothing in the list. return 0. 00153 if (!aNextNode) return 0; 00154 00155 // does node pass the filters and whatToShow? 00156 accepted = acceptNode(aNextNode); 00157 if (accepted) { 00158 // if so, then the node is the current node-> 00159 fCurrentNode = aNextNode; 00160 return fCurrentNode; 00161 } 00162 } 00163 00164 // no nodes, or no accepted nodes. 00165 return 0; 00166 } 00167 00168 00173 DOMNode* DOMNodeIteratorImpl::previousNode () { 00174 if (fDetached) 00175 throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); 00176 00177 // if the root is 0, or the current node is 0, return 0. 00178 if (!fRoot || !fCurrentNode) return 0; 00179 00180 DOMNode* aPreviousNode = fCurrentNode; 00181 bool accepted = false; 00182 00183 while (!accepted) { 00184 00185 if (fForward && (aPreviousNode != 0)) { 00186 //repeat last node-> 00187 aPreviousNode = fCurrentNode; 00188 } else { 00189 // get previous node in backwards depth first order. 00190 aPreviousNode = previousNode(aPreviousNode); 00191 } 00192 00193 // we are going backwards 00194 fForward = false; 00195 00196 // if the new previous node is 0, we're at head or past the root, 00197 // so return 0. 00198 if (!aPreviousNode) return 0; 00199 00200 // check if node passes filters and whatToShow. 00201 accepted = acceptNode(aPreviousNode); 00202 if (accepted) { 00203 // if accepted, update the current node, and return it. 00204 fCurrentNode = aPreviousNode; 00205 return fCurrentNode; 00206 } 00207 } 00208 // there are no nodes? 00209 return 0; 00210 } 00211 00212 00214 bool DOMNodeIteratorImpl::acceptNode (DOMNode* node) { 00215 if (fDetached) 00216 throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); 00217 00218 if (fNodeFilter == 0) { 00219 return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0); 00220 } else { 00221 return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0) 00222 && fNodeFilter->acceptNode(node) == DOMNodeFilter::FILTER_ACCEPT; 00223 } 00224 } 00225 00226 00228 DOMNode* DOMNodeIteratorImpl::matchNodeOrParent (DOMNode* node) { 00229 00230 for (DOMNode* n = fCurrentNode; n != fRoot; n = n->getParentNode()) { 00231 if (node == n) return n; 00232 } 00233 00234 return 0; 00235 } 00236 00237 00245 DOMNode* DOMNodeIteratorImpl::nextNode (DOMNode* node, bool visitChildren) { 00246 if (fDetached) 00247 throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); 00248 00249 if (!node) return fRoot; 00250 00251 DOMNode* result = 0; 00252 // only check children if we visit children. 00253 if (visitChildren) { 00254 //if hasChildren, return 1st child. 00255 if ((fExpandEntityReferences || node->getNodeType()!=DOMNode::ENTITY_REFERENCE_NODE) && 00256 node->hasChildNodes()) { 00257 result = node->getFirstChild(); 00258 return result; 00259 } 00260 } 00261 00262 // if hasSibling, return sibling 00263 if (node != fRoot) { 00264 result = node->getNextSibling(); 00265 if (result != 0) return result; 00266 00267 00268 // return parent's 1st sibling. 00269 DOMNode* parent = node->getParentNode(); 00270 while ((parent != 0) && parent != fRoot) { 00271 result = parent->getNextSibling(); 00272 if (result != 0) { 00273 return result; 00274 } else { 00275 parent = parent->getParentNode(); 00276 } 00277 00278 } // while (parent != 0 && parent != fRoot) { 00279 } 00280 // end of list, return 0 00281 return 0; 00282 } 00283 00284 00289 DOMNode* DOMNodeIteratorImpl::previousNode (DOMNode* node) { 00290 if (fDetached) 00291 throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); 00292 00293 DOMNode* result = 0; 00294 00295 // if we're at the root, return 0. 00296 if (node == fRoot) 00297 return 0; 00298 00299 // get sibling 00300 result = node->getPreviousSibling(); 00301 if (!result) { 00302 //if 1st sibling, return parent 00303 result = node->getParentNode(); 00304 return result; 00305 } 00306 00307 // if sibling has children, keep getting last child of child. 00308 if (result->hasChildNodes()) { 00309 while ((fExpandEntityReferences || result->getNodeType()!=DOMNode::ENTITY_REFERENCE_NODE) && 00310 result->hasChildNodes()) { 00311 result = result->getLastChild(); 00312 } 00313 } 00314 00315 return result; 00316 } 00317 00318 00323 void DOMNodeIteratorImpl::removeNode (DOMNode* node) { 00324 if (fDetached) 00325 throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); 00326 00327 // Implementation note: Fix-up means setting the current node properly 00328 // after a remove. 00329 00330 if (!node) return; 00331 00332 DOMNode* deleted = matchNodeOrParent(node); 00333 00334 if (!deleted) return; 00335 00336 if (fForward) { 00337 fCurrentNode = previousNode(deleted); 00338 } else 00339 // if (!fForward) 00340 { 00341 DOMNode* next = nextNode(deleted, false); 00342 if (next != 0) { 00343 // normal case: there _are_ nodes following this in the iterator. 00344 fCurrentNode = next; 00345 } else { 00346 // the last node in the iterator is to be removed, 00347 // so we set the current node to be the previous one. 00348 fCurrentNode = previousNode(deleted); 00349 fForward = true; 00350 } 00351 00352 } 00353 00354 } 00355 00356 00357 void DOMNodeIteratorImpl::release() 00358 { 00359 detach(); 00360 00361 // for performance reason, do not recycle pointer 00362 // chance that this is allocated again and again is not usual 00363 } 00364 00365 XERCES_CPP_NAMESPACE_END