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