View Javadoc
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  package org.apache.commons.jxpath.ri.model.dom;
19  
20  import org.apache.commons.jxpath.ri.compiler.NodeTest;
21  import org.apache.commons.jxpath.ri.model.NodeIterator;
22  import org.apache.commons.jxpath.ri.model.NodePointer;
23  import org.w3c.dom.Node;
24  
25  /**
26   * An iterator of children of a DOM Node.
27   */
28  public class DOMNodeIterator implements NodeIterator {
29  
30      private final NodePointer parent;
31      private final NodeTest nodeTest;
32      private final Node node;
33      private Node child;
34      private final boolean reverse;
35      private int position;
36  
37      /**
38       * Constructs a new DOMNodeIterator.
39       *
40       * @param parent    parent pointer
41       * @param nodeTest  test
42       * @param reverse   whether to iterate in reverse
43       * @param startWith starting pointer
44       */
45      public DOMNodeIterator(final NodePointer parent, final NodeTest nodeTest, final boolean reverse, final NodePointer startWith) {
46          this.parent = parent;
47          this.node = (Node) parent.getNode();
48          if (startWith != null) {
49              this.child = (Node) startWith.getNode();
50          }
51          this.nodeTest = nodeTest;
52          this.reverse = reverse;
53      }
54  
55      @Override
56      public NodePointer getNodePointer() {
57          if (position == 0) {
58              setPosition(1);
59          }
60          return child == null ? null : new DOMNodePointer(parent, child);
61      }
62  
63      @Override
64      public int getPosition() {
65          return position;
66      }
67  
68      /**
69       * Sets the next position.
70       *
71       * @return whether valid
72       */
73      private boolean next() {
74          position++;
75          if (!reverse) {
76              if (position == 1 && child == null) {
77                  child = node.getFirstChild();
78              } else {
79                  child = child.getNextSibling();
80              }
81              while (child != null && !testChild()) {
82                  child = child.getNextSibling();
83              }
84          } else {
85              if (position == 1 && child == null) {
86                  child = node.getLastChild();
87              } else {
88                  child = child.getPreviousSibling();
89              }
90              while (child != null && !testChild()) {
91                  child = child.getPreviousSibling();
92              }
93          }
94          return child != null;
95      }
96  
97      /**
98       * Sets the previous position.
99       *
100      * @return whether valid
101      */
102     private boolean previous() {
103         position--;
104         if (!reverse) {
105             if (position == 0) {
106                 child = null;
107             } else if (child == null) {
108                 child = node.getLastChild();
109             } else {
110                 child = child.getPreviousSibling();
111             }
112             while (child != null && !testChild()) {
113                 child = child.getPreviousSibling();
114             }
115         } else {
116             child = child.getNextSibling();
117             while (child != null && !testChild()) {
118                 child = child.getNextSibling();
119             }
120         }
121         return child != null;
122     }
123 
124     @Override
125     public boolean setPosition(final int position) {
126         while (this.position < position) {
127             if (!next()) {
128                 return false;
129             }
130         }
131         while (this.position > position) {
132             if (!previous()) {
133                 return false;
134             }
135         }
136         return true;
137     }
138 
139     /**
140      * Test child.
141      *
142      * @return result of the test
143      */
144     private boolean testChild() {
145         return DOMNodePointer.testNode(child, nodeTest);
146     }
147 }