001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023:
024: package biz.hammurapi.xml.dom;
025:
026: import java.io.File;
027: import java.io.FileInputStream;
028: import java.io.FileOutputStream;
029: import java.io.IOException;
030: import java.io.InputStream;
031: import java.io.OutputStream;
032: import java.io.Reader;
033: import java.io.StringWriter;
034: import java.util.Iterator;
035: import java.util.Map;
036: import java.util.Properties;
037:
038: import javax.xml.parsers.DocumentBuilderFactory;
039: import javax.xml.parsers.FactoryConfigurationError;
040: import javax.xml.parsers.ParserConfigurationException;
041: import javax.xml.transform.Result;
042: import javax.xml.transform.Transformer;
043: import javax.xml.transform.TransformerException;
044: import javax.xml.transform.TransformerFactory;
045: import javax.xml.transform.dom.DOMSource;
046: import javax.xml.transform.stream.StreamResult;
047: import javax.xml.transform.stream.StreamSource;
048:
049: import org.apache.xpath.XPathAPI;
050: import org.w3c.dom.Document;
051: import org.w3c.dom.Element;
052: import org.w3c.dom.NamedNodeMap;
053: import org.w3c.dom.Node;
054: import org.w3c.dom.NodeList;
055: import org.w3c.dom.traversal.NodeIterator;
056: import org.xml.sax.InputSource;
057: import org.xml.sax.SAXException;
058:
059: import biz.hammurapi.config.ConfigurationException;
060:
061: /**
062: * Utility class for querying DOM.
063: *
064: * @author Pavel Vlasov
065: */
066: public class DOMUtils {
067:
068: /** Creates a new instance of DOMUtils */
069: private DOMUtils() {
070: // Utility class
071: }
072:
073: /**
074: * Ensures that thre is one and only one element and returns it.
075: */
076: public static Element getSingleElement(Element e, String elementName)
077: throws ConfigurationException, TransformerException {
078: NodeList nl = XPathAPI.selectNodeList(e, elementName);
079: if (nl.getLength() == 0) {
080: throw new ConfigurationException("Element <" + elementName
081: + "> not found");
082: }
083: if (nl.getLength() > 1) {
084: throw new ConfigurationException("Duplicate element <"
085: + elementName + ">");
086: }
087:
088: return (Element) nl.item(0);
089: }
090:
091: /**
092: * Ensures that there is only one element and returns its text
093: */
094: public static String getSingleElementText(Element e,
095: String elementName) throws ConfigurationException,
096: TransformerException {
097: return getElementText(getSingleElement(e, elementName));
098: }
099:
100: public static String getSingleNonBlankElementText(Element e,
101: String elementName) throws ConfigurationException,
102: TransformerException {
103: return getNonBlankElementText(getSingleElement(e, elementName));
104: }
105:
106: public static String getElementText(Element e)
107: throws TransformerException {
108: return XPathAPI.eval(e, "text()").toString();
109: }
110:
111: public static String getNonBlankElementText(Element e)
112: throws ConfigurationException, TransformerException {
113: String res = getElementText(e);
114: if (res.trim().length() == 0) {
115: throw new ConfigurationException("Element <"
116: + e.getNodeName() + "> is blank");
117: }
118: return res;
119: }
120:
121: public static Properties dom2Properties(Element e, String prefix)
122: throws TransformerException {
123: String root = prefix == null ? e.getNodeName() : prefix + "."
124: + e.getNodeName();
125: Properties res = new Properties();
126: String text = getElementText(e);
127: if (text.trim().length() != 0) {
128: res.setProperty(root, text);
129: }
130:
131: NamedNodeMap attributes = e.getAttributes();
132: for (int i = 0, l = attributes.getLength(); i < l; i++) {
133: Node attribute = attributes.item(i);
134: res.setProperty(root + "(" + attribute.getNodeName() + ")",
135: attribute.getNodeValue());
136: }
137:
138: NodeList nl = e.getChildNodes();
139: for (int i = 0; i < nl.getLength(); i++) {
140: Node n = nl.item(i);
141: if (n.getNodeType() == Node.ELEMENT_NODE) {
142: res.putAll(dom2Properties((Element) n, root));
143: }
144: }
145:
146: return res;
147: }
148:
149: /**
150: * Reads elements <property name="...">...</property> into
151: * properties
152: */
153: public static void readProperties(Element holder,
154: Properties properties) throws ConfigurationException,
155: TransformerException {
156: NodeIterator ni = XPathAPI.selectNodeIterator(holder,
157: "property");
158: Element el;
159: while ((el = (Element) ni.nextNode()) != null) {
160: if (!el.hasAttribute("name")) {
161: throw new ConfigurationException("Unnamed property");
162: }
163: if (properties.containsKey(el.getAttribute("name"))) {
164: throw new ConfigurationException(
165: "Property already set: "
166: + el.getAttribute("name"));
167: }
168:
169: properties.setProperty(el.getAttribute("name"), DOMUtils
170: .getNonBlankElementText(el));
171: }
172: }
173:
174: public static void serialize(Object o, String root, Result result)
175: throws ParserConfigurationException,
176: FactoryConfigurationError, TransformerException {
177: Document doc = DocumentBuilderFactory.newInstance()
178: .newDocumentBuilder().newDocument();
179: Element rootElement = AbstractDomObject.addElement(doc, root);
180: toDom(o, rootElement);
181: TransformerFactory.newInstance().newTransformer().transform(
182: new DOMSource(doc), result);
183: }
184:
185: public static void serialize(Object o, String root, File out)
186: throws ParserConfigurationException,
187: FactoryConfigurationError, IOException,
188: TransformerException {
189: Document doc = DocumentBuilderFactory.newInstance()
190: .newDocumentBuilder().newDocument();
191: Element rootElement = AbstractDomObject.addElement(doc, root);
192: toDom(o, rootElement);
193: FileOutputStream os = new FileOutputStream(out);
194: serialize(doc, os);
195: os.close();
196: }
197:
198: public static void serialize(Node node, File out)
199: throws IOException, TransformerException {
200: FileOutputStream os = new FileOutputStream(out);
201: serialize(node, os);
202: os.close();
203: }
204:
205: public static void serialize(Node node, OutputStream os)
206: throws TransformerException {
207: TransformerFactory.newInstance().newTransformer().transform(
208: new DOMSource(node), new StreamResult(os));
209: }
210:
211: public static String toString(Node node) throws IOException,
212: TransformerException {
213: Transformer transformer = TransformerFactory.newInstance()
214: .newTransformer();
215:
216: //transformer.setOutputProperty("method", "xml");
217: transformer.setOutputProperty("indent", "yes");
218: transformer.setOutputProperty("omit-xml-declaration", "yes");
219:
220: StringWriter sw = new StringWriter();
221: transformer
222: .transform(new DOMSource(node), new StreamResult(sw));
223: sw.close();
224: return sw.toString();
225: }
226:
227: public static String toXmlString(Object o, String root)
228: throws IOException, TransformerException,
229: ParserConfigurationException, FactoryConfigurationError {
230: Document doc = DocumentBuilderFactory.newInstance()
231: .newDocumentBuilder().newDocument();
232: Element rootElement = AbstractDomObject.addElement(doc, root);
233: toDom(o, rootElement);
234: return toString(rootElement);
235: }
236:
237: public static String toXmlString(Object o, String root,
238: CompositeDomSerializer domSerializer) throws IOException,
239: TransformerException, ParserConfigurationException,
240: FactoryConfigurationError {
241: Document doc = DocumentBuilderFactory.newInstance()
242: .newDocumentBuilder().newDocument();
243: Element rootElement = AbstractDomObject.addElement(doc, root);
244: toDom(o, rootElement, domSerializer);
245: return toString(rootElement);
246: }
247:
248: public static void style(Object o, String root, OutputStream os,
249: InputStream style, Map parameters)
250: throws ParserConfigurationException,
251: FactoryConfigurationError, TransformerException {
252: Document doc = DocumentBuilderFactory.newInstance()
253: .newDocumentBuilder().newDocument();
254: Element rootElement = AbstractDomObject.addElement(doc, root);
255: toDom(o, rootElement);
256: style(doc, os, style, parameters);
257: }
258:
259: public static void style(Object o, String root, File out,
260: InputStream style, Map parameters)
261: throws ParserConfigurationException,
262: FactoryConfigurationError, IOException,
263: TransformerException {
264: Document doc = DocumentBuilderFactory.newInstance()
265: .newDocumentBuilder().newDocument();
266: Element rootElement = AbstractDomObject.addElement(doc, root);
267: toDom(o, rootElement);
268: FileOutputStream os = new FileOutputStream(out);
269: style(doc, os, style, parameters);
270: os.close();
271: }
272:
273: public static void style(Document doc, File out, InputStream style,
274: Map parameters) throws IOException, TransformerException {
275: FileOutputStream os = new FileOutputStream(out);
276: style(doc, os, style, parameters);
277: os.close();
278: }
279:
280: public static void style(Document doc, OutputStream os,
281: InputStream style, Map parameters)
282: throws TransformerException {
283: TransformerFactory factory = TransformerFactory.newInstance();
284: Transformer transformer = style == null ? factory
285: .newTransformer() : factory
286: .newTransformer(new StreamSource(style));
287: if (parameters != null) {
288: Iterator it = parameters.entrySet().iterator();
289: while (it.hasNext()) {
290: Map.Entry entry = (Map.Entry) it.next();
291: transformer.setParameter((String) entry.getKey(), entry
292: .getValue());
293: }
294: }
295: transformer.transform(new DOMSource(doc), new StreamResult(os));
296: }
297:
298: public static Document parse(File file) throws SAXException,
299: IOException, ParserConfigurationException,
300: FactoryConfigurationError {
301: InputStream is = new FileInputStream(file);
302: try {
303: return parse(is);
304: } finally {
305: is.close();
306: }
307: }
308:
309: /**
310: * @param is
311: * @return
312: * @throws FactoryConfigurationError
313: * @throws ParserConfigurationException
314: * @throws IOException
315: * @throws SAXException
316: */
317: public static Document parse(InputStream is) throws SAXException,
318: IOException, ParserConfigurationException,
319: FactoryConfigurationError {
320: return DocumentBuilderFactory.newInstance()
321: .newDocumentBuilder().parse(is);
322: }
323:
324: /**
325: * @param is
326: * @return
327: * @throws FactoryConfigurationError
328: * @throws ParserConfigurationException
329: * @throws IOException
330: * @throws SAXException
331: */
332: public static Document parse(Reader is) throws SAXException,
333: IOException, ParserConfigurationException,
334: FactoryConfigurationError {
335: return DocumentBuilderFactory.newInstance()
336: .newDocumentBuilder().parse(new InputSource(is));
337: }
338:
339: /**
340: * Serializes object to XML. Specially treats collections,
341: * maps, arrays and DomSerializable objects.
342: * @param o
343: * @param holder
344: */
345: public static void toDom(Object o, Element holder) {
346: if (o != null) {
347: DomSerializable ds = CompositeDomSerializer
348: .getThreadInstance().toDomSerializable(o);
349: if (ds != null) {
350: ds.toDom(holder);
351: }
352: }
353: }
354:
355: /**
356: * Serializes object to XML. Specially treats collections,
357: * maps, arrays and DomSerializable objects.
358: * @param o
359: * @param name Element name
360: * @param parent parent element
361: */
362: public static void toDom(Object o, String name, Element parent) {
363: if (o != null) {
364: DomSerializable ds = CompositeDomSerializer
365: .getThreadInstance().toDomSerializable(o);
366: if (ds != null) {
367: Element holder = parent.getOwnerDocument()
368: .createElement(name);
369: parent.appendChild(holder);
370: ds.toDom(holder);
371: }
372: }
373: }
374:
375: public static Document toDom(Object o)
376: throws ParserConfigurationException,
377: FactoryConfigurationError {
378: Document document = DocumentBuilderFactory.newInstance()
379: .newDocumentBuilder().newDocument();
380: Element root = document.createElement("root");
381: document.appendChild(root);
382: toDom(o, root);
383: return document;
384: }
385:
386: /**
387: * Serializes object to XML. Specially treats collections,
388: * maps, arrays and DomSerializable objects.
389: * @param o
390: * @param holder
391: */
392: public static void toDom(Object o, Element holder,
393: CompositeDomSerializer domSerializer) {
394: if (o != null) {
395: DomSerializable ds = domSerializer.toDomSerializable(o);
396: if (ds != null) {
397: ds.toDom(holder);
398: }
399: }
400: }
401:
402: /**
403: * Serializes object to XML. Specially treats collections,
404: * maps, arrays and DomSerializable objects.
405: * @param o
406: * @param name Element name
407: * @param parent parent element
408: */
409: public static void toDom(Object o, String name, Element parent,
410: CompositeDomSerializer domSerializer) {
411: if (o != null) {
412: DomSerializable ds = domSerializer.toDomSerializable(o);
413: if (ds != null) {
414: Element holder = parent.getOwnerDocument()
415: .createElement(name);
416: parent.appendChild(holder);
417: ds.toDom(holder);
418: }
419: }
420: }
421:
422: public static Document toDom(Object o,
423: CompositeDomSerializer domSerializer)
424: throws ParserConfigurationException,
425: FactoryConfigurationError {
426: Document document = DocumentBuilderFactory.newInstance()
427: .newDocumentBuilder().newDocument();
428: Element root = document.createElement("root");
429: document.appendChild(root);
430: toDom(o, root, domSerializer);
431: return document;
432: }
433:
434: }
|