Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/gersonworks/xml/util/XMLProperties.java


1   /*
2    * XMLProperties library - A utility class which reads property lists from
3    * an XML document
4    * Copyright (C) 21 January 2004 Gerson Galang
5    * This library is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public
7    * License as published by the Free Software Foundation; either
8    * version 2.1 of the License, or (at your option) any later version.
9    *
10   * This library is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   * Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public
16   * License along with this library; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   * For any questions or suggestions, you can email me at :
19   * Email: gerson721@gawab.com
20  */
21  
22  package com.gersonworks.xml.util;
23  
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.HashMap;
27  import java.util.Set;
28  import java.util.Properties;
29  import java.util.Map.Entry;
30  
31  import java.io.File;
32  import java.io.InputStream;
33  import java.io.OutputStream;
34  import java.io.Writer;
35  import java.io.PrintWriter;
36  
37  /**
38   * The XMLProperties class represents a way of storing and retrieving properties
39   * data into and from an XML file. Each property key corresponds to an
40   * XMLPropertyValues object which may contain one or more property values.
41   * <p>
42   * Since the idea of implementing this class came from how the
43   * java.util.Properties class works, most of the methods provided by this class
44   * are similar to the functionality provided by the java.util.Properties'
45   * methods.
46   * <p>
47   * The main difference of this class from java.util.Properties class is that
48   * a property in XMLProperties may contain one or more property values. Another
49   * difference is that this class now reads in an XML document.
50   * <p>
51   * The order of how the keys were originally sorted cannot be guaranteed when
52   * the loaded property list is stored back into the XML properties file. It was
53   * implemented this way for simplicity. What I can only guarantee is that all
54   * the keys and its corresponding value/s will be in the properties file.
55   * <p>
56   * The XMLProperties class reads an XML document of the following format:
57   *
58   * <pre>
59   *  &lt;properties&gt;
60   *  &lt;!-- This is my XML configuration file --&gt;
61   *  &nbsp;&nbsp;&lt;property key=&quot;key1&quot;&gt;
62   *  &nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;key1Value1&lt;/value&gt;
63   *  &nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;key1Value2&lt;/value&gt;
64   *  &nbsp;&nbsp;&lt;/property&gt;
65   *  &nbsp;&nbsp;&lt;property key=&quot;key2&quot;&gt;
66   *  &nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;&lt;/value&gt;
67   *  &nbsp;&nbsp;&lt;/property&gt;
68   *  &lt;/properties&gt;
69   * </pre>
70   *
71   * XMLProperties can only recognize the following elements:
72   * <p>
73   *   <ol>
74   *     <li>
75   *        <tt>properties</tt> - is the <tt>root</tt> element of the XML
76   *        properties document. This element is usually composed of more than
77   *        one <tt>property</tt> elements but it is also possible for this
78   *        element to be an empty element.
79   *     </li>
80   *     <li>
81   *        <tt>property</tt> - is the child of the properties element and the
82   *        parent of the value element. The <tt>property</tt> element has a
83   *        <tt>key</tt> attribute which serves as the key to the property values.
84   *        The <tt>property</tt> element is only allowed to have the
85   *        <tt>value</tt> element as its child. It cannot contain any text (or
86   *        simple) contents under it.
87   *      </li>
88   *      <li>
89   *        <tt>value</tt> - is the child of the property element. There should be
90   *        at least one <tt>value</tt> element for each <tt>property</tt>
91   *        element. The <tt>value</tt> element can be an empty element but it
92   *        cannot contain any other elements except a text (or a simple) content.
93   *     </li>
94   *   </ol>
95   * <p>
96   * The rules specified by each element should be followed to avoid
97   * XMLPropertiesFormatException to be thrown. This exception is always thrown
98   * whenever an unrecognized element is inserted into the XML properties
99   * document.
100  *
101  * <p>Copyright: Copyright (c) 21 January 2004</p>
102  * @author Gerson Galang
103  * @version 1.1, 29 January 2004
104  * @see java.util.Properties
105  */
106 public class XMLProperties {
107 
108   // the map wrapped by this class
109   private Map xmlProperties;
110 
111   protected XMLProperties defaultXMLProps;
112 
113   /**
114    * Creates an empty property list with no defaults.
115    */
116   public XMLProperties() {
117     xmlProperties = new HashMap();
118     defaultXMLProps = null;
119   }
120 
121   /**
122    * Creates an empty property list with a default XMLProperties.
123    *
124    * @param defaultXMLProps the default XMLProperties
125    * @since XMLProperties version 1.1
126    */
127   public XMLProperties(XMLProperties defaultXMLProps) {
128     xmlProperties = new HashMap();
129     this.defaultXMLProps = defaultXMLProps;
130   }
131 
132   /**
133    * Creates an empty property list with a default java.util.Properties.
134    *
135    * @param defaultJavaProps the default java.util.Properties
136    * @since XMLProperties version 1.1
137    */
138   public XMLProperties(Properties defaultJavaProps) {
139     xmlProperties = new HashMap();
140     defaultXMLProps = new XMLProperties();
141     Set mapEntrySet = defaultJavaProps.entrySet();
142     // Map's putAll() method cannot be used in adding the properties
143     // into this class' property list because java.util.Properties has
144     // a different format for its property value.
145     for (Iterator mapIterator = mapEntrySet.iterator();
146          mapIterator.hasNext(); ) {
147       Map.Entry mapEntry = (Map.Entry)mapIterator.next();
148       defaultXMLProps.setProperty(mapEntry.getKey().toString(),
149                   mapEntry.getValue().toString());
150     }
151   }
152 
153   /**
154    * Locates the property values for the corresponding key.
155    *
156    * @param key the property key.
157    * @return the property values of the input key, or null if key is not found.
158    */
159   public XMLPropertyValues getPropertyValues(String key) {
160     return getPropertyValues(key, null);
161   }
162 
163   /**
164    * Locates the property values for the corresponding key. If the key is not
165    * found, the search returns the default XMLPropertyValues parameter of this
166    * method.
167    *
168    * @param key the property key.
169    * @param defaultValues the default XMLPropertyValues object to be returned
170    * if the key is not found.
171    * @return the property values of the input key or the defaultValues if the
172    * key is not found.
173    */
174   public XMLPropertyValues getPropertyValues(String key,
175                                          XMLPropertyValues defaultValues) {
176     XMLPropertyValues temp = (XMLPropertyValues)xmlProperties.get(key);
177     if (temp == null) {
178       if (defaultXMLProps != null) {
179         // check defaultXMLProps. it might contain the property values for
180         // the specified property key
181         return defaultXMLProps.getPropertyValues(key, defaultValues);
182       } else {
183         // if nothing is returned and defaultXMLProps is null, return
184         // defaultValues
185         return defaultValues;
186       }
187     }
188     return temp;
189   }
190 
191   /**
192    * Locates the property value for the corresponding key and property value's
193    * index. If the property key is found but the index is not within the
194    * property values' range, the method will throw an XMLPropertiesException.
195    *
196    * @param key the property key.
197    * @param index a number from 0 to XMLProperyValues.size() - 1. This is the
198    * index of the value in the property values collection.
199    * @return the property value which corresponds to the given key and index.
200    */
201   public String getPropertyValue(String key, int index)
202       throws XMLPropertiesException {
203     XMLPropertyValues temp = getPropertyValues(key);
204     if (temp == null) {
205       if (defaultXMLProps != null) {
206         // check defaultXMLProps. it might contain the property values for
207         // the specified property key
208         return defaultXMLProps.getPropertyValue(key, index);
209       } else {
210         // return null if key has not been found
211         return null;
212       }
213     }
214     // check if index is within the property values' range
215     try {
216       return temp.getValue(index);
217     } catch (IndexOutOfBoundsException e) {
218       // wrap IndexOutOfBoundsException in XMLPropertiesException
219       throw new XMLPropertiesException("Index is not within the range");
220     }
221   }
222 
223   /**
224    * Locates the property value for the corresponding key and property value's
225    * index. This method will return the defaultValue if the property key is not
226    * found, or if the value's index is not within the range of the found
227    * propertyValues.
228    *
229    * @param key the property key.
230    * @param index is a number from 0 to XMLProperyValues.size() - 1. This is the
231    * index of the value in the property values collection.
232    * @param defaultValue the default value to be returned.
233    * @return the found value, or the default value if the key is not found.
234    */
235   public String getPropertyValue(String key, int index,
236                                               String defaultValue) {
237     XMLPropertyValues temp = getPropertyValues(key);
238     if (temp == null) {
239       if (defaultXMLProps != null) {
240         // check defaultXMLProps. it might contain the property values for
241         // the specified property key
242         return defaultXMLProps.getPropertyValue(key, index, defaultValue);
243       } else {
244         // return null if key has not been found
245         return defaultValue;
246       }
247     }
248     // check if index is within the list's range
249     try {
250       return temp.getValue(index);
251     } catch (IndexOutOfBoundsException e) {
252       // the value at index has not been found, just return the defaultValue
253       return defaultValue;
254     }
255   }
256 
257   /**
258    * Reads the property list key-value/s pair from the properties file.
259    *
260    * @param propertiesFile the XMLProperties file.
261    */
262   public synchronized void load(File propertiesFile) {
263     XMLPropertiesHandler handler = new XMLPropertiesHandler(propertiesFile);
264     xmlProperties = handler.getProperties();
265   }
266 
267   /**
268    * Reads the property list of key-value/s pair from the properties URI.
269    *
270    * @param propertiesURI the URI of the XMLProperties.
271    */
272   public synchronized void load(String propertiesURI) {
273     XMLPropertiesHandler handler = new XMLPropertiesHandler(propertiesURI);
274     xmlProperties = handler.getProperties();
275   }
276 
277   /**
278    * Reads the property list of key-value/s pairs from the input stream
279    *
280    * @param inStream the InputStream containing the XMLProperties.
281    * @since XMLProperties version 1.1
282    */
283   public synchronized void load(InputStream inStream) {
284     XMLPropertiesHandler handler = new XMLPropertiesHandler(inStream);
285     xmlProperties = handler.getProperties();
286   }
287 
288   /**
289    * Returns an iterator of all the keys in the property list.
290    *
291    * @return an iterator of all the keys in the property list.
292    */
293   public synchronized Iterator getPropertyNames() {
294     return xmlProperties.keySet().iterator();
295   }
296 
297   /**
298    * Puts the key-value pair parameter into the property list. If the argument
299    * key exists in the property list, the old XMLPropertyValues object will
300    * be returned, otherwise null will be returned.
301    *
302    * @param key the property key.
303    * @param value the property value.
304    * @return the old XMLPropertyValues object if key used to be in the property
305    * list, or null otherwise.
306    */
307   public synchronized XMLPropertyValues setProperty(String key, String value) {
308     // add the value to the XMLPropertyValues object first
309     XMLPropertyValues tempValues = new XMLPropertyValues();
310     tempValues.addValue(value);
311     return (XMLPropertyValues)xmlProperties.put(key, tempValues);
312   }
313 
314   /**
315    * Puts the key-values pair parameter into the property list. If the argument
316    * key exists in the property list, the old XMLPropertyValues object will
317    * be returned, otherwise null will be returned.
318    *
319    * @param key the property key
320    * @param values the property values
321    * @return the old XMLPropertyValues object if key used to be in the property
322    * list, or null otherwise.
323    */
324   public synchronized XMLPropertyValues setProperty(String key,
325                           XMLPropertyValues values) {
326     return (XMLPropertyValues)xmlProperties.put(key, values);
327   }
328 
329   /**
330    * Writes the property list wrapped by this class into a Writer object.
331    *
332    * @param writer a Writer object.
333    */
334   public synchronized void store(Writer writer) {
335     store(writer, null);
336   }
337 
338   /**
339    * Writes the property list wrapped by this class into the output stream.
340    *
341    * @param outStream the output stream.
342    * @since XMLProperties version 1.1
343    */
344   public synchronized void store(OutputStream outStream) {
345     store(new PrintWriter(outStream), null);
346   }
347 
348   /**
349    * Writes the property list wrapped by this class into the output stream.
350    * This method adds additional header information to the output through the
351    * use of the headerComment.
352    *
353    * @param outStream the output stream.
354    * @param headerComment the header comment going to be written in the output
355    * stream.
356    * @since XMLProperties version 1.1
357    */
358   public synchronized void store(OutputStream outStream, String headerComment) {
359     store(new PrintWriter(outStream), headerComment);
360   }
361 
362 
363   /**
364    * Writes the property list wrapped by this class into a Writer object.
365    * This method adds additional header information to the output through the
366    * use of the headerComment.
367    *
368    * @param writer a Writer object.
369    * @param headerComment the header comment going to be written in the output.
370    */
371   public synchronized void store(Writer writer, String headerComment) {
372     PrintWriter printWriter = new PrintWriter(writer);
373     printWriter.println("<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?> ");
374     if (headerComment != null) {
375       printWriter.println("<!-- " + headerComment + " -->");
376     }
377     printWriter.println("<properties>");
378     Set keySet = xmlProperties.keySet();
379     for (Iterator keyIter = keySet.iterator(); keyIter.hasNext(); ) {
380       String propertyKey = keyIter.next().toString();
381       XMLPropertyValues propertyValues =
382           (XMLPropertyValues)xmlProperties.get(propertyKey);
383       printWriter.println("  <property key=\"" + propertyKey + "\">");
384       for (Iterator valueIter = propertyValues.iterator(); valueIter.hasNext(); ) {
385         // modified this section of the code on version 1.2
386         // reason: i just like the xml properties document in this format
387         printWriter.println("    <value>" + valueIter.next() + "</value>");
388       }
389       printWriter.println("  </property>");
390     }
391     printWriter.println("</properties>");
392     printWriter.flush();
393   }
394 
395 
396 
397 
398   /**
399    * Returns an iterator of all XMLPropertyValues objects in the property list.
400    *
401    * @return an iterator of all the XMLPropertyValues objects in the property
402    * list.
403    * @since XMLProperties version 1.1
404    */
405   public synchronized Iterator getPropertyValuesIterator() {
406     return xmlProperties.values().iterator();
407   }
408 
409   /**
410    * This method converts this class to its equivalent java.util.Properties
411    * object. It should be noted that only the first element (or propery value)
412    * of all the XMLPropertyValues objects in this class' property list will
413    * be stored in the output java.util.Properties object. The property list
414    * of the defaults are also not stored in the output java.util.Properties
415    * object.
416    *
417    * @return the equivalent java.util.Properties object of this object.
418    * @since XMLProperties version 1.1
419    */
420   public synchronized Properties getJavaUtilProperties() {
421     Properties tempProperties = new Properties();
422     Set keySet = xmlProperties.keySet();
423     for (Iterator keyIter = keySet.iterator(); keyIter.hasNext(); ) {
424       String propertyKey = keyIter.next().toString();
425       // Map's putAll() method cannot be used because only the first value
426       // of the propertyValues object should be added to java.util.Properties'
427       // property list.
428       tempProperties.setProperty(propertyKey, getPropertyValue(propertyKey, 0));
429     }
430     return tempProperties;
431   }
432 
433   /**
434    * Removes all the entries from the property list.
435    *
436    * @since XMLProperties version 1.1
437    */
438   public void clear() {
439     xmlProperties.clear();
440   }
441 
442   /**
443    * Checks if the specified key is in the property list.
444    *
445    * @param key the key to be checked.
446    * @return true if the key is in the property list, false otherwise.
447    * @since XMLProperties version 1.1
448    */
449   public boolean containsKey(String key) {
450     return xmlProperties.containsKey(key);
451   }
452 
453   /**
454    * Returns true if XMLProperties maps one or more keys for this value.
455    *
456    * @param value the value stored in an XMLPropertyValues object
457    * @return true if the value is found in any of the property values mapped
458    * by any of the keys in the property list.
459    * @since XMLProperties version 1.1
460    */
461   public synchronized boolean containsValue(String value) {
462     // go through all the property values objects stored by xmlProperties
463     for (Iterator propsValuesIter = getPropertyValuesIterator();
464          propsValuesIter.hasNext(); ) {
465       for (Iterator propsValueIter =
466            ((XMLPropertyValues)propsValuesIter.next()).iterator();
467            propsValueIter.hasNext(); ) {
468         if (propsValueIter.next().toString().equals(value)) {
469           return true;
470         }
471       }
472     }
473     return false;
474   }
475 
476   /**
477    * Returns true if the property list is empty.
478    *
479    * @return true if the property list is empty, false otherwise.
480    * @since XMLProperties version 1.1
481    */
482   public boolean isEmpty() {
483     return xmlProperties.isEmpty();
484   }
485 
486   /**
487    * Removes the property specified by the property key.
488    *
489    * @param key the key of the property to be removed
490    * @return the XMLPropertyValues object mapped by the specified key, null
491    * othewise.
492    * @since XMLProperties version 1.1
493    */
494   public XMLPropertyValues remove(String key) {
495     return (XMLPropertyValues)xmlProperties.remove(key);
496   }
497 
498   /**
499    * Returns the number of elements in the property list.
500    *
501    * @return the number of entries in the property list.
502    * @since XMLProperties version 1.1
503    */
504   public int size() {
505     return xmlProperties.size();
506   }
507 
508 }