1   /**
2    * Distribution License:
3    * JSword is free software; you can redistribute it and/or modify it under
4    * the terms of the GNU Lesser General Public License, version 2.1 as published by
5    * the Free Software Foundation. This program is distributed in the hope
6    * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7    * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8    * See the GNU Lesser General Public License for more details.
9    *
10   * The License is available on the internet at:
11   *       http://www.gnu.org/copyleft/lgpl.html
12   * or by writing to:
13   *      Free Software Foundation, Inc.
14   *      59 Temple Place - Suite 330
15   *      Boston, MA 02111-1307, USA
16   *
17   * Copyright: 2008
18   *     The copyright to this program is held by it's authors.
19   *
20   * ID: $Id: PropertyMap.java 2090 2011-03-07 04:13:05Z dmsmith $
21   */
22  package org.crosswire.common.util;
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.OutputStream;
27  import java.util.Enumeration;
28  import java.util.LinkedHashMap;
29  import java.util.Properties;
30  
31  
32  /**
33   * A PropertyMap is a Map<String,String> sitting over top a Property file.
34   * As such it must be defined in the same way as a java.lang.Properties expects.
35   *
36   * @see java.lang.Properties
37   * @see gnu.lgpl.License for license details.<br>
38   *      The copyright to this program is held by it's authors.
39   * @author DM Smith [dmsmith555 at yahoo dot com]
40   */
41  /**
42   *
43   *
44   * @see gnu.lgpl.License for license details.<br>
45   *      The copyright to this program is held by it's authors.
46   * @author DM Smith [dmsmith555 at yahoo dot com]
47   */
48  public class PropertyMap extends LinkedHashMap<String, String> {
49      /**
50       * Creates an empty property list with no default values.
51       */
52      public PropertyMap() {
53          this(null);
54      }
55  
56      /**
57       * Creates an empty property map with the specified defaults.
58       *
59       * @param   defaults   the defaults.
60       */
61      public PropertyMap(PropertyMap defaults) {
62          this.defaults = defaults;
63      }
64  
65      /**
66       * Searches for the property with the specified key in this property list.
67       * If the key is not found in this property list, the default property list,
68       * and its defaults, recursively, are then checked. The method returns
69       * <code>null</code> if the property is not found.
70       *
71       * @param   key   the lookup key.
72       * @return  the value in this property list with the specified key value.
73       * @see     java.lang.Properties#setProperty
74       * @see     #defaults
75       */
76      public String get(String key) {
77          String value = super.get(key);
78          return ((value == null) && (defaults != null)) ? defaults.get(key) : value;
79      }
80  
81      /**
82       * Searches for the property with the specified key in this property list.
83       * If the key is not found in this property list, the default property list,
84       * and its defaults, recursively, are then checked. The method returns the
85       * default value argument if the property is not found.
86       *
87       * @param   key            the lookup key.
88       * @param   defaultValue   a default value.
89       *
90       * @return  the value in this property list with the specified key value.
91       * @see     java.lang.Properties#setProperty
92       * @see     #defaults
93       */
94      public String get(String key, String defaultValue) {
95          String value = get(key);
96          return value == null ? defaultValue : value;
97      }
98  
99      /**
100      * Merely a call to {@link #put(String, String)}, provided as
101      * a simple way to migrate from {@link java.lang.Properties}.
102      *
103      * @param key the key to be placed into this property list.
104      * @param value the value corresponding to <tt>key</tt>.
105      * @return     the previous value of the specified key in this property
106      *             list, or <code>null</code> if it did not have one.
107      * @deprecated use {@link #put(String, String)} instead
108      */
109     @Deprecated
110     public String setProperty(String key, String value) {
111         return put(key, value);
112     }
113 
114     /**
115      * Merely a call to {@link #get(String)}, provided as
116      * a simple way to migrate from {@link java.lang.Properties}.
117      * 
118      * @param key the lookup key
119      * @return  the value in this property list with the specified key value.
120      * @deprecated use {@link @get(String)} instead
121      */
122     @Deprecated
123     public String getProperty(String key) {
124         return get(key);
125     }
126 
127     /**
128      * Merely a call to {@link #get(String, String)}, provided as
129      * a simple way to migrate from {@link java.lang.Properties}.
130      * @param   key            the lookup key.
131      * @param   defaultValue   a default value.
132      * @return  the value in this property list with the specified key value.
133      * @deprecated use {@link #get(String, String)} instead
134      */
135     @Deprecated
136     public String getProperty(String key, String defaultValue) {
137         return get(key, defaultValue);
138     }
139 
140     /**
141      * Reads a property list (key and element pairs) from the input
142      * byte stream. The input stream is in a simple line-oriented
143      * format as specified in
144      * {@link java.lang.Properties#load(java.io.InputStream) load(InputStream)} and is assumed to use
145      * the ISO 8859-1 character encoding; that is each byte is one Latin1
146      * character. Characters not in Latin1, and certain special characters,
147      * are represented in keys and elements using
148      * <a href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.3">Unicode escapes</a>.
149      * <p>
150      * The specified stream remains open after this method returns.
151      *
152      * @param      inStream   the input stream.
153      * @exception  IOException  if an error occurred when reading from the
154      *             input stream.
155      * @throws     IllegalArgumentException if the input stream contains a
156      *         malformed Unicode escape sequence.
157      * @since 1.2
158      */
159     public void load(InputStream inStream) throws IOException {
160         Properties prop = new Properties();
161         prop.load(inStream);
162         for (Enumeration<Object> e = prop.keys(); e.hasMoreElements(); ) {
163             Object k = e.nextElement();
164             Object v = prop.get(k);
165             if (k instanceof String && v instanceof String) {
166                 put((String) k, (String) v);
167             }
168         }
169     }
170 
171     /**
172      * Writes this property list (key and element pairs) in this
173      * <code>PropertyMap</code> table to the output stream in a format suitable
174      * for loading into a <code>PropertyMap</code> table using the
175      * {@link #load(InputStream) load(InputStream)} method.
176      * <p>
177      * Properties from the defaults table of this <code>PropertyMap</code>
178      * table (if any) are <i>not</i> written out by this method.
179      * <p>
180      * This method outputs the comments, properties keys and values in 
181      * the same format as specified in
182      * {@link java.lang.Properties#store(java.io.OutputStream, java.lang.String) store(Writer)},
183      * <p>
184      * After the entries have been written, the output stream is flushed.  
185      * The output stream remains open after this method returns.
186      * <p>
187      * @param   out      an output stream.
188      * @param   comments   a description of the property list.
189      * @exception  IOException if writing this property list to the specified
190      *             output stream throws an <tt>IOException</tt>.
191      * @exception  NullPointerException  if <code>out</code> is null.
192      * @since 1.2
193      */
194     public void store(OutputStream out, String comments) throws IOException {
195         Properties temp = new Properties();
196         temp.putAll(this);
197         temp.store(out, comments);
198     }
199 
200     /**
201      * Default values for any keys not found in this property map.
202      */
203     private PropertyMap defaults;
204 
205     /**
206      * The serialization id
207      */
208     private static final long serialVersionUID = 2821277155924802795L;
209 }
210