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