001: /*
002: $Id: DOMBuilder.java 4132 2006-10-18 08:24:58Z paulk $
003:
004: Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005:
006: Redistribution and use of this software and associated documentation
007: ("Software"), with or without modification, are permitted provided
008: that the following conditions are met:
009:
010: 1. Redistributions of source code must retain copyright
011: statements and notices. Redistributions must also contain a
012: copy of this document.
013:
014: 2. Redistributions in binary form must reproduce the
015: above copyright notice, this list of conditions and the
016: following disclaimer in the documentation and/or other
017: materials provided with the distribution.
018:
019: 3. The name "groovy" must not be used to endorse or promote
020: products derived from this Software without prior written
021: permission of The Codehaus. For written permission,
022: please contact info@codehaus.org.
023:
024: 4. Products derived from this Software may not be called "groovy"
025: nor may "groovy" appear in their names without prior written
026: permission of The Codehaus. "groovy" is a registered
027: trademark of The Codehaus.
028:
029: 5. Due credit should be given to The Codehaus -
030: http://groovy.codehaus.org/
031:
032: THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033: ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034: NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
036: THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043: OF THE POSSIBILITY OF SUCH DAMAGE.
044:
045: */
046: package groovy.xml;
047:
048: import groovy.util.BuilderSupport;
049:
050: import java.io.IOException;
051: import java.io.Reader;
052: import java.util.Iterator;
053: import java.util.Map;
054:
055: import javax.xml.parsers.DocumentBuilder;
056: import javax.xml.parsers.DocumentBuilderFactory;
057: import javax.xml.parsers.ParserConfigurationException;
058:
059: import org.w3c.dom.Document;
060: import org.w3c.dom.Element;
061: import org.w3c.dom.Node;
062: import org.xml.sax.InputSource;
063: import org.xml.sax.SAXException;
064:
065: /**
066: * A helper class for creating a W3C DOM tree
067: *
068: * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
069: * @version $Revision: 4132 $
070: */
071: public class DOMBuilder extends BuilderSupport {
072:
073: Document document;
074: DocumentBuilder documentBuilder;
075:
076: public static DOMBuilder newInstance()
077: throws ParserConfigurationException {
078: return newInstance(false, true);
079: }
080:
081: public static DOMBuilder newInstance(boolean validating,
082: boolean namespaceAware) throws ParserConfigurationException {
083: DocumentBuilderFactory factory = FactorySupport
084: .createDocumentBuilderFactory();
085: factory.setNamespaceAware(namespaceAware);
086: factory.setValidating(validating);
087: return new DOMBuilder(factory.newDocumentBuilder());
088: }
089:
090: public static Document parse(Reader reader) throws SAXException,
091: IOException, ParserConfigurationException {
092: return parse(reader, false, true);
093: }
094:
095: public static Document parse(Reader reader, boolean validating,
096: boolean namespaceAware) throws SAXException, IOException,
097: ParserConfigurationException {
098: DocumentBuilderFactory factory = FactorySupport
099: .createDocumentBuilderFactory();
100: factory.setNamespaceAware(namespaceAware);
101: factory.setValidating(validating);
102: DocumentBuilder documentBuilder = factory.newDocumentBuilder();
103: return documentBuilder.parse(new InputSource(reader));
104: }
105:
106: public DOMBuilder(Document document) {
107: this .document = document;
108: }
109:
110: public DOMBuilder(DocumentBuilder documentBuilder) {
111: this .documentBuilder = documentBuilder;
112: }
113:
114: protected void setParent(Object parent, Object child) {
115: Node current = (Node) parent;
116: Node node = (Node) child;
117:
118: current.appendChild(node);
119: }
120:
121: protected Object createNode(Object name) {
122: if (document == null) {
123: document = createDocument();
124: }
125: if (name instanceof QName) {
126: QName qname = (QName) name;
127: return document.createElementNS(qname.getNamespaceURI(),
128: qname.getQualifiedName());
129: } else {
130: return document.createElement(name.toString());
131: }
132: }
133:
134: protected Document createDocument() {
135: if (documentBuilder == null) {
136: throw new IllegalArgumentException(
137: "No Document or DOMImplementation available so cannot create Document");
138: } else {
139: return documentBuilder.newDocument();
140: }
141: }
142:
143: protected Object createNode(Object name, Object value) {
144: Element element = (Element) createNode(name);
145: element.appendChild(document.createTextNode(value.toString()));
146: return element;
147: }
148:
149: protected Object createNode(Object name, Map attributes,
150: Object value) {
151: Element element = (Element) createNode(name, attributes);
152: element.appendChild(document.createTextNode(value.toString()));
153: return element;
154: }
155:
156: protected Object createNode(Object name, Map attributes) {
157: Element element = (Element) createNode(name);
158: for (Iterator iter = attributes.entrySet().iterator(); iter
159: .hasNext();) {
160: Map.Entry entry = (Map.Entry) iter.next();
161: String attrName = entry.getKey().toString();
162: Object value = entry.getValue();
163: if ("xmlns".equals(attrName)) {
164: if (value instanceof Map) {
165: appendNamespaceAttributes(element, (Map) value);
166: } else {
167: throw new IllegalArgumentException(
168: "The value of the xmlns attribute must be a Map of QNames to String URIs");
169: }
170: } else {
171: // TODO handle null values and treat as ''
172: element.setAttribute(attrName, value.toString());
173: }
174: }
175: return element;
176: }
177:
178: protected void appendNamespaceAttributes(Element element,
179: Map attributes) {
180: for (Iterator iter = attributes.entrySet().iterator(); iter
181: .hasNext();) {
182: Map.Entry entry = (Map.Entry) iter.next();
183: Object key = entry.getKey();
184: Object value = entry.getValue();
185: if (value == null) {
186: throw new IllegalArgumentException("The value of key: "
187: + key + " cannot be null");
188: }
189: if (key instanceof String) {
190: String prefix = (String) key;
191:
192: //System.out.println("Creating namespace for prefix: " + prefix + " with value: " + value);
193:
194: //element.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xmlns:" + prefix, value.toString());
195: element.setAttributeNS("", prefix, value.toString());
196: } else if (key instanceof QName) {
197: QName qname = (QName) key;
198: element.setAttributeNS(qname.getNamespaceURI(), qname
199: .getQualifiedName(), value.toString());
200: } else {
201: throw new IllegalArgumentException("The key: " + key
202: + " should be an instanceof of " + QName.class);
203: }
204: }
205: }
206: }
|