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