View Javadoc

    1   /*
    2    * $Id: DOMCategory.java 4649 2007-01-02 14:26:37Z paulk $version Apr 25, 2004 5:18:30 PM $user Exp $
    3    *
    4    * Copyright 2003 (C) Sam Pullara. All Rights Reserved.
    5    *
    6    * Redistribution and use of this software and associated documentation
    7    * ("Software"), with or without modification, are permitted provided that the
    8    * following conditions are met: 1. Redistributions of source code must retain
    9    * copyright statements and notices. Redistributions must also contain a copy of
    10   * this document. 2. Redistributions in binary form must reproduce the above
    11   * copyright notice, this list of conditions and the following disclaimer in the
    12   * documentation and/or other materials provided with the distribution. 3. The
    13   * name "groovy" must not be used to endorse or promote products derived from
    14   * this Software without prior written permission of The Codehaus. For written
    15   * permission, please contact info@codehaus.org. 4. Products derived from this
    16   * Software may not be called "groovy" nor may "groovy" appear in their names
    17   * without prior written permission of The Codehaus. "groovy" is a registered
    18   * trademark of The Codehaus. 5. Due credit should be given to The Codehaus -
    19   * http://groovy.codehaus.org/
    20   *
    21   * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
    22   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    23   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    24   * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
    25   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    27   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    28   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    29   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31   *
    32   */
    33  package groovy.xml.dom;
    34
    35  import org.w3c.dom.*;
    36  import org.codehaus.groovy.runtime.DefaultGroovyMethods;
    37
    38  import java.util.Iterator;
    39  import java.util.List;
    40  import java.util.ArrayList;
    41  import java.util.Collection;
    42
    43  /***
    44   * @author sam
    45   * @author paulk
    46   */
    47  public class DOMCategory {
    48
    49      private static boolean trimWhitespace = true;
    50
    51      public static Object get(Object o, String elementName) {
    52          if (o instanceof Element) {
    53              return get((Element) o, elementName);
    54          }
    55          if (o instanceof NodeList) {
    56              return get((NodeList) o, elementName);
    57          }
    58          if (o instanceof NamedNodeMap) {
    59              return get((NamedNodeMap) o, elementName);
    60          }
    61          return null;
    62      }
    63
    64      private static Object get(Element element, String elementName) {
    65          return getAt(element, elementName);
    66      }
    67
    68      private static Object get(NodeList nodeList, String elementName) {
    69          return getAt(nodeList, elementName);
    70      }
    71
    72      private static Object get(NamedNodeMap nodeMap, String elementName) {
    73          return getAt(nodeMap, elementName);
    74      }
    75
    76      private static Object getAt(Element element, String elementName) {
    77          if ("..".equals(elementName)) {
    78              return parent(element);
    79          }
    80          if ("**".equals(elementName)) {
    81              return depthFirst(element);
    82          }
    83          if (elementName.startsWith("@")) {
    84              return element.getAttribute(elementName.substring(1));
    85          }
    86          return getChildElements(element, elementName);
    87      }
    88
    89      private static Object getAt(NodeList nodeList, String elementName) {
    90          List results = new ArrayList();
    91          for (int i = 0; i < nodeList.getLength(); i++) {
    92              Node node = nodeList.item(i);
    93              if (node instanceof Element) {
    94                  addResult(results, get(node, elementName));
    95              }
    96          }
    97          if (elementName.startsWith("@")) {
    98              return results;
    99          }
    100         return new NodeListsHolder(results);
    101     }
    102
    103     public static NamedNodeMap attributes(Element element) {
    104         return element.getAttributes();
    105     }
    106
    107     private static String getAt(NamedNodeMap namedNodeMap, String elementName) {
    108         Attr a = (Attr) namedNodeMap.getNamedItem(elementName);
    109         return a.getValue();
    110     }
    111
    112     public static int size(NamedNodeMap namedNodeMap) {
    113         return namedNodeMap.getLength();
    114     }
    115
    116     public static Node getAt(Node o, int i) {
    117         return nodeGetAt(o, i);
    118     }
    119
    120     public static Node getAt(NodeListsHolder o, int i) {
    121         return nodeGetAt(o, i);
    122     }
    123
    124     public static Node getAt(NodesHolder o, int i) {
    125         return nodeGetAt(o, i);
    126     }
    127
    128     private static Node nodeGetAt(Object o, int i) {
    129         if (o instanceof Element) {
    130             Node n = getAt((Element)o, i);
    131             if (n != null) return n;
    132         }
    133         if (o instanceof NodeList) {
    134             return getAt((NodeList)o, i);
    135         }
    136         return null;
    137     }
    138
    139     private static Node getAt(Element element, int i) {
    140         if (hasChildElements(element, "*")) {
    141             NodeList nodeList = getChildElements(element, "*");
    142             return nodeList.item(i);
    143         }
    144         return null;
    145     }
    146
    147     private static Node getAt(NodeList nodeList, int i) {
    148         if (i >= 0 && i < nodeList.getLength()) {
    149             return nodeList.item(i);
    150         }
    151         return null;
    152     }
    153
    154     public static String name(Element element) {
    155         return element.getNodeName();
    156     }
    157
    158     public static Node parent(Node node) {
    159         return node.getParentNode();
    160     }
    161
    162     public static String text(Object o) {
    163         if (o instanceof Element) {
    164             return text((Element) o);
    165         }
    166         if (o instanceof Node) {
    167             Node n = (Node) o;
    168             if (n.getNodeType() == Node.TEXT_NODE) {
    169                 return n.getNodeValue();
    170             }
    171         }
    172         if (o instanceof NodeList) {
    173             return text((NodeList) o);
    174         }
    175         return null;
    176     }
    177
    178     private static String text(Element element) {
    179         if (!element.hasChildNodes()) {
    180             return "";
    181         }
    182         if (element.getFirstChild().getNodeType() != Node.TEXT_NODE) {
    183             return "";
    184         }
    185         return element.getFirstChild().getNodeValue();
    186     }
    187
    188     private static String text(NodeList nodeList) {
    189         StringBuffer sb = new StringBuffer();
    190         for (int i = 0; i < nodeList.getLength(); i++) {
    191             sb.append(text(nodeList.item(i)));
    192         }
    193         return sb.toString();
    194     }
    195
    196     public static List list(NodeList self) {
    197         List answer = new ArrayList();
    198         Iterator it = DefaultGroovyMethods.iterator(self);
    199         while (it.hasNext()) {
    200             answer.add(it.next());
    201         }
    202         return answer;
    203     }
    204
    205     public static NodeList depthFirst(Element self) {
    206         List result = new ArrayList();
    207         result.add(createNodeList(self));
    208         result.add(self.getElementsByTagName("*"));
    209         return new NodeListsHolder(result);
    210     }
    211
    212     private static NodeList createNodeList(Element self) {
    213         List first = new ArrayList();
    214         first.add(self);
    215         return new NodesHolder(first);
    216     }
    217
    218     public static NodeList breadthFirst(Element self) {
    219         List result = new ArrayList();
    220         NodeList thisLevel = createNodeList(self);
    221         while (thisLevel.getLength() > 0) {
    222             result.add(thisLevel);
    223             thisLevel = getNextLevel(thisLevel);
    224         }
    225         return new NodeListsHolder(result);
    226     }
    227
    228     private static NodeList getNextLevel(NodeList thisLevel) {
    229         List result = new ArrayList();
    230         for (int i = 0; i < thisLevel.getLength(); i++) {
    231             Node n = thisLevel.item(i);
    232             if (n instanceof Element) {
    233                 result.add(getChildElements((Element) n, "*"));
    234             }
    235         }
    236         return new NodeListsHolder(result);
    237     }
    238
    239     public static NodeList children(Element self) {
    240         return getChildElements(self, "*");
    241     }
    242
    243     private static boolean hasChildElements(Element self, String elementName) {
    244         return getChildElements(self, elementName).getLength() > 0;
    245     }
    246
    247     private static NodeList getChildElements(Element self, String elementName) {
    248         List result = new ArrayList();
    249         NodeList nodeList = self.getChildNodes();
    250         for (int i = 0; i < nodeList.getLength(); i++) {
    251             Node node = nodeList.item(i);
    252             if (node.getNodeType() == Node.ELEMENT_NODE) {
    253                 Element child = (Element) node;
    254                 if ("*".equals(elementName) || child.getTagName().equals(elementName)) {
    255                     result.add(child);
    256                 }
    257             } else if (node.getNodeType() == Node.TEXT_NODE) {
    258                 String value = node.getNodeValue();
    259                 if (trimWhitespace) {
    260                     value = value.trim();
    261                 }
    262                 if ("*".equals(elementName) && value.length() > 0) {
    263                     node.setNodeValue(value);
    264                     result.add(node);
    265                 }
    266             }
    267         }
    268         return new NodesHolder(result);
    269     }
    270
    271     public static String toString(Object o) {
    272         if (o instanceof Node) {
    273             if (((Node) o).getNodeType() == Node.TEXT_NODE) {
    274                 return ((Node) o).getNodeValue();
    275             }
    276         }
    277         if (o instanceof NodeList) {
    278             return toString((NodeList) o);
    279         }
    280         return o.toString();
    281     }
    282
    283     private static String toString(NodeList self) {
    284         StringBuffer sb = new StringBuffer();
    285         sb.append("[");
    286         Iterator it = DefaultGroovyMethods.iterator(self);
    287         while (it.hasNext()) {
    288             if (sb.length() > 1) sb.append(", ");
    289             sb.append(it.next().toString());
    290         }
    291         sb.append("]");
    292         return sb.toString();
    293     }
    294
    295     public static int size(NodeList self) {
    296         return self.getLength();
    297     }
    298
    299     public static boolean isEmpty(NodeList self) {
    300         return size(self) == 0;
    301     }
    302
    303     private static void addResult(List results, Object result) {
    304         if (result != null) {
    305             if (result instanceof Collection) {
    306                 results.addAll((Collection) result);
    307             } else {
    308                 results.add(result);
    309             }
    310         }
    311     }
    312
    313     private static class NodeListsHolder implements NodeList {
    314         private List nodeLists;
    315
    316         private NodeListsHolder(List nodeLists) {
    317             this.nodeLists = nodeLists;
    318         }
    319
    320         public int getLength() {
    321             int length = 0;
    322             for (int i = 0; i < nodeLists.size(); i++) {
    323                 NodeList nl = (NodeList) nodeLists.get(i);
    324                 length += nl.getLength();
    325             }
    326             return length;
    327         }
    328
    329         public Node item(int index) {
    330             int relativeIndex = index;
    331             for (int i = 0; i < nodeLists.size(); i++) {
    332                 NodeList nl = (NodeList) nodeLists.get(i);
    333                 if (relativeIndex < nl.getLength()) {
    334                     return nl.item(relativeIndex);
    335                 }
    336                 relativeIndex -= nl.getLength();
    337             }
    338             return null;
    339         }
    340
    341         public String toString() {
    342             return DOMCategory.toString(this);
    343         }
    344     }
    345
    346     private static class NodesHolder implements NodeList {
    347         private List nodes;
    348
    349         private NodesHolder(List nodes) {
    350             this.nodes = nodes;
    351         }
    352
    353         public int getLength() {
    354             return nodes.size();
    355         }
    356
    357         public Node item(int index) {
    358             if (index < 0 || index >= getLength()) {
    359                 return null;
    360             }
    361             return (Node) nodes.get(index);
    362         }
    363     }
    364 }