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 }