View Javadoc

1   /*
2    * Copyright 2004-2005 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   * <p>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.</p>
28   * <p>It is usually not necessary to use this class directly. Instead the
29   * <code>{@link Configuration#subset(String)}</code> method should be used,
30   * which will return a correctly initialized instance.</p>
31   *
32   * @author Emmanuel Bourg
33   * @version $Revision: 156268 $, $Date: 2005-03-05 18:45:50 +0100 (Sa, 05 Mrz 2005) $
34   */
35  public class SubsetConfiguration extends AbstractConfiguration
36  {
37      /*** The parent configuration. */
38      protected Configuration parent;
39  
40      /*** The prefix used to select the properties. */
41      protected String prefix;
42  
43      /*** The prefix delimiter */
44      protected String delimiter;
45  
46      /***
47       * Create a subset of the specified configuration
48       *
49       * @param parent The parent configuration
50       * @param prefix The prefix used to select the properties
51       */
52      public SubsetConfiguration(Configuration parent, String prefix)
53      {
54          this.parent = parent;
55          this.prefix = prefix;
56      }
57  
58      /***
59       * Create a subset of the specified configuration
60       *
61       * @param parent    The parent configuration
62       * @param prefix    The prefix used to select the properties
63       * @param delimiter The prefix delimiter
64       */
65      public SubsetConfiguration(Configuration parent, String prefix, String delimiter)
66      {
67          this.parent = parent;
68          this.prefix = prefix;
69          this.delimiter = delimiter;
70      }
71  
72      /***
73       * Return the key in the parent configuration associated to the specified
74       * key in this subset.
75       *
76       * @param key The key in the subset.
77       */
78      protected String getParentKey(String key)
79      {
80          if ("".equals(key) || key == null)
81          {
82              return prefix;
83          }
84          else
85          {
86              return delimiter == null ? prefix + key : prefix + delimiter + key;
87          }
88      }
89  
90      /***
91       * Return the key in the subset configuration associated to the specified
92       * key in the parent configuration.
93       *
94       * @param key The key in the parent configuration.
95       */
96      protected String getChildKey(String key)
97      {
98          if (!key.startsWith(prefix))
99          {
100             throw new IllegalArgumentException("The parent key '" + key + "' is not in the subset.");
101         }
102         else
103         {
104             String modifiedKey = null;
105             if (key.length() == prefix.length())
106             {
107                 modifiedKey = "";
108             }
109             else
110             {
111                 int i = prefix.length() + (delimiter != null ? delimiter.length() : 0);
112                 modifiedKey = key.substring(i);
113             }
114 
115             return modifiedKey;
116         }
117     }
118 
119     /***
120      * Return the parent configuation for this subset.
121      */
122     public Configuration getParent()
123     {
124         return parent;
125     }
126 
127     /***
128      * Return the prefix used to select the properties in the parent configuration.
129      */
130     public String getPrefix()
131     {
132         return prefix;
133     }
134 
135     /***
136      * Set the prefix used to select the properties in the parent configuration.
137      */
138     public void setPrefix(String prefix)
139     {
140         this.prefix = prefix;
141     }
142 
143     /***
144      * {@inheritDoc}
145      */
146     public Configuration subset(String prefix)
147     {
148         return parent.subset(getParentKey(prefix));
149     }
150 
151     /***
152      * {@inheritDoc}
153      */
154     public boolean isEmpty()
155     {
156         return !getKeys().hasNext();
157     }
158 
159     /***
160      * {@inheritDoc}
161      */
162     public boolean containsKey(String key)
163     {
164         return parent.containsKey(getParentKey(key));
165     }
166 
167     /***
168      * {@inheritDoc}
169      */
170     public void addPropertyDirect(String key, Object value)
171     {
172         parent.addProperty(getParentKey(key), value);
173     }
174 
175     /***
176      * {@inheritDoc}
177      */
178     public void setProperty(String key, Object value)
179     {
180         parent.setProperty(getParentKey(key), value);
181     }
182 
183     /***
184      * {@inheritDoc}
185      */
186     public void clearProperty(String key)
187     {
188         parent.clearProperty(getParentKey(key));
189     }
190 
191     /***
192      * {@inheritDoc}
193      */
194     public Object getProperty(String key)
195     {
196         return parent.getProperty(getParentKey(key));
197     }
198 
199     /***
200      * {@inheritDoc}
201      */
202     public Iterator getKeys(String prefix)
203     {
204         return new TransformIterator(parent.getKeys(getParentKey(prefix)), new Transformer()
205         {
206             public Object transform(Object obj)
207             {
208                 return getChildKey((String) obj);
209             }
210         });
211     }
212 
213     /***
214      * {@inheritDoc}
215      */
216     public Iterator getKeys()
217     {
218         return new TransformIterator(parent.getKeys(prefix), new Transformer()
219         {
220             public Object transform(Object obj)
221             {
222                 return getChildKey((String) obj);
223             }
224         });
225     }
226 
227     /***
228      * {@inheritDoc}
229      */
230     protected String interpolate(String base)
231     {
232         if (delimiter == null && "".equals(prefix))
233         {
234             return super.interpolate(base);
235         }
236         else
237         {
238             SubsetConfiguration config = new SubsetConfiguration(parent, "");
239             return config.interpolate(base);
240         }
241     }
242 
243     /***
244      * {@inheritDoc}
245      *
246      * Change the behaviour of the parent configuration if it supports this feature.
247      */
248     public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)
249     {
250         if (parent instanceof AbstractConfiguration)
251         {
252             ((AbstractConfiguration) parent).setThrowExceptionOnMissing(throwExceptionOnMissing);
253         }
254         else
255         {
256             super.setThrowExceptionOnMissing(throwExceptionOnMissing);
257         }
258     }
259 
260     /***
261      * {@inheritDoc}
262      *
263      * The subset inherits this feature from its parent if it supports this feature.
264      */
265     public boolean isThrowExceptionOnMissing()
266     {
267         if (parent instanceof AbstractConfiguration)
268         {
269             return ((AbstractConfiguration) parent).isThrowExceptionOnMissing();
270         }
271         else
272         {
273             return super.isThrowExceptionOnMissing();
274         }
275     }
276 }