View Javadoc

1   /*
2    * Copyright 2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License")
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.configuration;
18  
19  import java.util.Iterator;
20  
21  import org.apache.commons.collections.Transformer;
22  import org.apache.commons.collections.iterators.TransformIterator;
23  
24  /***
25   * A subset of another configuration. The new Configuration object contains
26   * every key from the parent Configuration that starts with prefix. The prefix
27   * is removed from the keys in the subset.
28   *
29   * @see Configuration#subset(String)
30   *
31   * @author Emmanuel Bourg
32   * @version $Revision: 1.6 $, $Date: 2004/10/05 21:17:25 $
33   */
34  public class SubsetConfiguration extends AbstractConfiguration
35  {
36      /*** The parent configuration. */
37      protected Configuration parent;
38  
39      /*** The prefix used to select the properties. */
40      protected String prefix;
41  
42      /*** The prefix delimiter */
43      protected String delimiter;
44  
45      /***
46       * Create a subset of the specified configuration
47       *
48       * @param parent The parent configuration
49       * @param prefix The prefix used to select the properties
50       */
51      public SubsetConfiguration(Configuration parent, String prefix)
52      {
53          this.parent = parent;
54          this.prefix = prefix;
55      }
56  
57      /***
58       * Create a subset of the specified configuration
59       *
60       * @param parent    The parent configuration
61       * @param prefix    The prefix used to select the properties
62       * @param delimiter The prefix delimiter
63       */
64      public SubsetConfiguration(Configuration parent, String prefix, String delimiter)
65      {
66          this.parent = parent;
67          this.prefix = prefix;
68          this.delimiter = delimiter;
69      }
70  
71      /***
72       * Return the key in the parent configuration associated to the specified
73       * key in this subset.
74       *
75       * @param key The key in the subset.
76       */
77      protected String getParentKey(String key)
78      {
79          if ("".equals(key) || key == null)
80          {
81              return prefix;
82          }
83          else
84          {
85              return delimiter == null ? prefix + key : prefix + delimiter + key;
86          }
87      }
88  
89      /***
90       * Return the key in the subset configuration associated to the specified
91       * key in the parent configuration.
92       *
93       * @param key The key in the parent configuration.
94       */
95      protected String getChildKey(String key)
96      {
97          if (!key.startsWith(prefix))
98          {
99              throw new IllegalArgumentException("The parent key '" + key + "' is not in the subset.");
100         }
101         else
102         {
103             String modifiedKey = null;
104             if (key.length() == prefix.length())
105             {
106                 modifiedKey = "";
107             }
108             else
109             {
110                 int i = prefix.length() + (delimiter != null ? delimiter.length() : 0);
111                 modifiedKey = key.substring(i);
112             }
113 
114             return modifiedKey;
115         }
116     }
117 
118     /***
119      * Return the parent configuation for this subset.
120      */
121     public Configuration getParent()
122     {
123         return parent;
124     }
125 
126     /***
127      * Return the prefix used to select the properties in the parent configuration.
128      */
129     public String getPrefix()
130     {
131         return prefix;
132     }
133 
134     /***
135      * Set the prefix used to select the properties in the parent configuration.
136      */
137     public void setPrefix(String prefix)
138     {
139         this.prefix = prefix;
140     }
141 
142     /***
143      * {@inheritDoc}
144      */
145     public Configuration subset(String prefix)
146     {
147         return parent.subset(getParentKey(prefix));
148     }
149 
150     /***
151      * {@inheritDoc}
152      */
153     public boolean isEmpty()
154     {
155         return !getKeys().hasNext();
156     }
157 
158     /***
159      * {@inheritDoc}
160      */
161     public boolean containsKey(String key)
162     {
163         return parent.containsKey(getParentKey(key));
164     }
165 
166     /***
167      * {@inheritDoc}
168      */
169     public void addPropertyDirect(String key, Object value)
170     {
171         parent.addProperty(getParentKey(key), value);
172     }
173 
174     /***
175      * {@inheritDoc}
176      */
177     public void setProperty(String key, Object value)
178     {
179         parent.setProperty(getParentKey(key), value);
180     }
181 
182     /***
183      * {@inheritDoc}
184      */
185     public void clearProperty(String key)
186     {
187         parent.clearProperty(getParentKey(key));
188     }
189 
190     /***
191      * {@inheritDoc}
192      */
193     public Object getPropertyDirect(String key)
194     {
195         return parent.getProperty(getParentKey(key));
196     }
197 
198     /***
199      * {@inheritDoc}
200      */
201     public Iterator getKeys(String prefix)
202     {
203         return new TransformIterator(parent.getKeys(getParentKey(prefix)), new Transformer()
204         {
205             public Object transform(Object obj)
206             {
207                 return getChildKey((String) obj);
208             }
209         });
210     }
211 
212     /***
213      * {@inheritDoc}
214      */
215     public Iterator getKeys()
216     {
217         return new TransformIterator(parent.getKeys(prefix), new Transformer()
218         {
219             public Object transform(Object obj)
220             {
221                 return getChildKey((String) obj);
222             }
223         });
224     }
225 
226     /***
227      * {@inheritDoc}
228      */
229     protected String interpolate(String base)
230     {
231         if (delimiter == null && "".equals(prefix))
232         {
233             return super.interpolate(base);
234         }
235         else
236         {
237             SubsetConfiguration config = new SubsetConfiguration(parent, "");
238             return config.interpolate(base);
239         }
240     }
241 
242     /***
243      * {@inheritDoc}
244      *
245      * Change the behaviour of the parent configuration if it supports this feature.
246      */
247     public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)
248     {
249         if (parent instanceof AbstractConfiguration)
250         {
251             ((AbstractConfiguration) parent).setThrowExceptionOnMissing(throwExceptionOnMissing);
252         }
253         else
254         {
255             super.setThrowExceptionOnMissing(throwExceptionOnMissing);
256         }
257     }
258 
259     /***
260      * {@inheritDoc}
261      *
262      * The subset inherits this feature from its parent if it supports this feature.
263      */
264     public boolean isThrowExceptionOnMissing()
265     {
266         if (parent instanceof AbstractConfiguration)
267         {
268             return ((AbstractConfiguration) parent).isThrowExceptionOnMissing();
269         }
270         else
271         {
272             return super.isThrowExceptionOnMissing();
273         }
274     }
275 }