1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /*
6  * Licensed to the Apache Software Foundation (ASF) under one or more
7  * contributor license agreements.  See the NOTICE file distributed with
8  * this work for additional information regarding copyright ownership.
9  * The ASF licenses this file to You under the Apache License, Version 2.0
10  * (the "License"); you may not use this file except in compliance with
11  * the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 package com.sun.org.apache.xerces.internal.dom;
23 
24 import org.w3c.dom.DOMException;
25 import org.w3c.dom.Node;
26 import org.w3c.dom.traversal.NodeFilter;
27 import org.w3c.dom.traversal.TreeWalker;
28 
29 /** This class implements the TreeWalker interface.
30  *
31  * @xerces.internal
32  *
33  */
34 
35 public class TreeWalkerImpl implements TreeWalker {
36 
37     //
38     // Data
39     //
40 
41     /** When TRUE, the children of entites references are returned in the iterator. */
42     private boolean fEntityReferenceExpansion = false;
43     /** The whatToShow mask. */
44     int fWhatToShow = NodeFilter.SHOW_ALL;
45     /** The NodeFilter reference. */
46     NodeFilter fNodeFilter;
47     /** The current Node. */
48     Node fCurrentNode;
49     /** The root Node. */
50     Node fRoot;
51 
52     //
53     // Implementation Note: No state is kept except the data above
54     // (fWhatToShow, fNodeFilter, fCurrentNode, fRoot) such that
55     // setters could be created for these data values and the
56     // implementation will still work.
57 
58 
59     //
60     // Constructor
61     //
62 
63     /** Public constructor */
TreeWalkerImpl(Node root, int whatToShow, NodeFilter nodeFilter, boolean entityReferenceExpansion)64     public TreeWalkerImpl(Node root,
65                           int whatToShow,
66                           NodeFilter nodeFilter,
67                           boolean entityReferenceExpansion) {
68         fCurrentNode = root;
69         fRoot = root;
70         fWhatToShow = whatToShow;
71         fNodeFilter = nodeFilter;
72         fEntityReferenceExpansion = entityReferenceExpansion;
73     }
74 
getRoot()75     public Node getRoot() {
76         return fRoot;
77     }
78 
79     /** Return the whatToShow value */
getWhatToShow()80     public int                getWhatToShow() {
81         return fWhatToShow;
82     }
83 
setWhatShow(int whatToShow)84     public void setWhatShow(int whatToShow){
85         fWhatToShow = whatToShow;
86     }
87     /** Return the NodeFilter */
getFilter()88     public NodeFilter         getFilter() {
89         return fNodeFilter;
90     }
91 
92     /** Return whether children entity references are included in the iterator. */
getExpandEntityReferences()93     public boolean            getExpandEntityReferences() {
94         return fEntityReferenceExpansion;
95     }
96 
97     /** Return the current Node. */
getCurrentNode()98     public Node               getCurrentNode() {
99         return fCurrentNode;
100     }
101     /** Return the current Node. */
setCurrentNode(Node node)102     public void               setCurrentNode(Node node) {
103         if (node == null) {
104             String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
105               throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
106         }
107 
108         fCurrentNode = node;
109     }
110 
111     /** Return the parent Node from the current node,
112      *  after applying filter, whatToshow.
113      *  If result is not null, set the current Node.
114      */
parentNode()115     public Node               parentNode() {
116 
117         if (fCurrentNode == null) return null;
118 
119         Node node = getParentNode(fCurrentNode);
120         if (node !=null) {
121             fCurrentNode = node;
122         }
123         return node;
124 
125     }
126 
127     /** Return the first child Node from the current node,
128      *  after applying filter, whatToshow.
129      *  If result is not null, set the current Node.
130      */
firstChild()131     public Node               firstChild() {
132 
133         if (fCurrentNode == null) return null;
134 
135         Node node = getFirstChild(fCurrentNode);
136         if (node !=null) {
137             fCurrentNode = node;
138         }
139         return node;
140     }
141     /** Return the last child Node from the current node,
142      *  after applying filter, whatToshow.
143      *  If result is not null, set the current Node.
144      */
lastChild()145     public Node               lastChild() {
146 
147         if (fCurrentNode == null) return null;
148 
149         Node node = getLastChild(fCurrentNode);
150         if (node !=null) {
151             fCurrentNode = node;
152         }
153         return node;
154     }
155 
156     /** Return the previous sibling Node from the current node,
157      *  after applying filter, whatToshow.
158      *  If result is not null, set the current Node.
159      */
previousSibling()160     public Node               previousSibling() {
161 
162         if (fCurrentNode == null) return null;
163 
164         Node node = getPreviousSibling(fCurrentNode);
165         if (node !=null) {
166             fCurrentNode = node;
167         }
168         return node;
169     }
170 
171     /** Return the next sibling Node from the current node,
172      *  after applying filter, whatToshow.
173      *  If result is not null, set the current Node.
174      */
nextSibling()175     public Node               nextSibling(){
176         if (fCurrentNode == null) return null;
177 
178         Node node = getNextSibling(fCurrentNode);
179         if (node !=null) {
180             fCurrentNode = node;
181         }
182         return node;
183     }
184 
185     /** Return the previous Node from the current node,
186      *  after applying filter, whatToshow.
187      *  If result is not null, set the current Node.
188      */
previousNode()189     public Node               previousNode() {
190         Node result;
191 
192         if (fCurrentNode == null) return null;
193 
194         // get sibling
195         result = getPreviousSibling(fCurrentNode);
196         if (result == null) {
197             result = getParentNode(fCurrentNode);
198             if (result != null) {
199                 fCurrentNode = result;
200                 return fCurrentNode;
201             }
202             return null;
203         }
204 
205         // get the lastChild of result.
206         Node lastChild  = getLastChild(result);
207 
208         Node prev = lastChild ;
209         while (lastChild != null) {
210           prev = lastChild ;
211           lastChild = getLastChild(prev) ;
212         }
213 
214         lastChild = prev ;
215 
216         // if there is a lastChild which passes filters return it.
217         if (lastChild != null) {
218             fCurrentNode = lastChild;
219             return fCurrentNode;
220         }
221 
222         // otherwise return the previous sibling.
223         if (result != null) {
224             fCurrentNode = result;
225             return fCurrentNode;
226         }
227 
228         // otherwise return null.
229         return null;
230     }
231 
232     /** Return the next Node from the current node,
233      *  after applying filter, whatToshow.
234      *  If result is not null, set the current Node.
235      */
nextNode()236     public Node               nextNode() {
237 
238         if (fCurrentNode == null) return null;
239 
240         Node result = getFirstChild(fCurrentNode);
241 
242         if (result != null) {
243             fCurrentNode = result;
244             return result;
245         }
246 
247         result = getNextSibling(fCurrentNode);
248 
249         if (result != null) {
250             fCurrentNode = result;
251             return result;
252         }
253 
254         // return parent's 1st sibling.
255         Node parent = getParentNode(fCurrentNode);
256         while (parent != null) {
257             result = getNextSibling(parent);
258             if (result != null) {
259                 fCurrentNode = result;
260                 return result;
261             } else {
262                 parent = getParentNode(parent);
263             }
264         }
265 
266         // end , return null
267         return null;
268     }
269 
270     /** Internal function.
271      *  Return the parent Node, from the input node
272      *  after applying filter, whatToshow.
273      *  The current node is not consulted or set.
274      */
getParentNode(Node node)275     Node getParentNode(Node node) {
276 
277         if (node == null || node == fRoot) return null;
278 
279         Node newNode = node.getParentNode();
280         if (newNode == null)  return null;
281 
282         int accept = acceptNode(newNode);
283 
284         if (accept == NodeFilter.FILTER_ACCEPT)
285             return newNode;
286         else
287         //if (accept == NodeFilter.SKIP_NODE) // and REJECT too.
288         {
289             return getParentNode(newNode);
290         }
291 
292 
293     }
294 
295     /** Internal function.
296      *  Return the nextSibling Node, from the input node
297      *  after applying filter, whatToshow.
298      *  The current node is not consulted or set.
299      */
getNextSibling(Node node)300     Node getNextSibling(Node node) {
301                 return getNextSibling(node, fRoot);
302         }
303 
304     /** Internal function.
305      *  Return the nextSibling Node, from the input node
306      *  after applying filter, whatToshow.
307      *  NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
308      *  The current node is not consulted or set.
309      */
getNextSibling(Node node, Node root)310     Node getNextSibling(Node node, Node root) {
311 
312         if (node == null || node == root) return null;
313 
314         Node newNode = node.getNextSibling();
315         if (newNode == null) {
316 
317             newNode = node.getParentNode();
318 
319             if (newNode == null || newNode == root)  return null;
320 
321             int parentAccept = acceptNode(newNode);
322 
323             if (parentAccept==NodeFilter.FILTER_SKIP) {
324                 return getNextSibling(newNode, root);
325             }
326 
327             return null;
328         }
329 
330         int accept = acceptNode(newNode);
331 
332         if (accept == NodeFilter.FILTER_ACCEPT)
333             return newNode;
334         else
335         if (accept == NodeFilter.FILTER_SKIP) {
336             Node fChild = getFirstChild(newNode);
337             if (fChild == null) {
338                 return getNextSibling(newNode, root);
339             }
340             return fChild;
341         }
342         else
343         //if (accept == NodeFilter.REJECT_NODE)
344         {
345             return getNextSibling(newNode, root);
346         }
347 
348     } // getNextSibling(Node node) {
349 
350     /** Internal function.
351      *  Return the previous sibling Node, from the input node
352      *  after applying filter, whatToshow.
353      *  The current node is not consulted or set.
354      */
getPreviousSibling(Node node)355     Node getPreviousSibling(Node node) {
356                 return getPreviousSibling(node, fRoot);
357         }
358 
359     /** Internal function.
360      *  Return the previousSibling Node, from the input node
361      *  after applying filter, whatToshow.
362          *  NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
363      *  The current node is not consulted or set.
364      */
getPreviousSibling(Node node, Node root)365     Node getPreviousSibling(Node node, Node root) {
366 
367         if (node == null || node == root) return null;
368 
369         Node newNode = node.getPreviousSibling();
370         if (newNode == null) {
371 
372             newNode = node.getParentNode();
373             if (newNode == null || newNode == root)  return null;
374 
375             int parentAccept = acceptNode(newNode);
376 
377             if (parentAccept==NodeFilter.FILTER_SKIP) {
378                 return getPreviousSibling(newNode, root);
379             }
380 
381             return null;
382         }
383 
384         int accept = acceptNode(newNode);
385 
386         if (accept == NodeFilter.FILTER_ACCEPT)
387             return newNode;
388         else
389         if (accept == NodeFilter.FILTER_SKIP) {
390             Node fChild =  getLastChild(newNode);
391             if (fChild == null) {
392                 return getPreviousSibling(newNode, root);
393             }
394             return fChild;
395         }
396         else
397         //if (accept == NodeFilter.REJECT_NODE)
398         {
399             return getPreviousSibling(newNode, root);
400         }
401 
402     } // getPreviousSibling(Node node) {
403 
404     /** Internal function.
405      *  Return the first child Node, from the input node
406      *  after applying filter, whatToshow.
407      *  The current node is not consulted or set.
408      */
getFirstChild(Node node)409     Node getFirstChild(Node node) {
410         if (node == null) return null;
411 
412         if ( !fEntityReferenceExpansion
413              && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
414             return null;
415         Node newNode = node.getFirstChild();
416         if (newNode == null)  return null;
417         int accept = acceptNode(newNode);
418 
419         if (accept == NodeFilter.FILTER_ACCEPT)
420             return newNode;
421         else
422         if (accept == NodeFilter.FILTER_SKIP
423             && newNode.hasChildNodes())
424         {
425             Node fChild = getFirstChild(newNode);
426 
427             if (fChild == null) {
428                 return getNextSibling(newNode, node);
429             }
430             return fChild;
431         }
432         else
433         //if (accept == NodeFilter.REJECT_NODE)
434         {
435             return getNextSibling(newNode, node);
436         }
437 
438 
439     }
440 
441     /** Internal function.
442      *  Return the last child Node, from the input node
443      *  after applying filter, whatToshow.
444      *  The current node is not consulted or set.
445      */
getLastChild(Node node)446     Node getLastChild(Node node) {
447 
448         if (node == null) return null;
449 
450         if ( !fEntityReferenceExpansion
451              && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
452             return null;
453 
454         Node newNode = node.getLastChild();
455         if (newNode == null)  return null;
456 
457         int accept = acceptNode(newNode);
458 
459         if (accept == NodeFilter.FILTER_ACCEPT)
460             return newNode;
461         else
462         if (accept == NodeFilter.FILTER_SKIP
463             && newNode.hasChildNodes())
464         {
465             Node lChild = getLastChild(newNode);
466             if (lChild == null) {
467                 return getPreviousSibling(newNode, node);
468             }
469             return lChild;
470         }
471         else
472         //if (accept == NodeFilter.REJECT_NODE)
473         {
474             return getPreviousSibling(newNode, node);
475         }
476 
477 
478     }
479 
480     /** Internal function.
481      *  The node whatToShow and the filter are combined into one result. */
acceptNode(Node node)482     short acceptNode(Node node) {
483         /***
484          7.1.2.4. Filters and whatToShow flags
485 
486          Iterator and TreeWalker apply whatToShow flags before applying Filters. If a node is rejected by the
487          active whatToShow flags, a Filter will not be called to evaluate that node. When a node is rejected by
488          the active whatToShow flags, children of that node will still be considered, and Filters may be called to
489          evaluate them.
490          ***/
491 
492         if (fNodeFilter == null) {
493             if ( ( fWhatToShow & (1 << node.getNodeType()-1)) != 0) {
494                 return NodeFilter.FILTER_ACCEPT;
495             } else {
496                 return NodeFilter.FILTER_SKIP;
497             }
498         } else {
499             if ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 ) {
500                 return fNodeFilter.acceptNode(node);
501             } else {
502                 // What to show has failed. See above excerpt from spec.
503                 // Equivalent to FILTER_SKIP.
504                 return NodeFilter.FILTER_SKIP;
505             }
506         }
507     }
508 }
509