001: /*
002: * $Id: DOMCategory.java 4649 2007-01-02 14:26:37Z 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,
108: String elementName) {
109: Attr a = (Attr) namedNodeMap.getNamedItem(elementName);
110: return a.getValue();
111: }
112:
113: public static int size(NamedNodeMap namedNodeMap) {
114: return namedNodeMap.getLength();
115: }
116:
117: public static Node getAt(Node o, int i) {
118: return nodeGetAt(o, i);
119: }
120:
121: public static Node getAt(NodeListsHolder o, int i) {
122: return nodeGetAt(o, i);
123: }
124:
125: public static Node getAt(NodesHolder o, int i) {
126: return nodeGetAt(o, i);
127: }
128:
129: private static Node nodeGetAt(Object o, int i) {
130: if (o instanceof Element) {
131: Node n = getAt((Element) o, i);
132: if (n != null)
133: return n;
134: }
135: if (o instanceof NodeList) {
136: return getAt((NodeList) o, i);
137: }
138: return null;
139: }
140:
141: private static Node getAt(Element element, int i) {
142: if (hasChildElements(element, "*")) {
143: NodeList nodeList = getChildElements(element, "*");
144: return nodeList.item(i);
145: }
146: return null;
147: }
148:
149: private static Node getAt(NodeList nodeList, int i) {
150: if (i >= 0 && i < nodeList.getLength()) {
151: return nodeList.item(i);
152: }
153: return null;
154: }
155:
156: public static String name(Element element) {
157: return element.getNodeName();
158: }
159:
160: public static Node parent(Node node) {
161: return node.getParentNode();
162: }
163:
164: public static String text(Object o) {
165: if (o instanceof Element) {
166: return text((Element) o);
167: }
168: if (o instanceof Node) {
169: Node n = (Node) o;
170: if (n.getNodeType() == Node.TEXT_NODE) {
171: return n.getNodeValue();
172: }
173: }
174: if (o instanceof NodeList) {
175: return text((NodeList) o);
176: }
177: return null;
178: }
179:
180: private static String text(Element element) {
181: if (!element.hasChildNodes()) {
182: return "";
183: }
184: if (element.getFirstChild().getNodeType() != Node.TEXT_NODE) {
185: return "";
186: }
187: return element.getFirstChild().getNodeValue();
188: }
189:
190: private static String text(NodeList nodeList) {
191: StringBuffer sb = new StringBuffer();
192: for (int i = 0; i < nodeList.getLength(); i++) {
193: sb.append(text(nodeList.item(i)));
194: }
195: return sb.toString();
196: }
197:
198: public static List list(NodeList self) {
199: List answer = new ArrayList();
200: Iterator it = DefaultGroovyMethods.iterator(self);
201: while (it.hasNext()) {
202: answer.add(it.next());
203: }
204: return answer;
205: }
206:
207: public static NodeList depthFirst(Element self) {
208: List result = new ArrayList();
209: result.add(createNodeList(self));
210: result.add(self.getElementsByTagName("*"));
211: return new NodeListsHolder(result);
212: }
213:
214: private static NodeList createNodeList(Element self) {
215: List first = new ArrayList();
216: first.add(self);
217: return new NodesHolder(first);
218: }
219:
220: public static NodeList breadthFirst(Element self) {
221: List result = new ArrayList();
222: NodeList this Level = createNodeList(self);
223: while (this Level.getLength() > 0) {
224: result.add(this Level);
225: this Level = getNextLevel(this Level);
226: }
227: return new NodeListsHolder(result);
228: }
229:
230: private static NodeList getNextLevel(NodeList this Level) {
231: List result = new ArrayList();
232: for (int i = 0; i < this Level.getLength(); i++) {
233: Node n = this Level.item(i);
234: if (n instanceof Element) {
235: result.add(getChildElements((Element) n, "*"));
236: }
237: }
238: return new NodeListsHolder(result);
239: }
240:
241: public static NodeList children(Element self) {
242: return getChildElements(self, "*");
243: }
244:
245: private static boolean hasChildElements(Element self,
246: String elementName) {
247: return getChildElements(self, elementName).getLength() > 0;
248: }
249:
250: private static NodeList getChildElements(Element self,
251: String elementName) {
252: List result = new ArrayList();
253: NodeList nodeList = self.getChildNodes();
254: for (int i = 0; i < nodeList.getLength(); i++) {
255: Node node = nodeList.item(i);
256: if (node.getNodeType() == Node.ELEMENT_NODE) {
257: Element child = (Element) node;
258: if ("*".equals(elementName)
259: || child.getTagName().equals(elementName)) {
260: result.add(child);
261: }
262: } else if (node.getNodeType() == Node.TEXT_NODE) {
263: String value = node.getNodeValue();
264: if (trimWhitespace) {
265: value = value.trim();
266: }
267: if ("*".equals(elementName) && value.length() > 0) {
268: node.setNodeValue(value);
269: result.add(node);
270: }
271: }
272: }
273: return new NodesHolder(result);
274: }
275:
276: public static String toString(Object o) {
277: if (o instanceof Node) {
278: if (((Node) o).getNodeType() == Node.TEXT_NODE) {
279: return ((Node) o).getNodeValue();
280: }
281: }
282: if (o instanceof NodeList) {
283: return toString((NodeList) o);
284: }
285: return o.toString();
286: }
287:
288: private static String toString(NodeList self) {
289: StringBuffer sb = new StringBuffer();
290: sb.append("[");
291: Iterator it = DefaultGroovyMethods.iterator(self);
292: while (it.hasNext()) {
293: if (sb.length() > 1)
294: sb.append(", ");
295: sb.append(it.next().toString());
296: }
297: sb.append("]");
298: return sb.toString();
299: }
300:
301: public static int size(NodeList self) {
302: return self.getLength();
303: }
304:
305: public static boolean isEmpty(NodeList self) {
306: return size(self) == 0;
307: }
308:
309: private static void addResult(List results, Object result) {
310: if (result != null) {
311: if (result instanceof Collection) {
312: results.addAll((Collection) result);
313: } else {
314: results.add(result);
315: }
316: }
317: }
318:
319: private static class NodeListsHolder implements NodeList {
320: private List nodeLists;
321:
322: private NodeListsHolder(List nodeLists) {
323: this .nodeLists = nodeLists;
324: }
325:
326: public int getLength() {
327: int length = 0;
328: for (int i = 0; i < nodeLists.size(); i++) {
329: NodeList nl = (NodeList) nodeLists.get(i);
330: length += nl.getLength();
331: }
332: return length;
333: }
334:
335: public Node item(int index) {
336: int relativeIndex = index;
337: for (int i = 0; i < nodeLists.size(); i++) {
338: NodeList nl = (NodeList) nodeLists.get(i);
339: if (relativeIndex < nl.getLength()) {
340: return nl.item(relativeIndex);
341: }
342: relativeIndex -= nl.getLength();
343: }
344: return null;
345: }
346:
347: public String toString() {
348: return DOMCategory.toString(this );
349: }
350: }
351:
352: private static class NodesHolder implements NodeList {
353: private List nodes;
354:
355: private NodesHolder(List nodes) {
356: this .nodes = nodes;
357: }
358:
359: public int getLength() {
360: return nodes.size();
361: }
362:
363: public Node item(int index) {
364: if (index < 0 || index >= getLength()) {
365: return null;
366: }
367: return (Node) nodes.get(index);
368: }
369: }
370: }
|