1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 }