1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package groovy.util.slurpersupport;
19
20 import groovy.lang.Buildable;
21 import groovy.lang.Closure;
22 import groovy.lang.GroovyObject;
23 import groovy.lang.GroovyRuntimeException;
24
25 import java.io.IOException;
26 import java.io.Writer;
27 import java.util.Iterator;
28 import java.util.Map;
29
30 import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
31
32 /***
33 * @author John Wilson
34 */
35
36 class NodeChildren extends GPathResult {
37 private int size = -1;
38
39 /***
40 * @param parent
41 * @param name
42 * @param namespacePrefix
43 * @param namespaceTagHints
44 */
45 public NodeChildren(final GPathResult parent, final String name, final String namespacePrefix, final Map namespaceTagHints) {
46 super(parent, name, namespacePrefix, namespaceTagHints);
47 }
48
49 /***
50 * @param parent
51 * @param name
52 * @param namespaceTagHints
53 */
54 public NodeChildren(final GPathResult parent, final String name, final Map namespaceTagHints) {
55 this(parent, name, "*", namespaceTagHints);
56 }
57
58 /***
59 * @param parent
60 * @param namespaceTagHints
61 */
62 public NodeChildren(final GPathResult parent, final Map namespaceTagHints) {
63 this(parent, "*", namespaceTagHints);
64 }
65
66 public Iterator childNodes() {
67 return new Iterator() {
68 private final Iterator iter = NodeChildren.this.parent.childNodes();
69 private Iterator childIter = nextChildIter();
70
71
72
73
74 public boolean hasNext() {
75 return this.childIter != null;
76 }
77
78
79
80
81 public Object next() {
82 while (this.childIter != null) {
83 try {
84 if (this.childIter.hasNext()) {
85 return this.childIter.next();
86 }
87 } finally {
88 if (!this.childIter.hasNext()) {
89 this.childIter = nextChildIter();
90 }
91 }
92 }
93
94 return null;
95 }
96
97
98
99
100 public void remove() {
101 throw new UnsupportedOperationException();
102 }
103
104 private Iterator nextChildIter() {
105 while (this.iter.hasNext()) {
106 final Node node = (Node) this.iter.next();
107
108 if (NodeChildren.this.name.equals(node.name())) {
109 final Iterator result = node.childNodes();
110
111 if (result.hasNext()) {
112 if ("*".equals(NodeChildren.this.namespacePrefix) ||
113 ("".equals(NodeChildren.this.namespacePrefix) && "".equals(node.namespaceURI())) ||
114 node.namespaceURI().equals(NodeChildren.this.namespaceMap.get(NodeChildren.this.namespacePrefix))) {
115 return result;
116 }
117 }
118 }
119 }
120
121 return null;
122 }
123 };
124 }
125
126 public Iterator iterator() {
127 return new Iterator() {
128 final Iterator iter = nodeIterator();
129
130 public boolean hasNext() {
131 return this.iter.hasNext();
132 }
133
134 public Object next() {
135 return new NodeChild((Node) this.iter.next(), NodeChildren.this.parent, NodeChildren.this.namespaceTagHints);
136 }
137
138 public void remove() {
139 throw new UnsupportedOperationException();
140 }
141 };
142 }
143
144 public Iterator nodeIterator() {
145 if ("*".equals(this.name)) {
146 return this.parent.childNodes();
147 } else {
148 return new NodeIterator(this.parent.childNodes()) {
149
150
151
152 protected Object getNextNode(Iterator iter) {
153 while (iter.hasNext()) {
154 final Node node = (Node) iter.next();
155
156 if (NodeChildren.this.name.equals(node.name())) {
157 if ("*".equals(NodeChildren.this.namespacePrefix) ||
158 ("".equals(NodeChildren.this.namespacePrefix) && "".equals(node.namespaceURI())) ||
159 node.namespaceURI().equals(NodeChildren.this.namespaceMap.get(NodeChildren.this.namespacePrefix))) {
160 return node;
161 }
162 }
163 }
164
165 return null;
166 }
167 };
168 }
169 }
170
171 public GPathResult parents() {
172
173 throw new GroovyRuntimeException("parents() not implemented yet");
174 }
175
176 public synchronized int size() {
177 if (this.size == -1) {
178 final Iterator iter = iterator();
179
180 this.size = 0;
181 while (iter.hasNext()) {
182 iter.next();
183 this.size++;
184 }
185 }
186
187 return this.size;
188 }
189
190 public String text() {
191 final StringBuffer buf = new StringBuffer();
192 final Iterator iter = nodeIterator();
193
194 while (iter.hasNext()) {
195 buf.append(((Node) iter.next()).text());
196 }
197
198 return buf.toString();
199 }
200
201 public GPathResult find(final Closure closure) {
202 final Iterator iter = iterator();
203
204 while (iter.hasNext()) {
205 final Object node = iter.next();
206
207 if (DefaultTypeTransformation.castToBoolean(closure.call(new Object[]{node}))) {
208 return (GPathResult) node;
209 }
210 }
211
212 return new NoChildren(this, this.name, this.namespaceTagHints);
213 }
214
215 public GPathResult findAll(final Closure closure) {
216 return new FilteredNodeChildren(this, closure, this.namespaceTagHints);
217 }
218
219 public void build(final GroovyObject builder) {
220 final Iterator iter = nodeIterator();
221
222 while (iter.hasNext()) {
223 final Object next = iter.next();
224
225 if (next instanceof Buildable) {
226 ((Buildable) next).build(builder);
227 } else {
228 ((Node) next).build(builder, this.namespaceMap, this.namespaceTagHints);
229 }
230 }
231 }
232
233
234
235
236 public Writer writeTo(final Writer out) throws IOException {
237 final Iterator iter = nodeIterator();
238
239 while (iter.hasNext()) {
240 ((Node) iter.next()).writeTo(out);
241 }
242
243 return out;
244 }
245
246 protected void replaceNode(final Closure newValue) {
247 final Iterator iter = iterator();
248
249 while (iter.hasNext()) {
250 final NodeChild result = (NodeChild)iter.next();
251 result.replaceNode(newValue);
252 }
253 }
254
255 protected void replaceBody(final Object newValue) {
256 final Iterator iter = iterator();
257
258 while (iter.hasNext()) {
259 final NodeChild result = (NodeChild)iter.next();
260 result.replaceBody(newValue);
261 }
262 }
263
264 protected void appendNode(final Object newValue) {
265 final Iterator iter = iterator();
266
267 while (iter.hasNext()) {
268 final NodeChild result = (NodeChild)iter.next();
269 result.appendNode(newValue);
270 }
271 }
272 }