View Javadoc

1   /*
2    * Copyright 2005 John G. Wilson
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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              /* (non-Javadoc)
72              * @see java.util.Iterator#hasNext()
73              */
74              public boolean hasNext() {
75                  return this.childIter != null;
76              }
77  
78              /* (non-Javadoc)
79              * @see java.util.Iterator#next()
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              /* (non-Javadoc)
98              * @see java.util.Iterator#remove()
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                 /* (non-Javadoc)
150                 * @see org.codehaus.groovy.sandbox.util.slurpersupport.NodeIterator#getNextNode(java.util.Iterator)
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         // TODO Auto-generated method stub
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     /* (non-Javadoc)
234     * @see groovy.lang.Writable#writeTo(java.io.Writer)
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 }