1
2
3
4
5
6
7
8 package org.codehaus.dna.impl;
9
10 import java.util.Properties;
11 import javax.xml.parsers.DocumentBuilder;
12 import javax.xml.parsers.DocumentBuilderFactory;
13 import javax.xml.parsers.SAXParser;
14 import javax.xml.parsers.SAXParserFactory;
15 import javax.xml.transform.OutputKeys;
16 import javax.xml.transform.Result;
17 import javax.xml.transform.TransformerFactory;
18 import javax.xml.transform.sax.SAXTransformerFactory;
19 import javax.xml.transform.sax.TransformerHandler;
20
21 import org.codehaus.dna.Configuration;
22 import org.w3c.dom.Document;
23 import org.w3c.dom.Element;
24 import org.w3c.dom.NamedNodeMap;
25 import org.w3c.dom.Node;
26 import org.w3c.dom.NodeList;
27 import org.w3c.dom.Text;
28 import org.xml.sax.InputSource;
29
30 /***
31 * Class containing utility methods to work with Configuration
32 * objects.
33 *
34 * @version $Revision: 1.2 $ $Date: 2004/05/01 09:51:48 $
35 */
36 public class ConfigurationUtil
37 {
38 /***
39 * Constant defining separator for paths in document.
40 */
41 public static final String PATH_SEPARATOR = "/";
42
43 /***
44 * Constant defining root path of document.
45 */
46 public static final String ROOT_PATH = "";
47
48 /***
49 * Constant indicating location was generated from DOM
50 * Element.
51 */
52 private static final String ELEMENT_LOCATION = "dom-gen";
53
54 /***
55 * Serialize Configuration object to sepcified Result object.
56 * The developer can serialize to a system out by using
57 * {@link javax.xml.transform.stream.StreamResult} in code
58 * such as;
59 *
60 * <pre>
61 * ConfigurationUtil.
62 * serializeToResult( new StreamResult( System.out ),
63 * configuration );
64 * </pre>
65 *
66 * <p>The developer can also output to SAX stream or DOM trees
67 * via {@link javax.xml.transform.sax.SAXResult} and
68 * {@link javax.xml.transform.dom.DOMResult}.</p>
69 *
70 * @param result the result object to serialize configuration to
71 * @param configuration the configuration
72 * @throws Exception if unable to serialize configuration
73 */
74 public static void serializeToResult( final Result result,
75 final Configuration configuration )
76 throws Exception
77 {
78 final SAXTransformerFactory factory =
79 (SAXTransformerFactory)TransformerFactory.newInstance();
80 final TransformerHandler handler = factory.newTransformerHandler();
81
82 final Properties format = new Properties();
83 format.put( OutputKeys.METHOD, "xml" );
84 format.put( OutputKeys.INDENT, "yes" );
85 handler.setResult( result );
86 handler.getTransformer().setOutputProperties( format );
87
88 final SAXConfigurationSerializer serializer = new SAXConfigurationSerializer();
89 serializer.serialize( configuration, handler );
90 }
91
92 /***
93 * Create a configuration object from specified XML InputSource.
94 *
95 * @param input the InputSource
96 * @return the configuration object
97 * @throws Exception if unable to create configuration object
98 * from input
99 */
100 public static Configuration buildFromXML( final InputSource input )
101 throws Exception
102 {
103 final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
104 saxParserFactory.setNamespaceAware( false );
105 final SAXParser saxParser = saxParserFactory.newSAXParser();
106 final SAXConfigurationHandler handler = new SAXConfigurationHandler();
107 saxParser.parse( input, handler );
108 return handler.getConfiguration();
109 }
110
111 /***
112 * Convert specified Element into a configuration object.
113 *
114 * @param element the Element
115 * @return the Configuration object
116 */
117 public static Configuration toConfiguration( final Element element )
118 {
119 return toConfiguration( element, ROOT_PATH );
120 }
121
122 /***
123 * Internal utility method to convert specified Element into
124 * a configuration object.
125 *
126 * @param element the Element
127 * @param parentPath the path to root of document
128 * @return the Configuration object
129 */
130 private static Configuration toConfiguration( final Element element,
131 final String parentPath )
132 {
133 final DefaultConfiguration configuration =
134 new DefaultConfiguration( element.getNodeName(), ELEMENT_LOCATION, parentPath );
135 final NamedNodeMap attributes = element.getAttributes();
136 final int length = attributes.getLength();
137 for( int i = 0; i < length; i++ )
138 {
139 final Node node = attributes.item( i );
140 final String name = node.getNodeName();
141 final String value = node.getNodeValue();
142 configuration.setAttribute( name, value );
143 }
144
145 final String childPath =
146 generatePathName( parentPath, configuration.getName() );
147
148 String content = null;
149 final NodeList nodes = element.getChildNodes();
150 final int count = nodes.getLength();
151 for( int i = 0; i < count; i++ )
152 {
153 final Node node = nodes.item( i );
154 if( node instanceof Element )
155 {
156 final Configuration child = toConfiguration( (Element)node, childPath );
157 configuration.addChild( child );
158 }
159 else if( node instanceof Text )
160 {
161 final Text data = (Text)node;
162 if( null != content )
163 {
164 content += data.getData();
165 }
166 else
167 {
168 content = data.getData();
169 }
170 }
171 }
172
173 if( null != content )
174 {
175 configuration.setValue( content );
176 }
177
178 return configuration;
179 }
180
181 /***
182 * Add in utity method to generate path string from parent.
183 *
184 * @param path parents path
185 * @param name parents name
186 * @return the path string
187 */
188 static String generatePathName( final String path,
189 final String name )
190 {
191 if( ROOT_PATH.equals( path ) )
192 {
193 return name;
194 }
195 else
196 {
197 return path + PATH_SEPARATOR + name;
198 }
199 }
200
201 /***
202 * Convert specified Configuration object into a Element.
203 *
204 * @param configuration the Configuration
205 * @return the Element object
206 */
207 public static Element toElement( final Configuration configuration )
208 {
209 try
210 {
211 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
212 final DocumentBuilder builder = factory.newDocumentBuilder();
213 final Document document = builder.newDocument();
214
215 return createElement( document, configuration );
216 }
217 catch( final Throwable t )
218 {
219 throw new IllegalStateException( t.toString() );
220 }
221 }
222
223 /***
224 * Internal helper method to convert specified Configuration object
225 * into a Element.
226 *
227 * @param document the owner document
228 * @param configuration the Configuration
229 * @return the Element object
230 */
231 private static Element createElement( final Document document,
232 final Configuration configuration )
233 {
234 final Element element = document.createElement( configuration.getName() );
235
236 final String content = configuration.getValue( null );
237 if( null != content )
238 {
239 final Text child = document.createTextNode( content );
240 element.appendChild( child );
241 }
242
243 final String[] names = configuration.getAttributeNames();
244 for( int i = 0; i < names.length; i++ )
245 {
246 final String name = names[ i ];
247 final String value = configuration.getAttribute( name, null );
248 element.setAttribute( name, value );
249 }
250 final Configuration[] children = configuration.getChildren();
251 for( int i = 0; i < children.length; i++ )
252 {
253 final Element child = createElement( document, children[ i ] );
254 element.appendChild( child );
255 }
256 return element;
257 }
258
259 /***
260 * Test if two configuration objects are equal. To be equal
261 * the configuration objects must have equal child configuration
262 * objects in identical orders or identical content values and
263 * must have the same attributes with the same values.
264 *
265 * @param configuration1 a configuration object
266 * @param configuration2 a configuration object
267 * @return true if the configuration objects are equal
268 */
269 public static boolean equals( final Configuration configuration1,
270 final Configuration configuration2 )
271 {
272 final String name1 = configuration1.getName();
273 final String name2 = configuration2.getName();
274 if( !name1.equals( name2 ) )
275 {
276 return false;
277 }
278
279 final Configuration[] children1 = configuration1.getChildren();
280 final Configuration[] children2 = configuration2.getChildren();
281 if( children1.length != children2.length )
282 {
283 return false;
284 }
285 else
286 {
287 for( int i = 0; i < children1.length; i++ )
288 {
289 if( !equals( children1[ i ], children2[ i ] ) )
290 {
291 return false;
292 }
293 }
294 }
295
296 final String[] names1 = configuration1.getAttributeNames();
297 final String[] names2 = configuration2.getAttributeNames();
298 if( names1.length != names2.length )
299 {
300 return false;
301 }
302 else
303 {
304 for( int i = 0; i < names1.length; i++ )
305 {
306 final String value1 =
307 configuration1.getAttribute( names1[ i ], null );
308 final String value2 =
309 configuration2.getAttribute( names1[ i ], null );
310 if( !value1.equals( value2 ) )
311 {
312 return false;
313 }
314 }
315 }
316
317 final String value1 = configuration1.getValue( null );
318 final String value2 = configuration2.getValue( null );
319 if( null == value1 && null == value2 )
320 {
321 return true;
322 }
323 else if( null != value1 && null != value2 )
324 {
325 return value1.equals( value2 );
326 }
327 else
328 {
329 return false;
330 }
331 }
332 }