View Javadoc

1   /*
2    * Copyright (C) The DNA Group. All rights reserved.
3    *
4    * This software is published under the terms of the DNA
5    * Software License version 1.1, a copy of which has been included
6    * with this distribution in the LICENSE.txt file.
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 }