1 package org.apache.velocity.tools.generic;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Map;
23 import java.util.Locale;
24 import java.util.Set;
25 import java.util.HashMap;
26 import java.util.Collection;
27
28 import org.apache.velocity.tools.config.DefaultKey;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 @DefaultKey("parser")
46 public class ValueParser extends ConversionTool implements Map<String,Object>
47 {
48 private Map<String,Object> source = null;
49
50 private boolean allowSubkeys = true;
51
52
53
54
55
56 private Boolean hasSubkeys = null;
57
58
59 private boolean readOnly = true;
60
61
62
63
64 public static final String ALLOWSUBKEYS_KEY = "allowSubkeys";
65
66
67
68
69 public static final String READONLY_KEY = "readOnly";
70
71 public ValueParser() {}
72
73 public ValueParser(Map<String,Object> source)
74 {
75 setSource(source);
76 }
77
78 protected void setSource(Map<String,Object> source)
79 {
80 this.source = source;
81 }
82
83 protected Map<String,Object> getSource()
84 {
85 return this.source;
86 }
87
88
89
90
91
92 protected boolean getAllowSubkeys()
93 {
94 return allowSubkeys;
95 }
96
97
98
99
100
101 protected void setAllowSubkeys(boolean allow)
102 {
103 allowSubkeys = allow;
104 }
105
106
107
108
109
110 protected boolean getReadOnly()
111 {
112 return readOnly;
113 }
114
115
116
117
118
119 protected void setReadOnly(boolean ro)
120 {
121 readOnly = ro;
122 }
123
124
125
126
127
128
129
130 @Override
131 protected void configure(ValueParser values)
132 {
133 super.configure(values);
134
135
136 Boolean depMode = values.getBoolean("deprecationSupportMode");
137 if (depMode != null && depMode.booleanValue())
138 {
139
140 setAllowSubkeys(false);
141 }
142
143
144 Boolean allow = values.getBoolean(ALLOWSUBKEYS_KEY);
145 if(allow != null)
146 {
147 setAllowSubkeys(allow);
148 }
149
150 Boolean ro = values.getBoolean(READONLY_KEY);
151 if(ro != null)
152 {
153 setReadOnly(ro);
154 }
155 }
156
157
158
159
160
161
162
163
164
165
166 public boolean exists(String key)
167 {
168 return (getValue(key) != null);
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182 public Object get(String key)
183 {
184 Object value = getValue(key);
185 if (value == null && getSource() != null && getAllowSubkeys())
186 {
187 value = getSubkey(key);
188 }
189 return value;
190 }
191
192
193
194
195
196
197 public Object getValue(String key)
198 {
199 if (getSource() == null)
200 {
201 return null;
202 }
203 return getSource().get(key);
204 }
205
206
207
208
209
210
211
212
213 public Object getValue(String key, Object alternate)
214 {
215 Object value = getValue(key);
216 if (value == null)
217 {
218 return alternate;
219 }
220 return value;
221 }
222
223 public Object[] getValues(String key)
224 {
225 Object value = getValue(key);
226 if (value == null)
227 {
228 return null;
229 }
230 if (value instanceof String)
231 {
232 return parseStringList((String)value);
233 }
234 if (value instanceof Object[])
235 {
236 return (Object[])value;
237 }
238 return new Object[] { value };
239 }
240
241
242
243
244
245
246
247 public String getString(String key)
248 {
249 return toString(getValue(key));
250 }
251
252
253
254
255
256
257
258
259 public String getString(String key, String alternate)
260 {
261 String s = getString(key);
262 return (s != null) ? s : alternate;
263 }
264
265
266
267
268
269
270 public Boolean getBoolean(String key)
271 {
272 return toBoolean(getValue(key));
273 }
274
275
276
277
278
279
280
281 public boolean getBoolean(String key, boolean alternate)
282 {
283 Boolean bool = getBoolean(key);
284 return (bool != null) ? bool.booleanValue() : alternate;
285 }
286
287
288
289
290
291
292
293 public Boolean getBoolean(String key, Boolean alternate)
294 {
295 Boolean bool = getBoolean(key);
296 return (bool != null) ? bool : alternate;
297 }
298
299
300
301
302
303
304 public Integer getInteger(String key)
305 {
306 return toInteger(getValue(key));
307 }
308
309
310
311
312
313
314
315 public Integer getInteger(String key, Integer alternate)
316 {
317 Integer num = getInteger(key);
318 if (num == null)
319 {
320 return alternate;
321 }
322 return num;
323 }
324
325
326
327
328
329
330 public Double getDouble(String key)
331 {
332 return toDouble(getValue(key));
333 }
334
335
336
337
338
339
340
341 public Double getDouble(String key, Double alternate)
342 {
343 Double num = getDouble(key);
344 if (num == null)
345 {
346 return alternate;
347 }
348 return num;
349 }
350
351
352
353
354
355
356 public Number getNumber(String key)
357 {
358 return toNumber(getValue(key));
359 }
360
361
362
363
364
365
366 public Locale getLocale(String key)
367 {
368 return toLocale(getValue(key));
369 }
370
371
372
373
374
375
376
377 public Number getNumber(String key, Number alternate)
378 {
379 Number n = getNumber(key);
380 return (n != null) ? n : alternate;
381 }
382
383
384
385
386
387
388
389 public int getInt(String key, int alternate)
390 {
391 Number n = getNumber(key);
392 return (n != null) ? n.intValue() : alternate;
393 }
394
395
396
397
398
399
400
401 public double getDouble(String key, double alternate)
402 {
403 Number n = getNumber(key);
404 return (n != null) ? n.doubleValue() : alternate;
405 }
406
407
408
409
410
411
412
413 public Locale getLocale(String key, Locale alternate)
414 {
415 Locale l = getLocale(key);
416 return (l != null) ? l : alternate;
417 }
418
419
420
421
422
423
424
425
426 public String[] getStrings(String key)
427 {
428 return toStrings(getValues(key));
429 }
430
431
432
433
434
435
436 public Boolean[] getBooleans(String key)
437 {
438 return toBooleans(getValues(key));
439 }
440
441
442
443
444
445
446 public Number[] getNumbers(String key)
447 {
448 return toNumbers(getValues(key));
449 }
450
451
452
453
454
455
456 public int[] getInts(String key)
457 {
458 return toInts(getValues(key));
459 }
460
461
462
463
464
465
466 public double[] getDoubles(String key)
467 {
468 return toDoubles(getValues(key));
469 }
470
471
472
473
474
475
476 public Locale[] getLocales(String key)
477 {
478 return toLocales(getValues(key));
479 }
480
481
482
483
484 public boolean hasSubkeys()
485 {
486 if (getSource() == null)
487 {
488 return false;
489 }
490
491 if (hasSubkeys == null)
492 {
493 for (String key : getSource().keySet())
494 {
495 int dot = key.indexOf('.');
496 if (dot > 0 && dot < key.length())
497 {
498 hasSubkeys = Boolean.TRUE;
499 break;
500 }
501 }
502 if (hasSubkeys == null)
503 {
504 hasSubkeys = Boolean.FALSE;
505 }
506 }
507 return hasSubkeys;
508 }
509
510
511
512
513
514
515
516
517 protected ValueParser getSubkey(String subkey)
518 {
519 if (!hasSubkeys() || subkey == null || subkey.length() == 0)
520 {
521 return null;
522 }
523
524 Map<String,Object> values = null;
525 subkey = subkey.concat(".");
526 for (Map.Entry<String,Object> entry : getSource().entrySet())
527 {
528 if (entry.getKey().startsWith(subkey) &&
529 entry.getKey().length() > subkey.length())
530 {
531 if(values == null)
532 {
533 values = new HashMap<String,Object>();
534 }
535
536 values.put(entry.getKey().substring(subkey.length()),entry.getValue());
537 }
538 }
539 if (values == null)
540 {
541 return null;
542 }
543 else
544 {
545 return new ValueParser(values);
546 }
547 }
548
549 public int size()
550 {
551 return getSource().size();
552 }
553
554 public boolean isEmpty()
555 {
556 return getSource().isEmpty();
557 }
558
559 public boolean containsKey(Object key)
560 {
561 return getSource().containsKey(key);
562 }
563
564 public boolean containsValue(Object value)
565 {
566 return getSource().containsValue(value);
567 }
568
569 public Object get(Object key)
570 {
571 return get(String.valueOf(key));
572 }
573
574 public Object put(String key, Object value)
575 {
576 if(readOnly)
577 {
578 throw new UnsupportedOperationException("Cannot put("+key+","+value+"); "+getClass().getName()+" is read-only");
579 }
580 if(hasSubkeys != null && hasSubkeys.equals(Boolean.FALSE) && key.indexOf('.') != -1)
581 {
582 hasSubkeys = Boolean.TRUE;
583 }
584 return source.put(key,value);
585 }
586
587 public Object remove(Object key)
588 {
589 if(readOnly)
590 {
591 throw new UnsupportedOperationException("Cannot remove("+key+"); "+getClass().getName()+" is read-only");
592 }
593 if(hasSubkeys != null && hasSubkeys.equals(Boolean.TRUE) && ((String)key).indexOf('.') != -1)
594 {
595 hasSubkeys = null;
596 }
597 return source.remove(key);
598 }
599
600 public void putAll(Map<? extends String,? extends Object> m) {
601 if(readOnly)
602 {
603 throw new UnsupportedOperationException("Cannot putAll("+m+"); "+getClass().getName()+" is read-only");
604 }
605 hasSubkeys = null;
606 source.putAll(m);
607 }
608
609 public void clear() {
610 if(readOnly)
611 {
612 throw new UnsupportedOperationException("Cannot clear(); "+getClass().getName()+" is read-only");
613 }
614 hasSubkeys = Boolean.FALSE;
615 source.clear();
616 }
617
618 public Set<String> keySet() {
619 return getSource().keySet();
620 }
621
622 public Collection values() {
623 return getSource().values();
624 }
625
626 public Set<Map.Entry<String,Object>> entrySet() {
627 return getSource().entrySet();
628 }
629
630 public String toString() {
631 StringBuilder builder = new StringBuilder();
632 builder.append('{');
633 boolean empty = true;
634 for(Map.Entry<String,Object> entry:entrySet())
635 {
636 if(!empty)
637 {
638 builder.append(", ");
639 }
640 empty = false;
641 builder.append(entry.getKey());
642 builder.append('=');
643 builder.append(String.valueOf(entry.getValue()));
644 }
645 builder.append('}');
646 return builder.toString();
647 }
648 }