1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.configuration2;
19
20 import java.util.Iterator;
21 import java.util.Objects;
22
23 import org.apache.commons.configuration2.convert.ListDelimiterHandler;
24 import org.apache.commons.lang3.StringUtils;
25
26
27
28
29
30
31
32
33
34
35
36 public class SubsetConfiguration extends AbstractConfiguration {
37
38 protected Configuration parent;
39
40
41 protected String prefix;
42
43
44 protected String delimiter;
45
46
47
48
49
50
51
52
53 public SubsetConfiguration(final Configuration parent, final String prefix) {
54 this(parent, prefix, null);
55 }
56
57
58
59
60
61
62
63
64
65 public SubsetConfiguration(final Configuration parent, final String prefix, final String delimiter) {
66 this.parent = Objects.requireNonNull(parent, "parent");
67 this.prefix = prefix;
68 this.delimiter = delimiter;
69 initInterpolator();
70 }
71
72
73
74
75
76
77
78 protected String getParentKey(final String key) {
79 if (StringUtils.isEmpty(key)) {
80 return prefix;
81 }
82 return delimiter == null ? prefix + key : prefix + delimiter + key;
83 }
84
85
86
87
88
89
90
91 protected String getChildKey(final String key) {
92 if (!key.startsWith(prefix)) {
93 throw new IllegalArgumentException("The parent key '" + key + "' is not in the subset.");
94 }
95 String modifiedKey = null;
96 if (key.length() == prefix.length()) {
97 modifiedKey = "";
98 } else {
99 final int i = prefix.length() + (delimiter != null ? delimiter.length() : 0);
100 modifiedKey = key.substring(i);
101 }
102
103 return modifiedKey;
104 }
105
106
107
108
109
110
111 public Configuration getParent() {
112 return parent;
113 }
114
115
116
117
118
119
120 public String getPrefix() {
121 return prefix;
122 }
123
124
125
126
127
128
129 public void setPrefix(final String prefix) {
130 this.prefix = prefix;
131 }
132
133 @Override
134 public Configuration subset(final String prefix) {
135 return parent.subset(getParentKey(prefix));
136 }
137
138 @Override
139 protected boolean isEmptyInternal() {
140 return !getKeysInternal().hasNext();
141 }
142
143 @Override
144 protected boolean containsKeyInternal(final String key) {
145 return parent.containsKey(getParentKey(key));
146 }
147
148 @Override
149 public void addPropertyDirect(final String key, final Object value) {
150 parent.addProperty(getParentKey(key), value);
151 }
152
153 @Override
154 protected void clearPropertyDirect(final String key) {
155 parent.clearProperty(getParentKey(key));
156 }
157
158 @Override
159 protected Object getPropertyInternal(final String key) {
160 return parent.getProperty(getParentKey(key));
161 }
162
163 @Override
164 protected Iterator<String> getKeysInternal(final String prefix) {
165 return new SubsetIterator(parent.getKeys(getParentKey(prefix)));
166 }
167
168 @Override
169 protected Iterator<String> getKeysInternal() {
170 return new SubsetIterator(parent.getKeys(prefix, delimiter));
171 }
172
173
174
175
176
177
178 @Override
179 public void setThrowExceptionOnMissing(final boolean throwExceptionOnMissing) {
180 if (parent instanceof AbstractConfiguration) {
181 ((AbstractConfiguration) parent).setThrowExceptionOnMissing(throwExceptionOnMissing);
182 } else {
183 super.setThrowExceptionOnMissing(throwExceptionOnMissing);
184 }
185 }
186
187
188
189
190
191
192 @Override
193 public boolean isThrowExceptionOnMissing() {
194 if (parent instanceof AbstractConfiguration) {
195 return ((AbstractConfiguration) parent).isThrowExceptionOnMissing();
196 }
197 return super.isThrowExceptionOnMissing();
198 }
199
200
201
202
203
204 @Override
205 public ListDelimiterHandler getListDelimiterHandler() {
206 return parent instanceof AbstractConfiguration ? ((AbstractConfiguration) parent).getListDelimiterHandler() : super.getListDelimiterHandler();
207 }
208
209
210
211
212
213 @Override
214 public void setListDelimiterHandler(final ListDelimiterHandler listDelimiterHandler) {
215 if (parent instanceof AbstractConfiguration) {
216 ((AbstractConfiguration) parent).setListDelimiterHandler(listDelimiterHandler);
217 } else {
218 super.setListDelimiterHandler(listDelimiterHandler);
219 }
220 }
221
222
223
224
225
226
227 private void initInterpolator() {
228 getInterpolator().setParentInterpolator(getParent().getInterpolator());
229 }
230
231
232
233
234
235 private final class SubsetIterator implements Iterator<String> {
236
237 private final Iterator<String> parentIterator;
238
239
240
241
242
243
244 public SubsetIterator(final Iterator<String> it) {
245 parentIterator = it;
246 }
247
248
249
250
251
252
253 @Override
254 public boolean hasNext() {
255 return parentIterator.hasNext();
256 }
257
258
259
260
261
262
263
264 @Override
265 public String next() {
266 return getChildKey(parentIterator.next());
267 }
268
269
270
271
272 @Override
273 public void remove() {
274 parentIterator.remove();
275 }
276 }
277 }