1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package groovy.util;
47
48 import groovy.lang.Closure;
49 import groovy.lang.GroovyObjectSupport;
50 import groovy.lang.GroovyRuntimeException;
51
52 import java.util.HashMap;
53 import java.util.Map;
54
55
56 /***
57 * Represents a dynamically expandable bean.
58 *
59 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
60 * @version $Revision: 1.2 $
61 */
62 public class Expando extends GroovyObjectSupport {
63
64 private Map expandoProperties;
65
66 public Expando() {
67 }
68
69 public Expando(Map expandoProperties) {
70 this.expandoProperties = expandoProperties;
71 }
72
73 /***
74 * @return the dynamically expanded properties
75 */
76 public Map getExpandoProperties() {
77 if (expandoProperties == null) {
78 expandoProperties = createMap();
79 }
80 return expandoProperties;
81 }
82
83 public Object getProperty(String property) {
84 try {
85 return super.getProperty(property);
86 }
87 catch (GroovyRuntimeException e) {
88 return getExpandoProperties().get(property);
89 }
90 }
91
92 public void setProperty(String property, Object newValue) {
93 try {
94 super.setProperty(property, newValue);
95 }
96 catch (GroovyRuntimeException e) {
97 getExpandoProperties().put(property, newValue);
98 }
99 }
100
101 public Object invokeMethod(String name, Object args) {
102 try {
103 return super.invokeMethod(name, args);
104 }
105 catch (GroovyRuntimeException e) {
106
107 Object value = this.getProperty(name);
108 if (value instanceof Closure) {
109 Closure closure = (Closure) value;
110 closure.setDelegate(this);
111 return closure.call(args);
112 }
113 else {
114 throw e;
115 }
116 }
117
118 }
119
120 /***
121 * Factory method to create a new Map used to store the expando properties map
122 * @return a newly created Map implementation
123 */
124 protected Map createMap() {
125 return new HashMap();
126 }
127
128 }