blob: 7bf333dfafaeb42387debe88ff2d5778e0395f70 [file] [log] [blame]
/*
* $Id$version Apr 25, 2004 5:18:30 PM $user Exp $
*
* Copyright 2003 (C) Sam Pullara. All Rights Reserved.
*
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided that the
* following conditions are met: 1. Redistributions of source code must retain
* copyright statements and notices. Redistributions must also contain a copy of
* this document. 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. 3. The
* name "groovy" must not be used to endorse or promote products derived from
* this Software without prior written permission of The Codehaus. For written
* permission, please contact info@codehaus.org. 4. Products derived from this
* Software may not be called "groovy" nor may "groovy" appear in their names
* without prior written permission of The Codehaus. "groovy" is a registered
* trademark of The Codehaus. 5. Due credit should be given to The Codehaus -
* http://groovy.codehaus.org/
*
* THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package groovy.xml.dom;
import org.w3c.dom.*;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author sam
* @author paulk
*/
public class DOMCategory {
private static boolean trimWhitespace = true;
public static Object get(Object o, String elementName) {
if (o instanceof Element) {
return get((Element) o, elementName);
}
if (o instanceof NodeList) {
return get((NodeList) o, elementName);
}
if (o instanceof NamedNodeMap) {
return get((NamedNodeMap) o, elementName);
}
return null;
}
private static Object get(Element element, String elementName) {
return getAt(element, elementName);
}
private static Object get(NodeList nodeList, String elementName) {
return getAt(nodeList, elementName);
}
private static Object get(NamedNodeMap nodeMap, String elementName) {
return getAt(nodeMap, elementName);
}
private static Object getAt(Element element, String elementName) {
if ("..".equals(elementName)) {
return parent(element);
}
if ("**".equals(elementName)) {
return depthFirst(element);
}
if (elementName.startsWith("@")) {
return element.getAttribute(elementName.substring(1));
}
return getChildElements(element, elementName);
}
private static Object getAt(NodeList nodeList, String elementName) {
List results = new ArrayList();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node instanceof Element) {
addResult(results, get(node, elementName));
}
}
if (elementName.startsWith("@")) {
return results;
}
return new NodeListsHolder(results);
}
public static NamedNodeMap attributes(Element element) {
return element.getAttributes();
}
private static String getAt(NamedNodeMap namedNodeMap, String elementName) {
Attr a = (Attr) namedNodeMap.getNamedItem(elementName);
return a.getValue();
}
public static int size(NamedNodeMap namedNodeMap) {
return namedNodeMap.getLength();
}
public static Node getAt(Node o, int i) {
return nodeGetAt(o, i);
}
public static Node getAt(NodeListsHolder o, int i) {
return nodeGetAt(o, i);
}
public static Node getAt(NodesHolder o, int i) {
return nodeGetAt(o, i);
}
private static Node nodeGetAt(Object o, int i) {
if (o instanceof Element) {
Node n = getAt((Element)o, i);
if (n != null) return n;
}
if (o instanceof NodeList) {
return getAt((NodeList)o, i);
}
return null;
}
private static Node getAt(Element element, int i) {
if (hasChildElements(element, "*")) {
NodeList nodeList = getChildElements(element, "*");
return nodeList.item(i);
}
return null;
}
private static Node getAt(NodeList nodeList, int i) {
if (i >= 0 && i < nodeList.getLength()) {
return nodeList.item(i);
}
return null;
}
public static String name(Element element) {
return element.getNodeName();
}
public static Node parent(Node node) {
return node.getParentNode();
}
public static String text(Object o) {
if (o instanceof Element) {
return text((Element) o);
}
if (o instanceof Node) {
Node n = (Node) o;
if (n.getNodeType() == Node.TEXT_NODE) {
return n.getNodeValue();
}
}
if (o instanceof NodeList) {
return text((NodeList) o);
}
return null;
}
private static String text(Element element) {
if (!element.hasChildNodes()) {
return "";
}
if (element.getFirstChild().getNodeType() != Node.TEXT_NODE) {
return "";
}
return element.getFirstChild().getNodeValue();
}
private static String text(NodeList nodeList) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < nodeList.getLength(); i++) {
sb.append(text(nodeList.item(i)));
}
return sb.toString();
}
public static List list(NodeList self) {
List answer = new ArrayList();
Iterator it = DefaultGroovyMethods.iterator(self);
while (it.hasNext()) {
answer.add(it.next());
}
return answer;
}
public static NodeList depthFirst(Element self) {
List result = new ArrayList();
result.add(createNodeList(self));
result.add(self.getElementsByTagName("*"));
return new NodeListsHolder(result);
}
private static NodeList createNodeList(Element self) {
List first = new ArrayList();
first.add(self);
return new NodesHolder(first);
}
public static NodeList breadthFirst(Element self) {
List result = new ArrayList();
NodeList thisLevel = createNodeList(self);
while (thisLevel.getLength() > 0) {
result.add(thisLevel);
thisLevel = getNextLevel(thisLevel);
}
return new NodeListsHolder(result);
}
private static NodeList getNextLevel(NodeList thisLevel) {
List result = new ArrayList();
for (int i = 0; i < thisLevel.getLength(); i++) {
Node n = thisLevel.item(i);
if (n instanceof Element) {
result.add(getChildElements((Element) n, "*"));
}
}
return new NodeListsHolder(result);
}
public static NodeList children(Element self) {
return getChildElements(self, "*");
}
private static boolean hasChildElements(Element self, String elementName) {
return getChildElements(self, elementName).getLength() > 0;
}
private static NodeList getChildElements(Element self, String elementName) {
List result = new ArrayList();
NodeList nodeList = self.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element child = (Element) node;
if ("*".equals(elementName) || child.getTagName().equals(elementName)) {
result.add(child);
}
} else if (node.getNodeType() == Node.TEXT_NODE) {
String value = node.getNodeValue();
if (trimWhitespace) {
value = value.trim();
}
if ("*".equals(elementName) && value.length() > 0) {
node.setNodeValue(value);
result.add(node);
}
}
}
return new NodesHolder(result);
}
public static String toString(Object o) {
if (o instanceof Node) {
if (((Node) o).getNodeType() == Node.TEXT_NODE) {
return ((Node) o).getNodeValue();
}
}
if (o instanceof NodeList) {
return toString((NodeList) o);
}
return o.toString();
}
private static String toString(NodeList self) {
StringBuffer sb = new StringBuffer();
sb.append("[");
Iterator it = DefaultGroovyMethods.iterator(self);
while (it.hasNext()) {
if (sb.length() > 1) sb.append(", ");
sb.append(it.next().toString());
}
sb.append("]");
return sb.toString();
}
public static int size(NodeList self) {
return self.getLength();
}
public static boolean isEmpty(NodeList self) {
return size(self) == 0;
}
private static void addResult(List results, Object result) {
if (result != null) {
if (result instanceof Collection) {
results.addAll((Collection) result);
} else {
results.add(result);
}
}
}
private static class NodeListsHolder implements NodeList {
private List nodeLists;
private NodeListsHolder(List nodeLists) {
this.nodeLists = nodeLists;
}
public int getLength() {
int length = 0;
for (int i = 0; i < nodeLists.size(); i++) {
NodeList nl = (NodeList) nodeLists.get(i);
length += nl.getLength();
}
return length;
}
public Node item(int index) {
int relativeIndex = index;
for (int i = 0; i < nodeLists.size(); i++) {
NodeList nl = (NodeList) nodeLists.get(i);
if (relativeIndex < nl.getLength()) {
return nl.item(relativeIndex);
}
relativeIndex -= nl.getLength();
}
return null;
}
public String toString() {
return DOMCategory.toString(this);
}
}
private static class NodesHolder implements NodeList {
private List nodes;
private NodesHolder(List nodes) {
this.nodes = nodes;
}
public int getLength() {
return nodes.size();
}
public Node item(int index) {
if (index < 0 || index >= getLength()) {
return null;
}
return (Node) nodes.get(index);
}
}
}