source: icXML/icXML-devel/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp @ 2722

Last change on this file since 2722 was 2722, checked in by cameron, 6 years ago

Original Xerces files with import mods for icxercesc

File size: 10.4 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: DOMNodeIteratorImpl.cpp 671894 2008-06-26 13:29:21Z borisk $
20 */
21
22//////////////////////////////////////////////////////////////////////
23// DOMNodeIteratorImpl.cpp: implementation of the DOMNodeIteratorImpl class.
24//
25//////////////////////////////////////////////////////////////////////
26
27#include "DOMNodeIteratorImpl.hpp"
28#include "DOMDocumentImpl.hpp"
29#include <xercesc/dom/DOMDocument.hpp>
30#include <xercesc/dom/DOMException.hpp>
31
32XERCES_CPP_NAMESPACE_BEGIN
33
34//////////////////////////////////////////////////////////////////////
35// Construction/Destruction
36//////////////////////////////////////////////////////////////////////
37
38DOMNodeIteratorImpl::DOMNodeIteratorImpl (DOMDocument* doc,
39                                    DOMNode* root,
40                                    DOMNodeFilter::ShowType whatToShow,
41                                    DOMNodeFilter* nodeFilter,
42                                    bool expandEntityRef)
43:   fRoot(root),
44    fDocument(doc),
45    fWhatToShow(whatToShow),
46    fNodeFilter(nodeFilter),
47    fExpandEntityReferences(expandEntityRef),
48    fDetached(false),
49    fCurrentNode(0),
50    fForward(true)
51{
52
53}
54
55
56DOMNodeIteratorImpl::DOMNodeIteratorImpl ( const DOMNodeIteratorImpl& toCopy)
57    : DOMNodeIterator(toCopy),
58    fRoot(toCopy.fRoot),
59    fDocument(toCopy.fDocument),
60    fWhatToShow(toCopy.fWhatToShow),
61    fNodeFilter(toCopy.fNodeFilter),
62    fExpandEntityReferences(toCopy.fExpandEntityReferences),
63    fDetached(toCopy.fDetached),
64    fCurrentNode(toCopy.fCurrentNode),
65    fForward(toCopy.fForward)
66{
67}
68
69
70DOMNodeIteratorImpl& DOMNodeIteratorImpl::operator= (const DOMNodeIteratorImpl& other) {
71    fRoot                   = other.fRoot;
72    fCurrentNode            = other.fRoot;
73    fWhatToShow             = other.fWhatToShow;
74    fNodeFilter             = other.fNodeFilter;
75    fForward                = other.fForward;
76    fDetached               = other.fDetached;
77    fExpandEntityReferences = other.fExpandEntityReferences;
78    fDocument               = other.fDocument;
79    return *this;
80}
81
82DOMNodeIteratorImpl::~DOMNodeIteratorImpl ()
83{
84        fDetached = false;
85}
86
87
88void DOMNodeIteratorImpl::detach ()
89{
90        fDetached = true;
91   ((DOMDocumentImpl *)fDocument)->removeNodeIterator(this);
92}
93
94
95DOMNode* DOMNodeIteratorImpl::getRoot() {
96    return fRoot;
97}
98
99
100// Implementation Note: Note that the iterator looks at whatToShow
101// and filter values at each call, and therefore one _could_ add
102// setters for these values and alter them while iterating!
103
104/** Return the whatToShow value */
105
106DOMNodeFilter::ShowType DOMNodeIteratorImpl::getWhatToShow () {
107    return fWhatToShow;
108}
109
110
111/** Return the filter */
112
113DOMNodeFilter* DOMNodeIteratorImpl::getFilter () {
114    return fNodeFilter;
115}
116
117/** Get the expandEntity reference flag. */
118bool DOMNodeIteratorImpl::getExpandEntityReferences()
119{
120    return fExpandEntityReferences;
121}
122
123/** Return the next DOMNode* in the Iterator. The node is the next node in
124 *  depth-first order which also passes the filter, and whatToShow.
125 *  A 0 return means either that
126 */
127
128DOMNode* DOMNodeIteratorImpl::nextNode () {
129        if (fDetached)
130                throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager);
131
132    // if root is 0 there is no next node->
133    if (!fRoot)
134                        return 0;
135
136    DOMNode* aNextNode = fCurrentNode;
137    bool accepted = false; // the next node has not been accepted.
138
139    while (!accepted) {
140
141        // if last direction is not forward, repeat node->
142        if (!fForward && (aNextNode != 0)) {
143            //System.out.println("nextNode():!fForward:"+fCurrentNode.getNodeName());
144            aNextNode = fCurrentNode;
145        } else {
146        // else get the next node via depth-first
147            aNextNode = nextNode(aNextNode, true);
148        }
149
150        fForward = true; //REVIST: should direction be set forward before 0 check?
151
152        // nothing in the list. return 0.
153        if (!aNextNode) return 0;
154
155        // does node pass the filters and whatToShow?
156        accepted = acceptNode(aNextNode);
157        if (accepted) {
158            // if so, then the node is the current node->
159            fCurrentNode = aNextNode;
160            return fCurrentNode;
161        }
162    }
163
164    // no nodes, or no accepted nodes.
165    return 0;
166}
167
168
169/** Return the previous Node in the Iterator. The node is the next node in
170 *  _backwards_ depth-first order which also passes the filter, and whatToShow.
171 */
172
173DOMNode* DOMNodeIteratorImpl::previousNode () {
174        if (fDetached)
175                throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager);
176
177    // if the root is 0, or the current node is 0, return 0.
178    if (!fRoot || !fCurrentNode) return 0;
179
180    DOMNode* aPreviousNode = fCurrentNode;
181    bool accepted = false;
182
183    while (!accepted) {
184
185        if (fForward && (aPreviousNode != 0)) {
186            //repeat last node->
187            aPreviousNode = fCurrentNode;
188        } else {
189            // get previous node in backwards depth first order.
190            aPreviousNode = previousNode(aPreviousNode);
191        }
192
193        // we are going backwards
194        fForward = false;
195
196        // if the new previous node is 0, we're at head or past the root,
197        // so return 0.
198        if (!aPreviousNode) return 0;
199
200        // check if node passes filters and whatToShow.
201        accepted = acceptNode(aPreviousNode);
202        if (accepted) {
203            // if accepted, update the current node, and return it.
204            fCurrentNode = aPreviousNode;
205            return fCurrentNode;
206        }
207    }
208    // there are no nodes?
209    return 0;
210}
211
212
213/** The node is accepted if it passes the whatToShow and the filter. */
214bool DOMNodeIteratorImpl::acceptNode (DOMNode* node) {
215        if (fDetached)
216                throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager);
217
218    if (fNodeFilter == 0) {
219        return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0);
220    } else {
221        return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0)
222            && fNodeFilter->acceptNode(node) == DOMNodeFilter::FILTER_ACCEPT;
223    }
224}
225
226
227/** Return node, if matches or any parent if matches. */
228DOMNode* DOMNodeIteratorImpl::matchNodeOrParent (DOMNode* node) {
229
230    for (DOMNode* n = fCurrentNode; n != fRoot; n = n->getParentNode()) {
231        if (node == n) return n;
232    }
233
234    return 0;
235}
236
237
238/** The method nextNode(DOMNode, bool) returns the next node
239 *  from the actual DOM tree.
240 *
241 *  The bool visitChildren determines whether to visit the children.
242 *  The result is the nextNode.
243 */
244
245DOMNode* DOMNodeIteratorImpl::nextNode (DOMNode* node, bool visitChildren) {
246        if (fDetached)
247                throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager);
248
249    if (!node) return fRoot;
250
251    DOMNode* result = 0;
252    // only check children if we visit children.
253    if (visitChildren) {
254        //if hasChildren, return 1st child.
255        if ((fExpandEntityReferences || node->getNodeType()!=DOMNode::ENTITY_REFERENCE_NODE) &&
256            node->hasChildNodes()) {
257            result = node->getFirstChild();
258            return result;
259        }
260    }
261
262    // if hasSibling, return sibling
263    if (node != fRoot) {
264        result = node->getNextSibling();
265        if (result != 0) return result;
266
267
268        // return parent's 1st sibling.
269        DOMNode* parent = node->getParentNode();
270        while ((parent != 0) && parent != fRoot) {
271            result = parent->getNextSibling();
272            if (result != 0) {
273                return result;
274            } else {
275                parent = parent->getParentNode();
276            }
277
278        } // while (parent != 0 && parent != fRoot) {
279    }
280    // end of list, return 0
281    return 0;
282}
283
284
285/** The method previousNode(DOMNode) returns the previous node
286 *  from the actual DOM tree.
287 */
288
289DOMNode* DOMNodeIteratorImpl::previousNode (DOMNode* node) {
290        if (fDetached)
291                throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager);
292
293    DOMNode* result = 0;
294
295    // if we're at the root, return 0.
296    if (node == fRoot)
297                        return 0;
298
299    // get sibling
300    result = node->getPreviousSibling();
301    if (!result) {
302        //if 1st sibling, return parent
303        result = node->getParentNode();
304        return result;
305    }
306
307    // if sibling has children, keep getting last child of child.
308    if (result->hasChildNodes()) {
309        while ((fExpandEntityReferences || result->getNodeType()!=DOMNode::ENTITY_REFERENCE_NODE) &&
310               result->hasChildNodes()) {
311            result = result->getLastChild();
312        }
313    }
314
315    return result;
316}
317
318
319/** Fix-up the iterator on a remove. Called by DOM or otherwise,
320 *  before an actual DOM remove.
321 */
322
323void DOMNodeIteratorImpl::removeNode (DOMNode* node) {
324        if (fDetached)
325                throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager);
326
327    // Implementation note: Fix-up means setting the current node properly
328    // after a remove.
329
330    if (!node) return;
331
332    DOMNode* deleted = matchNodeOrParent(node);
333
334    if (!deleted) return;
335
336    if (fForward) {
337        fCurrentNode = previousNode(deleted);
338    } else
339    // if (!fForward)
340    {
341        DOMNode* next = nextNode(deleted, false);
342        if (next != 0) {
343            // normal case: there _are_ nodes following this in the iterator.
344            fCurrentNode = next;
345        } else {
346            // the last node in the iterator is to be removed,
347            // so we set the current node to be the previous one.
348            fCurrentNode = previousNode(deleted);
349            fForward = true;
350        }
351
352    }
353
354}
355
356
357void DOMNodeIteratorImpl::release()
358{
359    detach();
360
361    // for performance reason, do not recycle pointer
362    // chance that this is allocated again and again is not usual
363}
364
365XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.