1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.util.properties;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.LinkedHashMap;
23 import java.util.LinkedHashSet;
24 import java.util.Map;
25 import java.util.Properties;
26 import java.util.Set;
27
28 import org.apache.commons.lang.StringUtils;
29 import org.apache.log4j.Logger;
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public class PropertyTree implements Map {
44 private static Logger LOG = Logger.getLogger(PropertyTree.class);
45
46 final boolean flat;
47 final PropertyTree parent;
48 String directValue;
49 Map children;
50
51
52
53
54 public PropertyTree() {
55 this(false);
56 }
57
58
59
60
61
62 public PropertyTree(boolean flat) {
63 this.parent = null;
64 this.children = new LinkedHashMap();
65 this.flat = flat;
66 }
67
68
69
70
71
72 private PropertyTree(PropertyTree parent) {
73 this.parent = parent;
74 this.children = new LinkedHashMap();
75 this.flat = parent.flat;
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 public void setProperty(String key, String value) {
104 validateKey(key);
105 validateValue(value);
106
107 if (parent == null) {
108 LOG.debug("setting (k,v) (" + key + "," + value + ")");
109 }
110
111 if (StringUtils.contains(key, '.')) {
112 String prefix = StringUtils.substringBefore(key, ".");
113 String suffix = StringUtils.substringAfter(key, ".");
114
115 PropertyTree node = getChild(prefix);
116 node.setProperty(suffix, value);
117 }
118 else {
119 PropertyTree node = getChild(key);
120 node.setDirectValue(value);
121 }
122 }
123
124
125
126
127
128
129
130
131
132 public void setProperties(Properties properties) {
133 if (properties == null) {
134 throw new IllegalArgumentException("invalid (null) Properties object");
135 }
136
137 for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
138 Map.Entry e = (Map.Entry) i.next();
139 setProperty((String) e.getKey(), (String) e.getValue());
140 }
141 }
142
143 public void setProperties(Map<String,String> properties) {
144 if (properties == null) {
145 throw new IllegalArgumentException("invalid (null) Properties object");
146 }
147
148 for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
149 Map.Entry e = (Map.Entry) i.next();
150 setProperty((String) e.getKey(), (String) e.getValue());
151 }
152 }
153
154
155
156
157
158
159
160
161 private PropertyTree getSubtree(String key) {
162 validateKey(key);
163
164 PropertyTree returnValue = null;
165 if (StringUtils.contains(key, '.')) {
166 String prefix = StringUtils.substringBefore(key, ".");
167 String suffix = StringUtils.substringAfter(key, ".");
168
169 PropertyTree child = (PropertyTree) this.children.get(prefix);
170 if (child != null) {
171 returnValue = child.getSubtree(suffix);
172 }
173 }
174 else {
175 returnValue = (PropertyTree) this.children.get(key);
176 }
177
178 return returnValue;
179 }
180
181
182
183
184
185
186 public String getProperty(String key) {
187 String propertyValue = null;
188
189 PropertyTree subtree = getSubtree(key);
190 if (subtree != null) {
191 propertyValue = subtree.getDirectValue();
192 }
193
194 return propertyValue;
195 }
196
197
198
199
200
201 public Map getDirectChildren() {
202 return Collections.unmodifiableMap(this.children);
203 }
204
205
206
207
208
209
210
211
212 public String toString() {
213 return getDirectValue();
214 }
215
216
217
218
219
220
221 private void setDirectValue(String value) {
222 validateValue(value);
223
224 this.directValue = value;
225 }
226
227
228
229
230 private String getDirectValue() {
231 return this.directValue;
232 }
233
234
235
236
237 private boolean hasDirectValue() {
238 return (this.directValue != null);
239 }
240
241
242
243
244 private boolean hasChildren() {
245 return (!this.children.isEmpty());
246 }
247
248
249
250
251
252
253
254
255
256 private PropertyTree getChild(String key) {
257 validateKey(key);
258
259 PropertyTree child = (PropertyTree) this.children.get(key);
260 if (child == null) {
261 child = new PropertyTree((PropertyTree)this);
262 this.children.put(key, child);
263 }
264
265 return child;
266 }
267
268
269
270
271
272 private void validateKey(Object key) {
273 if (!(key instanceof String)) {
274 throw new IllegalArgumentException("invalid (non-String) key");
275 }
276 else if (key == null) {
277 throw new IllegalArgumentException("invalid (null) key");
278 }
279 }
280
281
282
283
284
285 private void validateValue(Object value) {
286 if (!(value instanceof String)) {
287 throw new IllegalArgumentException("invalid (non-String) value");
288 }
289 else if (value == null) {
290 throw new IllegalArgumentException("invalid (null) value");
291 }
292 }
293
294
295
296
297
298
299
300
301 public Set entrySet() {
302 return Collections.unmodifiableSet(collectEntries(null, this.flat).entrySet());
303 }
304
305
306
307
308
309
310 private Map collectEntries(String prefix, boolean flattenEntries) {
311 LinkedHashMap entryMap = new LinkedHashMap();
312
313 for (Iterator i = this.children.entrySet().iterator(); i.hasNext();) {
314 Map.Entry e = (Map.Entry) i.next();
315 PropertyTree child = (PropertyTree) e.getValue();
316 String childKey = (String) e.getKey();
317
318
319 if (child.hasDirectValue()) {
320 String entryKey = (prefix == null) ? childKey : prefix + "." + childKey;
321 String entryValue = child.getDirectValue();
322
323 entryMap.put(entryKey, entryValue);
324 }
325
326
327 if (!flattenEntries && child.hasChildren()) {
328 String childPrefix = (prefix == null) ? childKey : prefix + "." + childKey;
329
330 entryMap.putAll(child.collectEntries(childPrefix, flattenEntries));
331 }
332 }
333
334 return entryMap;
335 }
336
337
338
339
340 public int size() {
341 return entrySet().size();
342 }
343
344
345
346
347 public boolean isEmpty() {
348 return entrySet().isEmpty();
349 }
350
351
352
353
354
355
356 public Collection values() {
357 ArrayList values = new ArrayList();
358
359 Set entrySet = entrySet();
360 for (Iterator i = entrySet.iterator(); i.hasNext();) {
361 Map.Entry e = (Map.Entry) i.next();
362
363 values.add(e.getValue());
364 }
365
366 return Collections.unmodifiableList(values);
367 }
368
369
370
371
372
373
374 public Set keySet() {
375 LinkedHashSet keys = new LinkedHashSet();
376
377 Set entrySet = entrySet();
378 for (Iterator i = entrySet.iterator(); i.hasNext();) {
379 Map.Entry e = (Map.Entry) i.next();
380
381 keys.add(e.getKey());
382 }
383
384 return Collections.unmodifiableSet(keys);
385 }
386
387
388
389
390 public boolean containsKey(Object key) {
391 validateKey(key);
392
393 boolean containsKey = false;
394
395 Set entrySet = entrySet();
396 for (Iterator i = entrySet.iterator(); !containsKey && i.hasNext();) {
397 Map.Entry e = (Map.Entry) i.next();
398
399 Object entryKey = e.getKey();
400 containsKey = (entryKey != null) && entryKey.equals(key);
401 }
402
403 return containsKey;
404 }
405
406
407
408
409 public boolean containsValue(Object value) {
410 validateValue(value);
411
412 boolean containsValue = false;
413
414 Set entrySet = entrySet();
415 for (Iterator i = entrySet.iterator(); !containsValue && i.hasNext();) {
416 Map.Entry e = (Map.Entry) i.next();
417
418 Object entryValue = e.getValue();
419 containsValue = (entryValue != null) && entryValue.equals(value);
420 }
421
422 return containsValue;
423 }
424
425
426
427
428
429
430
431
432
433
434 public Object get(Object key) {
435 validateKey(key);
436
437 return getSubtree((String) key);
438 }
439
440
441
442
443
444
445 public void clear() {
446 throw new UnsupportedOperationException();
447 }
448
449
450
451
452 public void putAll(Map t) {
453 throw new UnsupportedOperationException();
454 }
455
456
457
458
459 public Object remove(Object key) {
460 throw new UnsupportedOperationException();
461 }
462
463
464
465
466 public Object put(Object key, Object value) {
467 throw new UnsupportedOperationException();
468 }
469 }