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 package groovy.lang;
36
37
38 import org.codehaus.groovy.runtime.InvokerHelper;
39
40 /***
41 * Represents a property on a bean which may have a getter and/or a setter
42 *
43 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
44 * @author Kim Pilho
45 * @version $Revision: 1.6 $
46 */
47 public class MetaBeanProperty extends MetaProperty {
48
49 private MetaMethod getter;
50 private MetaMethod setter;
51
52 public MetaBeanProperty(String name, Class type, MetaMethod getter, MetaMethod setter) {
53 super(name, type);
54 this.getter = getter;
55 this.setter = setter;
56 }
57
58 /***
59 * @return the property of the given object
60 * @throws Exception if the property could not be evaluated
61 */
62 public Object getProperty(Object object) throws Exception {
63 if (getter == null) {
64
65 throw new GroovyRuntimeException("Cannot read write-only property: " + name);
66 }
67 return getter.invoke(object, MetaClass.EMPTY_ARRAY);
68 }
69
70 /***
71 * Sets the property on the given object to the new value
72 *
73 * @param object on which to set the property
74 * @param newValue the new value of the property
75 * @throws Exception if the property could not be set
76 */
77 public void setProperty(Object object, Object newValue) {
78 if (setter == null) {
79 throw new GroovyRuntimeException("Cannot set read-only property: " + name);
80 }
81
82 try {
83
84 if (getType() == String.class && !(newValue instanceof String)) {
85 newValue = newValue.toString();
86 }
87
88
89 if (newValue instanceof java.math.BigDecimal) {
90 if (getType() == Double.class) {
91 newValue = new Double(((java.math.BigDecimal) newValue).doubleValue());
92 }
93 else if (getType() == Float.class) {
94 newValue = new Float(((java.math.BigDecimal) newValue).floatValue());
95 }
96 else if (getType() == Long.class) {
97 newValue = new Long(((java.math.BigDecimal) newValue).longValue());
98 }
99 else if (getType() == Integer.class) {
100 newValue = new Integer(((java.math.BigDecimal) newValue).intValue());
101 }
102 else if (getType() == Short.class) {
103 newValue = new Short((short) ((java.math.BigDecimal) newValue).intValue());
104 }
105 else if (getType() == Byte.class) {
106 newValue = new Byte((byte) ((java.math.BigDecimal) newValue).intValue());
107 }
108 else if (getType() == Character.class) {
109 newValue = new Character((char) ((java.math.BigDecimal) newValue).intValue());
110 }
111 }
112 else if (newValue instanceof java.math.BigInteger) {
113 if (getType() == Long.class) {
114 newValue = new Long(((java.math.BigInteger) newValue).longValue());
115 }
116 else if (getType() == Integer.class) {
117 newValue = new Integer(((java.math.BigInteger) newValue).intValue());
118 }
119 else if (getType() == Short.class) {
120 newValue = new Short((short) ((java.math.BigInteger) newValue).intValue());
121 }
122 else if (getType() == Byte.class) {
123 newValue = new Byte((byte) ((java.math.BigInteger) newValue).intValue());
124 }
125 else if (getType() == Character.class) {
126 newValue = new Character((char) ((java.math.BigInteger) newValue).intValue());
127 }
128 }
129 else if (newValue instanceof java.lang.Long) {
130 if (getType() == Integer.class) {
131 newValue = new Integer(((Long) newValue).intValue());
132 }
133 else if (getType() == Short.class) {
134 newValue = new Short(((Long) newValue).shortValue());
135 }
136 else if (getType() == Byte.class) {
137 newValue = new Byte(((Long) newValue).byteValue());
138 }
139 else if (getType() == Character.class) {
140 newValue = new Character((char) ((Long) newValue).intValue());
141 }
142 }
143 else if (newValue instanceof java.lang.Integer) {
144 if (getType() == Short.class) {
145 newValue = new Short(((Integer) newValue).shortValue());
146 }
147 else if (getType() == Byte.class) {
148 newValue = new Byte(((Integer) newValue).byteValue());
149 }
150 else if (getType() == Character.class) {
151 newValue = new Character((char) ((Integer) newValue).intValue());
152 }
153 }
154
155 setter.invoke(object, new Object[]{newValue});
156 }
157 catch (IllegalArgumentException e) {
158 try {
159 newValue = InvokerHelper.asType(newValue, getType());
160 setter.invoke(object, new Object[]{newValue});
161 }
162 catch (Exception ex) {
163 throw new TypeMismatchException("The property '" + toName(object.getClass()) + "." + name
164 + "' can not refer to the value '"
165 + newValue + "' (type " + toName(newValue.getClass())
166 + "), because it is of the type " + toName(getType())
167 + ". The reason is from java.lang.IllegalArgumentException.");
168 }
169 }
170 catch (ClassCastException e) {
171 try {
172 newValue = InvokerHelper.asType(newValue, getType());
173 setter.invoke(object, new Object[]{newValue});
174 }
175 catch (Exception ex) {
176 throw new TypeMismatchException("The property '" + toName(object.getClass()) + "." + name
177 + "' can not refer to the value '"
178 + newValue + "' (type " + toName(newValue.getClass())
179 + "), because it is of the type " + toName(getType())
180 + ". The reason is from java.lang.ClassCastException.");
181 }
182 }
183 catch (Exception e) {
184 throw new GroovyRuntimeException("Cannot set property: " + name +
185 " reason: " + e.getMessage(), e);
186 }
187 }
188
189 private String toName(Class c) {
190 String s = c.toString();
191 if (s.startsWith("class ") && s.length() > 6) {
192 return s.substring(6);
193 }
194 else {
195 return s;
196 }
197 }
198
199 public MetaMethod getGetter() {
200 return getter;
201 }
202
203 public MetaMethod getSetter() {
204 return setter;
205 }
206
207 /***
208 * this is for MetaClass to patch up the object later when looking for get*() methods
209 */
210 void setGetter(MetaMethod getter) {
211 this.getter = getter;
212 }
213
214 /***
215 * this is for MetaClass to patch up the object later when looking for set*() methods
216 */
217 void setSetter(MetaMethod setter) {
218 this.setter = setter;
219 }
220 }