001: /*
002: * Copyright (C) The DNA Group. All rights reserved.
003: *
004: * This software is published under the terms of the DNA
005: * Software License version 1.1, a copy of which has been included
006: * with this distribution in the LICENSE.txt file.
007: */
008: package org.codehaus.dna.impl;
009:
010: import java.util.Properties;
011: import javax.xml.parsers.DocumentBuilder;
012: import javax.xml.parsers.DocumentBuilderFactory;
013: import javax.xml.parsers.SAXParser;
014: import javax.xml.parsers.SAXParserFactory;
015: import javax.xml.transform.OutputKeys;
016: import javax.xml.transform.Result;
017: import javax.xml.transform.TransformerFactory;
018: import javax.xml.transform.sax.SAXTransformerFactory;
019: import javax.xml.transform.sax.TransformerHandler;
020:
021: import org.codehaus.dna.Configuration;
022: import org.w3c.dom.Document;
023: import org.w3c.dom.Element;
024: import org.w3c.dom.NamedNodeMap;
025: import org.w3c.dom.Node;
026: import org.w3c.dom.NodeList;
027: import org.w3c.dom.Text;
028: import org.xml.sax.InputSource;
029:
030: /**
031: * Class containing utility methods to work with Configuration
032: * objects.
033: *
034: * @version $Revision: 1.2 $ $Date: 2004/05/01 09:51:48 $
035: */
036: public class ConfigurationUtil {
037: /**
038: * Constant defining separator for paths in document.
039: */
040: public static final String PATH_SEPARATOR = "/";
041:
042: /**
043: * Constant defining root path of document.
044: */
045: public static final String ROOT_PATH = "";
046:
047: /**
048: * Constant indicating location was generated from DOM
049: * Element.
050: */
051: private static final String ELEMENT_LOCATION = "dom-gen";
052:
053: /**
054: * Serialize Configuration object to sepcified Result object.
055: * The developer can serialize to a system out by using
056: * {@link javax.xml.transform.stream.StreamResult} in code
057: * such as;
058: *
059: * <pre>
060: * ConfigurationUtil.
061: * serializeToResult( new StreamResult( System.out ),
062: * configuration );
063: * </pre>
064: *
065: * <p>The developer can also output to SAX stream or DOM trees
066: * via {@link javax.xml.transform.sax.SAXResult} and
067: * {@link javax.xml.transform.dom.DOMResult}.</p>
068: *
069: * @param result the result object to serialize configuration to
070: * @param configuration the configuration
071: * @throws Exception if unable to serialize configuration
072: */
073: public static void serializeToResult(final Result result,
074: final Configuration configuration) throws Exception {
075: final SAXTransformerFactory factory = (SAXTransformerFactory) TransformerFactory
076: .newInstance();
077: final TransformerHandler handler = factory
078: .newTransformerHandler();
079:
080: final Properties format = new Properties();
081: format.put(OutputKeys.METHOD, "xml");
082: format.put(OutputKeys.INDENT, "yes");
083: handler.setResult(result);
084: handler.getTransformer().setOutputProperties(format);
085:
086: final SAXConfigurationSerializer serializer = new SAXConfigurationSerializer();
087: serializer.serialize(configuration, handler);
088: }
089:
090: /**
091: * Create a configuration object from specified XML InputSource.
092: *
093: * @param input the InputSource
094: * @return the configuration object
095: * @throws Exception if unable to create configuration object
096: * from input
097: */
098: public static Configuration buildFromXML(final InputSource input)
099: throws Exception {
100: final SAXParserFactory saxParserFactory = SAXParserFactory
101: .newInstance();
102: saxParserFactory.setNamespaceAware(false);
103: final SAXParser saxParser = saxParserFactory.newSAXParser();
104: final SAXConfigurationHandler handler = new SAXConfigurationHandler();
105: saxParser.parse(input, handler);
106: return handler.getConfiguration();
107: }
108:
109: /**
110: * Convert specified Element into a configuration object.
111: *
112: * @param element the Element
113: * @return the Configuration object
114: */
115: public static Configuration toConfiguration(final Element element) {
116: return toConfiguration(element, ROOT_PATH);
117: }
118:
119: /**
120: * Internal utility method to convert specified Element into
121: * a configuration object.
122: *
123: * @param element the Element
124: * @param parentPath the path to root of document
125: * @return the Configuration object
126: */
127: private static Configuration toConfiguration(final Element element,
128: final String parentPath) {
129: final DefaultConfiguration configuration = new DefaultConfiguration(
130: element.getNodeName(), ELEMENT_LOCATION, parentPath);
131: final NamedNodeMap attributes = element.getAttributes();
132: final int length = attributes.getLength();
133: for (int i = 0; i < length; i++) {
134: final Node node = attributes.item(i);
135: final String name = node.getNodeName();
136: final String value = node.getNodeValue();
137: configuration.setAttribute(name, value);
138: }
139:
140: final String childPath = generatePathName(parentPath,
141: configuration.getName());
142:
143: String content = null;
144: final NodeList nodes = element.getChildNodes();
145: final int count = nodes.getLength();
146: for (int i = 0; i < count; i++) {
147: final Node node = nodes.item(i);
148: if (node instanceof Element) {
149: final Configuration child = toConfiguration(
150: (Element) node, childPath);
151: configuration.addChild(child);
152: } else if (node instanceof Text) {
153: final Text data = (Text) node;
154: if (null != content) {
155: content += data.getData();
156: } else {
157: content = data.getData();
158: }
159: }
160: }
161:
162: if (null != content) {
163: configuration.setValue(content);
164: }
165:
166: return configuration;
167: }
168:
169: /**
170: * Add in utity method to generate path string from parent.
171: *
172: * @param path parents path
173: * @param name parents name
174: * @return the path string
175: */
176: static String generatePathName(final String path, final String name) {
177: if (ROOT_PATH.equals(path)) {
178: return name;
179: } else {
180: return path + PATH_SEPARATOR + name;
181: }
182: }
183:
184: /**
185: * Convert specified Configuration object into a Element.
186: *
187: * @param configuration the Configuration
188: * @return the Element object
189: */
190: public static Element toElement(final Configuration configuration) {
191: try {
192: final DocumentBuilderFactory factory = DocumentBuilderFactory
193: .newInstance();
194: final DocumentBuilder builder = factory
195: .newDocumentBuilder();
196: final Document document = builder.newDocument();
197:
198: return createElement(document, configuration);
199: } catch (final Throwable t) {
200: throw new IllegalStateException(t.toString());
201: }
202: }
203:
204: /**
205: * Internal helper method to convert specified Configuration object
206: * into a Element.
207: *
208: * @param document the owner document
209: * @param configuration the Configuration
210: * @return the Element object
211: */
212: private static Element createElement(final Document document,
213: final Configuration configuration) {
214: final Element element = document.createElement(configuration
215: .getName());
216:
217: final String content = configuration.getValue(null);
218: if (null != content) {
219: final Text child = document.createTextNode(content);
220: element.appendChild(child);
221: }
222:
223: final String[] names = configuration.getAttributeNames();
224: for (int i = 0; i < names.length; i++) {
225: final String name = names[i];
226: final String value = configuration.getAttribute(name, null);
227: element.setAttribute(name, value);
228: }
229: final Configuration[] children = configuration.getChildren();
230: for (int i = 0; i < children.length; i++) {
231: final Element child = createElement(document, children[i]);
232: element.appendChild(child);
233: }
234: return element;
235: }
236:
237: /**
238: * Test if two configuration objects are equal. To be equal
239: * the configuration objects must have equal child configuration
240: * objects in identical orders or identical content values and
241: * must have the same attributes with the same values.
242: *
243: * @param configuration1 a configuration object
244: * @param configuration2 a configuration object
245: * @return true if the configuration objects are equal
246: */
247: public static boolean equals(final Configuration configuration1,
248: final Configuration configuration2) {
249: final String name1 = configuration1.getName();
250: final String name2 = configuration2.getName();
251: if (!name1.equals(name2)) {
252: return false;
253: }
254:
255: final Configuration[] children1 = configuration1.getChildren();
256: final Configuration[] children2 = configuration2.getChildren();
257: if (children1.length != children2.length) {
258: return false;
259: } else {
260: for (int i = 0; i < children1.length; i++) {
261: if (!equals(children1[i], children2[i])) {
262: return false;
263: }
264: }
265: }
266:
267: final String[] names1 = configuration1.getAttributeNames();
268: final String[] names2 = configuration2.getAttributeNames();
269: if (names1.length != names2.length) {
270: return false;
271: } else {
272: for (int i = 0; i < names1.length; i++) {
273: final String value1 = configuration1.getAttribute(
274: names1[i], null);
275: final String value2 = configuration2.getAttribute(
276: names1[i], null);
277: if (!value1.equals(value2)) {
278: return false;
279: }
280: }
281: }
282:
283: final String value1 = configuration1.getValue(null);
284: final String value2 = configuration2.getValue(null);
285: if (null == value1 && null == value2) {
286: return true;
287: } else if (null != value1 && null != value2) {
288: return value1.equals(value2);
289: } else {
290: return false;
291: }
292: }
293: }
|