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 * <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 }