1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jxpath.ri.model.jdom;
17
18 import java.util.Collections;
19 import java.util.List;
20
21 import org.apache.commons.jxpath.ri.compiler.NodeTest;
22 import org.apache.commons.jxpath.ri.model.NodeIterator;
23 import org.apache.commons.jxpath.ri.model.NodePointer;
24 import org.jdom.Document;
25 import org.jdom.Element;
26
27 /***
28 * An iterator of children of a JDOM Node.
29 *
30 * @author Dmitri Plotnikov
31 * @version $Revision: 1.6 $ $Date: 2004/02/29 14:17:40 $
32 */
33 public class JDOMNodeIterator implements NodeIterator {
34 private NodePointer parent;
35 private NodeTest nodeTest;
36
37 private boolean reverse;
38 private int position = 0;
39 private int index = 0;
40 private List children;
41 private Object child;
42
43 public JDOMNodeIterator(
44 NodePointer parent, NodeTest nodeTest,
45 boolean reverse, NodePointer startWith)
46 {
47 this.parent = parent;
48 if (startWith != null) {
49 this.child = startWith.getNode();
50 }
51
52 Object node = parent.getNode();
53 if (node instanceof Document) {
54 this.children = ((Document) node).getContent();
55 }
56 else if (node instanceof Element) {
57 this.children = ((Element) node).getContent();
58 }
59 else {
60 this.children = Collections.EMPTY_LIST;
61 }
62 this.nodeTest = nodeTest;
63 this.reverse = reverse;
64 }
65
66 public NodePointer getNodePointer() {
67 if (child == null) {
68 if (!setPosition(1)) {
69 return null;
70 }
71 position = 0;
72 }
73
74 return new JDOMNodePointer(parent, child);
75 }
76
77 public int getPosition() {
78 return position;
79 }
80
81 public boolean setPosition(int position) {
82 while (this.position < position) {
83 if (!next()) {
84 return false;
85 }
86 }
87 while (this.position > position) {
88 if (!previous()) {
89 return false;
90 }
91 }
92 return true;
93 }
94
95 /***
96 * This is actually never invoked during the normal evaluation
97 * of xpaths - an iterator is always going forward, never backwards.
98 * So, this is implemented only for completeness and perhaps for
99 * those who use these iterators outside of XPath evaluation.
100 */
101 private boolean previous() {
102 position--;
103 if (!reverse) {
104 while (--index >= 0) {
105 child = children.get(index);
106 if (testChild()) {
107 return true;
108 }
109 }
110 }
111 else {
112 for (; index < children.size(); index++) {
113 child = children.get(index);
114 if (testChild()) {
115 return true;
116 }
117 }
118 }
119 return false;
120 }
121
122 private boolean next() {
123 position++;
124 if (!reverse) {
125 if (position == 1) {
126 index = 0;
127 if (child != null) {
128 index = children.indexOf(child) + 1;
129 }
130 }
131 else {
132 index++;
133 }
134 for (; index < children.size(); index++) {
135 child = children.get(index);
136 if (testChild()) {
137 return true;
138 }
139 }
140 return false;
141 }
142 else {
143 if (position == 1) {
144 index = children.size() - 1;
145 if (child != null) {
146 index = children.indexOf(child) - 1;
147 }
148 }
149 else {
150 index--;
151 }
152 for (; index >= 0; index--) {
153 child = children.get(index);
154 if (testChild()) {
155 return true;
156 }
157 }
158 return false;
159 }
160 }
161
162 private boolean testChild() {
163 return JDOMNodePointer.testNode(parent, child, nodeTest);
164 }
165 }