1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.chain.impl;
18
19
20 import java.beans.IntrospectionException;
21 import java.beans.Introspector;
22 import java.beans.PropertyDescriptor;
23 import java.lang.reflect.Method;
24 import java.util.AbstractCollection;
25 import java.util.AbstractSet;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.Set;
31 import java.io.Serializable;
32 import org.apache.commons.chain.Context;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class ContextBase extends HashMap implements Context {
54
55
56
57
58
59
60
61
62 public ContextBase() {
63
64 super();
65 initialize();
66
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 public ContextBase(Map map) {
84
85 super(map);
86 initialize();
87 putAll(map);
88
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 private transient Map descriptors = null;
108
109
110
111
112
113 private transient PropertyDescriptor[] pd = null;
114
115
116
117
118
119
120
121 private static Object singleton;
122
123 static {
124
125 singleton = new Serializable() {
126 public boolean equals(Object object) {
127 return (false);
128 }
129 };
130
131 }
132
133
134
135
136
137
138 private static Object[] zeroParams = new Object[0];
139
140
141
142
143
144
145
146
147
148 public void clear() {
149
150 if (descriptors == null) {
151 super.clear();
152 } else {
153 Iterator keys = keySet().iterator();
154 while (keys.hasNext()) {
155 Object key = keys.next();
156 if (!descriptors.containsKey(key)) {
157 keys.remove();
158 }
159 }
160 }
161
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176 public boolean containsValue(Object value) {
177
178
179 if (descriptors == null) {
180 return (super.containsValue(value));
181 }
182
183
184 else if (super.containsValue(value)) {
185 return (true);
186 }
187
188
189 for (int i = 0; i < pd.length; i++) {
190 if (pd[i].getReadMethod() != null) {
191 Object prop = readProperty(pd[i]);
192 if (value == null) {
193 if (prop == null) {
194 return (true);
195 }
196 } else if (value.equals(prop)) {
197 return (true);
198 }
199 }
200 }
201 return (false);
202
203 }
204
205
206
207
208
209
210
211
212
213
214
215 public Set entrySet() {
216
217 return (new EntrySetImpl());
218
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 public Object get(Object key) {
241
242
243 if (descriptors == null) {
244 return (super.get(key));
245 }
246
247
248 if (key != null) {
249 PropertyDescriptor descriptor =
250 (PropertyDescriptor) descriptors.get(key);
251 if (descriptor != null) {
252 if (descriptor.getReadMethod() != null) {
253 return (readProperty(descriptor));
254 } else {
255 return (null);
256 }
257 }
258 }
259
260
261 return (super.get(key));
262
263 }
264
265
266
267
268
269
270
271
272
273
274 public boolean isEmpty() {
275
276
277 if (descriptors == null) {
278 return (super.isEmpty());
279 }
280
281
282 return (super.size() <= descriptors.size());
283
284 }
285
286
287
288
289
290
291
292
293
294
295
296 public Set keySet() {
297
298
299 return (super.keySet());
300
301 }
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 public Object put(Object key, Object value) {
319
320
321 if (descriptors == null) {
322 return (super.put(key, value));
323 }
324
325
326 if (key != null) {
327 PropertyDescriptor descriptor =
328 (PropertyDescriptor) descriptors.get(key);
329 if (descriptor != null) {
330 Object previous = null;
331 if (descriptor.getReadMethod() != null) {
332 previous = readProperty(descriptor);
333 }
334 writeProperty(descriptor, value);
335 return (previous);
336 }
337 }
338
339
340 return (super.put(key, value));
341
342 }
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 public void putAll(Map map) {
359
360 Iterator pairs = map.entrySet().iterator();
361 while (pairs.hasNext()) {
362 Map.Entry pair = (Map.Entry) pairs.next();
363 put(pair.getKey(), pair.getValue());
364 }
365
366 }
367
368
369
370
371
372
373
374
375
376
377
378
379
380 public Object remove(Object key) {
381
382
383 if (descriptors == null) {
384 return (super.remove(key));
385 }
386
387
388 if (key != null) {
389 PropertyDescriptor descriptor =
390 (PropertyDescriptor) descriptors.get(key);
391 if (descriptor != null) {
392 throw new UnsupportedOperationException
393 ("Local property '" + key + "' cannot be removed");
394 }
395 }
396
397
398 return (super.remove(key));
399
400 }
401
402
403
404
405
406
407
408
409
410
411
412 public Collection values() {
413
414 return (new ValuesImpl());
415
416 }
417
418
419
420
421
422
423
424
425
426 private Iterator entriesIterator() {
427
428 return (new EntrySetIterator());
429
430 }
431
432
433
434
435
436
437
438
439 private Map.Entry entry(Object key) {
440
441 if (containsKey(key)) {
442 return (new MapEntryImpl(key, get(key)));
443 } else {
444 return (null);
445 }
446
447 }
448
449
450
451
452
453
454
455
456
457
458
459
460
461 private void initialize() {
462
463
464 try {
465 pd = Introspector.getBeanInfo
466 (getClass()).getPropertyDescriptors();
467 } catch (IntrospectionException e) {
468 pd = new PropertyDescriptor[0];
469 }
470
471
472 for (int i = 0; i < pd.length; i++) {
473 String name = pd[i].getName();
474
475
476 if (!("class".equals(name) || "empty".equals(name))) {
477 if (descriptors == null) {
478 descriptors = new HashMap((pd.length - 2));
479 }
480 descriptors.put(name, pd[i]);
481 super.put(name, singleton);
482 }
483 }
484
485 }
486
487
488
489
490
491
492
493
494
495
496
497
498
499 private Object readProperty(PropertyDescriptor descriptor) {
500
501 try {
502 Method method = descriptor.getReadMethod();
503 if (method == null) {
504 throw new UnsupportedOperationException
505 ("Property '" + descriptor.getName()
506 + "' is not readable");
507 }
508 return (method.invoke(this, zeroParams));
509 } catch (Exception e) {
510 throw new UnsupportedOperationException
511 ("Exception reading property '" + descriptor.getName()
512 + "': " + e.getMessage());
513 }
514
515 }
516
517
518
519
520
521
522
523
524
525
526
527
528 private boolean remove(Map.Entry entry) {
529
530 Map.Entry actual = entry(entry.getKey());
531 if (actual == null) {
532 return (false);
533 } else if (!entry.equals(actual)) {
534 return (false);
535 } else {
536 remove(entry.getKey());
537 return (true);
538 }
539
540 }
541
542
543
544
545
546
547 private Iterator valuesIterator() {
548
549 return (new ValuesIterator());
550
551 }
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567 private void writeProperty(PropertyDescriptor descriptor, Object value) {
568
569 try {
570 Method method = descriptor.getWriteMethod();
571 if (method == null) {
572 throw new UnsupportedOperationException
573 ("Property '" + descriptor.getName()
574 + "' is not writeable");
575 }
576 method.invoke(this, new Object[] {value});
577 } catch (Exception e) {
578 throw new UnsupportedOperationException
579 ("Exception writing property '" + descriptor.getName()
580 + "': " + e.getMessage());
581 }
582
583 }
584
585
586
587
588
589
590
591
592
593 private class EntrySetImpl extends AbstractSet {
594
595 public void clear() {
596 ContextBase.this.clear();
597 }
598
599 public boolean contains(Object obj) {
600 if (!(obj instanceof Map.Entry)) {
601 return (false);
602 }
603 Map.Entry entry = (Map.Entry) obj;
604 Entry actual = ContextBase.this.entry(entry.getKey());
605 if (actual != null) {
606 return (actual.equals(entry));
607 } else {
608 return (false);
609 }
610 }
611
612 public boolean isEmpty() {
613 return (ContextBase.this.isEmpty());
614 }
615
616 public Iterator iterator() {
617 return (ContextBase.this.entriesIterator());
618 }
619
620 public boolean remove(Object obj) {
621 if (obj instanceof Map.Entry) {
622 return (ContextBase.this.remove((Map.Entry) obj));
623 } else {
624 return (false);
625 }
626 }
627
628 public int size() {
629 return (ContextBase.this.size());
630 }
631
632 }
633
634
635
636
637
638
639 private class EntrySetIterator implements Iterator {
640
641 private Map.Entry entry = null;
642 private Iterator keys = ContextBase.this.keySet().iterator();
643
644 public boolean hasNext() {
645 return (keys.hasNext());
646 }
647
648 public Object next() {
649 entry = ContextBase.this.entry(keys.next());
650 return (entry);
651 }
652
653 public void remove() {
654 ContextBase.this.remove(entry);
655 }
656
657 }
658
659
660
661
662
663
664 private class MapEntryImpl implements Map.Entry {
665
666 MapEntryImpl(Object key, Object value) {
667 this.key = key;
668 this.value = value;
669 }
670
671 private Object key;
672 private Object value;
673
674 public boolean equals(Object obj) {
675 if (obj == null) {
676 return (false);
677 } else if (!(obj instanceof Map.Entry)) {
678 return (false);
679 }
680 Map.Entry entry = (Map.Entry) obj;
681 if (key == null) {
682 return (entry.getKey() == null);
683 }
684 if (key.equals(entry.getKey())) {
685 if (value == null) {
686 return (entry.getValue() == null);
687 } else {
688 return (value.equals(entry.getValue()));
689 }
690 } else {
691 return (false);
692 }
693 }
694
695 public Object getKey() {
696 return (this.key);
697 }
698
699 public Object getValue() {
700 return (this.value);
701 }
702
703 public int hashCode() {
704 return (((key == null) ? 0 : key.hashCode())
705 ^ ((value == null) ? 0 : value.hashCode()));
706 }
707
708 public Object setValue(Object value) {
709 Object previous = this.value;
710 ContextBase.this.put(this.key, value);
711 this.value = value;
712 return (previous);
713 }
714
715 public String toString() {
716 return getKey() + "=" + getValue();
717 }
718 }
719
720
721
722
723
724
725 private class ValuesImpl extends AbstractCollection {
726
727 public void clear() {
728 ContextBase.this.clear();
729 }
730
731 public boolean contains(Object obj) {
732 if (!(obj instanceof Map.Entry)) {
733 return (false);
734 }
735 Map.Entry entry = (Map.Entry) obj;
736 return (ContextBase.this.containsValue(entry.getValue()));
737 }
738
739 public boolean isEmpty() {
740 return (ContextBase.this.isEmpty());
741 }
742
743 public Iterator iterator() {
744 return (ContextBase.this.valuesIterator());
745 }
746
747 public boolean remove(Object obj) {
748 if (obj instanceof Map.Entry) {
749 return (ContextBase.this.remove((Map.Entry) obj));
750 } else {
751 return (false);
752 }
753 }
754
755 public int size() {
756 return (ContextBase.this.size());
757 }
758
759 }
760
761
762
763
764
765
766 private class ValuesIterator implements Iterator {
767
768 private Map.Entry entry = null;
769 private Iterator keys = ContextBase.this.keySet().iterator();
770
771 public boolean hasNext() {
772 return (keys.hasNext());
773 }
774
775 public Object next() {
776 entry = ContextBase.this.entry(keys.next());
777 return (entry.getValue());
778 }
779
780 public void remove() {
781 ContextBase.this.remove(entry);
782 }
783
784 }
785
786
787 }