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 }