001: /*
002: * The Apache Software License, Version 1.1
003: *
004: *
005: * Copyright (c) 1999 The Apache Software Foundation. All rights
006: * reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions and the following disclaimer in
017: * the documentation and/or other materials provided with the
018: * distribution.
019: *
020: * 3. The end-user documentation included with the redistribution,
021: * if any, must include the following acknowledgment:
022: * "This product includes software developed by the
023: * Apache Software Foundation (http://www.apache.org/)."
024: * Alternately, this acknowledgment may appear in the software itself,
025: * if and wherever such third-party acknowledgments normally appear.
026: *
027: * 4. The names "Xerces" and "Apache Software Foundation" must
028: * not be used to endorse or promote products derived from this
029: * software without prior written permission. For written
030: * permission, please contact apache@apache.org.
031: *
032: * 5. Products derived from this software may not be called "Apache",
033: * nor may "Apache" appear in their name, without prior written
034: * permission of the Apache Software Foundation.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: * ====================================================================
049: *
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the Apache Software Foundation and was
052: * originally based on software copyright (c) 1999, International
053: * Business Machines, Inc., http://www.apache.org. For more
054: * information on the Apache Software Foundation, please see
055: * <http://www.apache.org/>.
056: */
057:
058: package org.apache.xerces.dom;
059:
060: import org.w3c.dom.Node;
061: import org.w3c.dom.traversal.NodeFilter;
062: import org.w3c.dom.traversal.TreeWalker;
063:
064: /** This class implements the TreeWalker interface. */
065: public class TreeWalkerImpl implements TreeWalker {
066:
067: //
068: // Data
069: //
070:
071: /** When TRUE, the children of entites references are returned in the iterator. */
072: private boolean fEntityReferenceExpansion = false;
073: /** The whatToShow mask. */
074: int fWhatToShow = NodeFilter.SHOW_ALL;
075: /** The NodeFilter reference. */
076: NodeFilter fNodeFilter;
077: /** The current Node. */
078: Node fCurrentNode;
079: /** The root Node. */
080: Node fRoot;
081:
082: //
083: // Implementation Note: No state is kept except the data above
084: // (fWhatToShow, fNodeFilter, fCurrentNode, fRoot) such that
085: // setters could be created for these data values and the
086: // implementation will still work.
087:
088: //
089: // Constructor
090: //
091:
092: /** Public constructor */
093: public TreeWalkerImpl(Node root, int whatToShow,
094: NodeFilter nodeFilter, boolean entityReferenceExpansion) {
095: fCurrentNode = root;
096: fRoot = root;
097: fWhatToShow = whatToShow;
098: fNodeFilter = nodeFilter;
099: fEntityReferenceExpansion = entityReferenceExpansion;
100: }
101:
102: public Node getRoot() {
103: return fRoot;
104: }
105:
106: /** Return the whatToShow value */
107: public int getWhatToShow() {
108: return fWhatToShow;
109: }
110:
111: public void setWhatShow(int whatToShow) {
112: fWhatToShow = whatToShow;
113: }
114:
115: /** Return the NodeFilter */
116: public NodeFilter getFilter() {
117: return fNodeFilter;
118: }
119:
120: /** Return whether children entity references are included in the iterator. */
121: public boolean getExpandEntityReferences() {
122: return fEntityReferenceExpansion;
123: }
124:
125: /** Return the current Node. */
126: public Node getCurrentNode() {
127: return fCurrentNode;
128: }
129:
130: /** Return the current Node. */
131: public void setCurrentNode(Node node) {
132: fCurrentNode = node;
133: }
134:
135: /** Return the parent Node from the current node,
136: * after applying filter, whatToshow.
137: * If result is not null, set the current Node.
138: */
139: public Node parentNode() {
140:
141: if (fCurrentNode == null)
142: return null;
143:
144: Node node = getParentNode(fCurrentNode);
145: if (node != null) {
146: fCurrentNode = node;
147: }
148: return node;
149:
150: }
151:
152: /** Return the first child Node from the current node,
153: * after applying filter, whatToshow.
154: * If result is not null, set the current Node.
155: */
156: public Node firstChild() {
157:
158: if (fCurrentNode == null)
159: return null;
160:
161: Node node = getFirstChild(fCurrentNode);
162: if (node != null) {
163: fCurrentNode = node;
164: }
165: return node;
166: }
167:
168: /** Return the last child Node from the current node,
169: * after applying filter, whatToshow.
170: * If result is not null, set the current Node.
171: */
172: public Node lastChild() {
173:
174: if (fCurrentNode == null)
175: return null;
176:
177: Node node = getLastChild(fCurrentNode);
178: if (node != null) {
179: fCurrentNode = node;
180: }
181: return node;
182: }
183:
184: /** Return the previous sibling Node from the current node,
185: * after applying filter, whatToshow.
186: * If result is not null, set the current Node.
187: */
188: public Node previousSibling() {
189:
190: if (fCurrentNode == null)
191: return null;
192:
193: Node node = getPreviousSibling(fCurrentNode);
194: if (node != null) {
195: fCurrentNode = node;
196: }
197: return node;
198: }
199:
200: /** Return the next sibling Node from the current node,
201: * after applying filter, whatToshow.
202: * If result is not null, set the current Node.
203: */
204: public Node nextSibling() {
205: if (fCurrentNode == null)
206: return null;
207:
208: Node node = getNextSibling(fCurrentNode);
209: if (node != null) {
210: fCurrentNode = node;
211: }
212: return node;
213: }
214:
215: /** Return the previous Node from the current node,
216: * after applying filter, whatToshow.
217: * If result is not null, set the current Node.
218: */
219: public Node previousNode() {
220: Node result;
221:
222: if (fCurrentNode == null)
223: return null;
224:
225: // get sibling
226: result = getPreviousSibling(fCurrentNode);
227: if (result == null) {
228: result = getParentNode(fCurrentNode);
229: if (result != null) {
230: fCurrentNode = result;
231: return fCurrentNode;
232: }
233: return null;
234: }
235:
236: // get the lastChild of result.
237: Node lastChild = getLastChild(result);
238:
239: Node prev = lastChild;
240: while (lastChild != null) {
241: prev = lastChild;
242: lastChild = getLastChild(prev);
243: }
244:
245: lastChild = prev;
246:
247: // if there is a lastChild which passes filters return it.
248: if (lastChild != null) {
249: fCurrentNode = lastChild;
250: return fCurrentNode;
251: }
252:
253: // otherwise return the previous sibling.
254: if (result != null) {
255: fCurrentNode = result;
256: return fCurrentNode;
257: }
258:
259: // otherwise return null.
260: return null;
261: }
262:
263: /** Return the next Node from the current node,
264: * after applying filter, whatToshow.
265: * If result is not null, set the current Node.
266: */
267: public Node nextNode() {
268:
269: if (fCurrentNode == null)
270: return null;
271:
272: Node result = getFirstChild(fCurrentNode);
273:
274: if (result != null) {
275: fCurrentNode = result;
276: return result;
277: }
278:
279: result = getNextSibling(fCurrentNode);
280:
281: if (result != null) {
282: fCurrentNode = result;
283: return result;
284: }
285:
286: // return parent's 1st sibling.
287: Node parent = getParentNode(fCurrentNode);
288: while (parent != null) {
289: result = getNextSibling(parent);
290: if (result != null) {
291: fCurrentNode = result;
292: return result;
293: } else {
294: parent = getParentNode(parent);
295: }
296: }
297:
298: // end , return null
299: return null;
300: }
301:
302: /** Internal function.
303: * Return the parent Node, from the input node
304: * after applying filter, whatToshow.
305: * The current node is not consulted or set.
306: */
307: Node getParentNode(Node node) {
308:
309: if (node == null || node == fRoot)
310: return null;
311:
312: Node newNode = node.getParentNode();
313: if (newNode == null)
314: return null;
315:
316: int accept = acceptNode(newNode);
317:
318: if (accept == NodeFilter.FILTER_ACCEPT)
319: return newNode;
320: else
321: //if (accept == NodeFilter.SKIP_NODE) // and REJECT too.
322: {
323: return getParentNode(newNode);
324: }
325:
326: }
327:
328: /** Internal function.
329: * Return the nextSibling Node, from the input node
330: * after applying filter, whatToshow.
331: * The current node is not consulted or set.
332: */
333: Node getNextSibling(Node node) {
334: return getNextSibling(node, fRoot);
335: }
336:
337: /** Internal function.
338: * Return the nextSibling Node, from the input node
339: * after applying filter, whatToshow.
340: * NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
341: * The current node is not consulted or set.
342: */
343: Node getNextSibling(Node node, Node root) {
344:
345: if (node == null || node == root)
346: return null;
347:
348: Node newNode = node.getNextSibling();
349: if (newNode == null) {
350:
351: newNode = node.getParentNode();
352:
353: if (newNode == null || newNode == root)
354: return null;
355:
356: int parentAccept = acceptNode(newNode);
357:
358: if (parentAccept == NodeFilter.FILTER_SKIP) {
359: return getNextSibling(newNode, root);
360: }
361:
362: return null;
363: }
364:
365: int accept = acceptNode(newNode);
366:
367: if (accept == NodeFilter.FILTER_ACCEPT)
368: return newNode;
369: else if (accept == NodeFilter.FILTER_SKIP) {
370: Node fChild = getFirstChild(newNode);
371: if (fChild == null) {
372: return getNextSibling(newNode, root);
373: }
374: return fChild;
375: } else
376: //if (accept == NodeFilter.REJECT_NODE)
377: {
378: return getNextSibling(newNode, root);
379: }
380:
381: } // getNextSibling(Node node) {
382:
383: /** Internal function.
384: * Return the previous sibling Node, from the input node
385: * after applying filter, whatToshow.
386: * The current node is not consulted or set.
387: */
388: Node getPreviousSibling(Node node) {
389: return getPreviousSibling(node, fRoot);
390: }
391:
392: /** Internal function.
393: * Return the previousSibling Node, from the input node
394: * after applying filter, whatToshow.
395: * NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
396: * The current node is not consulted or set.
397: */
398: Node getPreviousSibling(Node node, Node root) {
399:
400: if (node == null || node == root)
401: return null;
402:
403: Node newNode = node.getPreviousSibling();
404: if (newNode == null) {
405:
406: newNode = node.getParentNode();
407: if (newNode == null || newNode == root)
408: return null;
409:
410: int parentAccept = acceptNode(newNode);
411:
412: if (parentAccept == NodeFilter.FILTER_SKIP) {
413: return getPreviousSibling(newNode, root);
414: }
415:
416: return null;
417: }
418:
419: int accept = acceptNode(newNode);
420:
421: if (accept == NodeFilter.FILTER_ACCEPT)
422: return newNode;
423: else if (accept == NodeFilter.FILTER_SKIP) {
424: Node fChild = getLastChild(newNode);
425: if (fChild == null) {
426: return getPreviousSibling(newNode, root);
427: }
428: return fChild;
429: } else
430: //if (accept == NodeFilter.REJECT_NODE)
431: {
432: return getPreviousSibling(newNode, root);
433: }
434:
435: } // getPreviousSibling(Node node) {
436:
437: /** Internal function.
438: * Return the first child Node, from the input node
439: * after applying filter, whatToshow.
440: * The current node is not consulted or set.
441: */
442: Node getFirstChild(Node node) {
443: if (node == null)
444: return null;
445:
446: if (!fEntityReferenceExpansion
447: && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
448: return null;
449: Node newNode = node.getFirstChild();
450: if (newNode == null)
451: return null;
452: int accept = acceptNode(newNode);
453:
454: if (accept == NodeFilter.FILTER_ACCEPT)
455: return newNode;
456: else if (accept == NodeFilter.FILTER_SKIP
457: && newNode.hasChildNodes()) {
458: Node fChild = getFirstChild(newNode);
459:
460: if (fChild == null) {
461: return getNextSibling(newNode, node);
462: }
463: return fChild;
464: } else
465: //if (accept == NodeFilter.REJECT_NODE)
466: {
467: return getNextSibling(newNode, node);
468: }
469:
470: }
471:
472: /** Internal function.
473: * Return the last child Node, from the input node
474: * after applying filter, whatToshow.
475: * The current node is not consulted or set.
476: */
477: Node getLastChild(Node node) {
478:
479: if (node == null)
480: return null;
481:
482: if (!fEntityReferenceExpansion
483: && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
484: return null;
485:
486: Node newNode = node.getLastChild();
487: if (newNode == null)
488: return null;
489:
490: int accept = acceptNode(newNode);
491:
492: if (accept == NodeFilter.FILTER_ACCEPT)
493: return newNode;
494: else if (accept == NodeFilter.FILTER_SKIP
495: && newNode.hasChildNodes()) {
496: Node lChild = getLastChild(newNode);
497: if (lChild == null) {
498: return getPreviousSibling(newNode, node);
499: }
500: return lChild;
501: } else
502: //if (accept == NodeFilter.REJECT_NODE)
503: {
504: return getPreviousSibling(newNode, node);
505: }
506:
507: }
508:
509: /** Internal function.
510: * The node whatToShow and the filter are combined into one result. */
511: short acceptNode(Node node) {
512: /***
513: 7.1.2.4. Filters and whatToShow flags
514:
515: Iterator and TreeWalker apply whatToShow flags before applying Filters. If a node is rejected by the
516: active whatToShow flags, a Filter will not be called to evaluate that node. When a node is rejected by
517: the active whatToShow flags, children of that node will still be considered, and Filters may be called to
518: evaluate them.
519: ***/
520:
521: if (fNodeFilter == null) {
522: if ((fWhatToShow & (1 << node.getNodeType() - 1)) != 0) {
523: return NodeFilter.FILTER_ACCEPT;
524: } else {
525: return NodeFilter.FILTER_SKIP;
526: }
527: } else {
528: if ((fWhatToShow & (1 << node.getNodeType() - 1)) != 0) {
529: return fNodeFilter.acceptNode(node);
530: } else {
531: // What to show has failed. See above excerpt from spec.
532: // Equivalent to FILTER_SKIP.
533: return NodeFilter.FILTER_SKIP;
534: }
535: }
536: }
537: }
|