001 /* 002 * $Id: DOMCategory.java 4201 2006-11-05 10:23:50Z paulk $version Apr 25, 2004 5:18:30 PM $user Exp $ 003 * 004 * Copyright 2003 (C) Sam Pullara. All Rights Reserved. 005 * 006 * Redistribution and use of this software and associated documentation 007 * ("Software"), with or without modification, are permitted provided that the 008 * following conditions are met: 1. Redistributions of source code must retain 009 * copyright statements and notices. Redistributions must also contain a copy of 010 * this document. 2. Redistributions in binary form must reproduce the above 011 * copyright notice, this list of conditions and the following disclaimer in the 012 * documentation and/or other materials provided with the distribution. 3. The 013 * name "groovy" must not be used to endorse or promote products derived from 014 * this Software without prior written permission of The Codehaus. For written 015 * permission, please contact info@codehaus.org. 4. Products derived from this 016 * Software may not be called "groovy" nor may "groovy" appear in their names 017 * without prior written permission of The Codehaus. "groovy" is a registered 018 * trademark of The Codehaus. 5. Due credit should be given to The Codehaus - 019 * http://groovy.codehaus.org/ 020 * 021 * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY 022 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 023 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 024 * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR 025 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 026 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 027 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 028 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 029 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 030 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 031 * 032 */ 033 package groovy.xml.dom; 034 035 import org.w3c.dom.*; 036 import org.codehaus.groovy.runtime.DefaultGroovyMethods; 037 038 import java.util.Iterator; 039 import java.util.List; 040 import java.util.ArrayList; 041 import java.util.Collection; 042 043 /** 044 * @author sam 045 * @author paulk 046 */ 047 public class DOMCategory { 048 049 private static boolean trimWhitespace = true; 050 051 public static Object get(Object o, String elementName) { 052 if (o instanceof Element) { 053 return get((Element) o, elementName); 054 } 055 if (o instanceof NodeList) { 056 return get((NodeList) o, elementName); 057 } 058 if (o instanceof NamedNodeMap) { 059 return get((NamedNodeMap) o, elementName); 060 } 061 return null; 062 } 063 064 private static Object get(Element element, String elementName) { 065 return getAt(element, elementName); 066 } 067 068 private static Object get(NodeList nodeList, String elementName) { 069 return getAt(nodeList, elementName); 070 } 071 072 private static Object get(NamedNodeMap nodeMap, String elementName) { 073 return getAt(nodeMap, elementName); 074 } 075 076 private static Object getAt(Element element, String elementName) { 077 if ("..".equals(elementName)) { 078 return parent(element); 079 } 080 if ("**".equals(elementName)) { 081 return depthFirst(element); 082 } 083 if (elementName.startsWith("@")) { 084 return element.getAttribute(elementName.substring(1)); 085 } 086 return getChildElements(element, elementName); 087 } 088 089 private static Object getAt(NodeList nodeList, String elementName) { 090 List results = new ArrayList(); 091 for (int i = 0; i < nodeList.getLength(); i++) { 092 Node node = nodeList.item(i); 093 if (node instanceof Element) { 094 addResult(results, get(node, elementName)); 095 } 096 } 097 if (elementName.startsWith("@")) { 098 return results; 099 } 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(Element element, int i) { 117 if (hasChildElements(element, "*")) { 118 NodeList nodeList = getChildElements(element, "*"); 119 return nodeList.item(i); 120 } 121 return null; 122 } 123 124 public static Node getAt(NodeList nodeList, int i) { 125 if (i >= 0 && i < nodeList.getLength()) { 126 return nodeList.item(i); 127 } 128 return null; 129 } 130 131 public static String name(Element element) { 132 return element.getNodeName(); 133 } 134 135 public static Node parent(Node node) { 136 return node.getParentNode(); 137 } 138 139 public static String text(Object o) { 140 if (o instanceof Element) { 141 return text((Element) o); 142 } 143 if (o instanceof Node) { 144 Node n = (Node) o; 145 if (n.getNodeType() == Node.TEXT_NODE) { 146 return n.getNodeValue(); 147 } 148 } 149 if (o instanceof NodeList) { 150 return text((NodeList) o); 151 } 152 return null; 153 } 154 155 private static String text(Element element) { 156 if (!element.hasChildNodes()) { 157 return ""; 158 } 159 if (element.getFirstChild().getNodeType() != Node.TEXT_NODE) { 160 return ""; 161 } 162 return element.getFirstChild().getNodeValue(); 163 } 164 165 private static String text(NodeList nodeList) { 166 StringBuffer sb = new StringBuffer(); 167 for (int i = 0; i < nodeList.getLength(); i++) { 168 sb.append(text(nodeList.item(i))); 169 } 170 return sb.toString(); 171 } 172 173 public static List list(NodeList self) { 174 List answer = new ArrayList(); 175 Iterator it = DefaultGroovyMethods.iterator(self); 176 while (it.hasNext()) { 177 answer.add(it.next()); 178 } 179 return answer; 180 } 181 182 public static NodeList depthFirst(Element self) { 183 List result = new ArrayList(); 184 result.add(createNodeList(self)); 185 result.add(self.getElementsByTagName("*")); 186 return new NodeListsHolder(result); 187 } 188 189 private static NodeList createNodeList(Element self) { 190 List first = new ArrayList(); 191 first.add(self); 192 return new NodesHolder(first); 193 } 194 195 public static NodeList breadthFirst(Element self) { 196 List result = new ArrayList(); 197 NodeList thisLevel = createNodeList(self); 198 while (thisLevel.getLength() > 0) { 199 result.add(thisLevel); 200 thisLevel = getNextLevel(thisLevel); 201 } 202 return new NodeListsHolder(result); 203 } 204 205 private static NodeList getNextLevel(NodeList thisLevel) { 206 List result = new ArrayList(); 207 for (int i = 0; i < thisLevel.getLength(); i++) { 208 Node n = thisLevel.item(i); 209 if (n instanceof Element) { 210 result.add(getChildElements((Element) n, "*")); 211 } 212 } 213 return new NodeListsHolder(result); 214 } 215 216 public static NodeList children(Element self) { 217 return getChildElements(self, "*"); 218 } 219 220 private static boolean hasChildElements(Element self, String elementName) { 221 return getChildElements(self, elementName).getLength() > 0; 222 } 223 224 private static NodeList getChildElements(Element self, String elementName) { 225 List result = new ArrayList(); 226 NodeList nodeList = self.getChildNodes(); 227 for (int i = 0; i < nodeList.getLength(); i++) { 228 Node node = nodeList.item(i); 229 if (node.getNodeType() == Node.ELEMENT_NODE) { 230 Element child = (Element) node; 231 if ("*".equals(elementName) || child.getTagName().equals(elementName)) { 232 result.add(child); 233 } 234 } else if (node.getNodeType() == Node.TEXT_NODE) { 235 String value = node.getNodeValue(); 236 if (trimWhitespace) { 237 value = value.trim(); 238 } 239 if ("*".equals(elementName) && value.length() > 0) { 240 node.setNodeValue(value); 241 result.add(node); 242 } 243 } 244 } 245 return new NodesHolder(result); 246 } 247 248 public static String toString(Object o) { 249 if (o instanceof Node) { 250 if (((Node) o).getNodeType() == Node.TEXT_NODE) { 251 return ((Node) o).getNodeValue(); 252 } 253 } 254 if (o instanceof NodeList) { 255 return toString((NodeList) o); 256 } 257 return o.toString(); 258 } 259 260 private static String toString(NodeList self) { 261 StringBuffer sb = new StringBuffer(); 262 sb.append("["); 263 Iterator it = DefaultGroovyMethods.iterator(self); 264 while (it.hasNext()) { 265 if (sb.length() > 1) sb.append(", "); 266 sb.append(it.next().toString()); 267 } 268 sb.append("]"); 269 return sb.toString(); 270 } 271 272 public static int size(NodeList self) { 273 return self.getLength(); 274 } 275 276 public static boolean isEmpty(NodeList self) { 277 return size(self) == 0; 278 } 279 280 private static void addResult(List results, Object result) { 281 if (result != null) { 282 if (result instanceof Collection) { 283 results.addAll((Collection) result); 284 } else { 285 results.add(result); 286 } 287 } 288 } 289 290 private static class NodeListsHolder implements NodeList { 291 private List nodeLists; 292 293 private NodeListsHolder(List nodeLists) { 294 this.nodeLists = nodeLists; 295 } 296 297 public int getLength() { 298 int length = 0; 299 for (int i = 0; i < nodeLists.size(); i++) { 300 NodeList nl = (NodeList) nodeLists.get(i); 301 length += nl.getLength(); 302 } 303 return length; 304 } 305 306 public Node item(int index) { 307 int relativeIndex = index; 308 for (int i = 0; i < nodeLists.size(); i++) { 309 NodeList nl = (NodeList) nodeLists.get(i); 310 if (relativeIndex < nl.getLength()) { 311 return nl.item(relativeIndex); 312 } 313 relativeIndex -= nl.getLength(); 314 } 315 return null; 316 } 317 318 public String toString() { 319 return DOMCategory.toString(this); 320 } 321 } 322 323 private static class NodesHolder implements NodeList { 324 private List nodes; 325 326 private NodesHolder(List nodes) { 327 this.nodes = nodes; 328 } 329 330 public int getLength() { 331 return nodes.size(); 332 } 333 334 public Node item(int index) { 335 if (index < 0 || index >= getLength()) { 336 return null; 337 } 338 return (Node) nodes.get(index); 339 } 340 } 341 }