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