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 java.math.BigDecimal;
39 import java.math.BigInteger;
40
41 import org.codehaus.groovy.runtime.InvokerHelper;
42 import org.codehaus.groovy.runtime.MetaClassHelper;
43
44 /***
45 * Represents a property on a bean which may have a getter and/or a setter
46 *
47 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
48 * @author Pilho Kim
49 * @version $Revision: 1.8 $
50 */
51 public class MetaBeanProperty extends MetaProperty {
52
53 private MetaMethod getter;
54 private MetaMethod setter;
55
56 public MetaBeanProperty(String name, Class type, MetaMethod getter, MetaMethod setter) {
57 super(name, type);
58 this.getter = getter;
59 this.setter = setter;
60 }
61
62 /***
63 * Get the property of the given object.
64 *
65 * @param object which to be got
66 * @return the property of the given object
67 * @throws Exception if the property could not be evaluated
68 */
69 public Object getProperty(Object object) throws Exception {
70 if (getter == null) {
71
72 throw new GroovyRuntimeException("Cannot read write-only property: " + name);
73 }
74 return getter.invoke(object, MetaClassHelper.EMPTY_ARRAY);
75 }
76
77 /***
78 * Set the property on the given object to the new value.
79 *
80 * @param object on which to set the property
81 * @param newValue the new value of the property
82 * @throws Exception if the property could not be set
83 */
84 public void setProperty(Object object, Object newValue) {
85 if (setter == null) {
86 throw new GroovyRuntimeException("Cannot set read-only property: " + name);
87 }
88
89 try {
90
91 if (getType() == String.class && !(newValue instanceof String)) {
92 newValue = newValue.toString();
93 }
94 else {
95
96 newValue = coercePrimitiveValue(newValue, getType());
97 }
98
99 setter.invoke(object, new Object[] { newValue });
100 }
101 catch (IllegalArgumentException e) {
102 try {
103 newValue = InvokerHelper.asType(newValue, getType());
104 setter.invoke(object, new Object[] { newValue });
105 }
106 catch (Exception ex) {
107 throw new TypeMismatchException("The property '" + toName(object.getClass()) + "." + name
108 + "' can not refer to the value '"
109 + newValue + "' (type " + toName(newValue.getClass())
110 + "), because it is of the type " + toName(getType())
111 + ". The reason is from java.lang.IllegalArgumentException.");
112 }
113 }
114 catch (ClassCastException e) {
115 try {
116 newValue = InvokerHelper.asType(newValue, getType());
117 setter.invoke(object, new Object[]{newValue});
118 }
119 catch (Exception ex) {
120 throw new TypeMismatchException("The property '" + toName(object.getClass()) + "." + name
121 + "' can not refer to the value '"
122 + newValue + "' (type " + toName(newValue.getClass())
123 + "), because it is of the type " + toName(getType())
124 + ". The reason is from java.lang.ClassCastException.");
125 }
126 }
127 catch (Exception e) {
128 throw new GroovyRuntimeException("Cannot set property: " + name +
129 " reason: " + e.getMessage(), e);
130 }
131 }
132
133 /***
134 * Coerce the object <code>src</code> to the target class.
135 */
136 protected static Object coercePrimitiveValue(Object src, Class target) {
137 Object newValue = src;
138
139 if (newValue instanceof BigDecimal) {
140 if (target == java.math.BigInteger.class) {
141 newValue = ((BigDecimal) newValue).unscaledValue();
142 }
143 else if (target == Double.class) {
144 newValue = new Double(((BigDecimal) newValue).doubleValue());
145 }
146 else if (target == Float.class) {
147 newValue = new Float(((BigDecimal) newValue).floatValue());
148 }
149 else if (target == Long.class) {
150 newValue = new Long(((BigDecimal) newValue).longValue());
151 }
152 else if (target == Integer.class) {
153 newValue = new Integer(((BigDecimal) newValue).intValue());
154 }
155 else if (target == Short.class) {
156 newValue = new Short((short) ((BigDecimal) newValue).intValue());
157 }
158 else if (target == Byte.class) {
159 newValue = new Byte((byte) ((BigDecimal) newValue).intValue());
160 }
161 else if (target == Character.class) {
162 newValue = new Character((char) ((BigDecimal) newValue).intValue());
163 }
164 }
165 else if (newValue instanceof BigInteger) {
166 if (target == BigDecimal.class) {
167 newValue = new BigDecimal((BigInteger) newValue);
168 }
169 else if (target == Double.class) {
170 newValue = new Double(((java.math.BigInteger) newValue).doubleValue());
171 }
172 else if (target == Float.class) {
173 newValue = new Float(((java.math.BigInteger) newValue).floatValue());
174 }
175 else if (target == Long.class) {
176 newValue = new Long(((java.math.BigInteger) newValue).longValue());
177 }
178 else if (target == Integer.class) {
179 newValue = new Integer(((java.math.BigInteger) newValue).intValue());
180 }
181 else if (target == Short.class) {
182 newValue = new Short((short) ((java.math.BigInteger) newValue).intValue());
183 }
184 else if (target == Byte.class) {
185 newValue = new Byte((byte) ((java.math.BigInteger) newValue).intValue());
186 }
187 else if (target == Character.class) {
188 newValue = new Character((char) ((java.math.BigInteger) newValue).intValue());
189 }
190 }
191 else if (newValue instanceof java.lang.Long) {
192 if (target == Integer.class) {
193 newValue = new Integer(((Long) newValue).intValue());
194 }
195 else if (target == Short.class) {
196 newValue = new Short(((Long) newValue).shortValue());
197 }
198 else if (target == Byte.class) {
199 newValue = new Byte(((Long) newValue).byteValue());
200 }
201 else if (target == Character.class) {
202 newValue = new Character((char) ((Long) newValue).intValue());
203 }
204 else if (target == BigInteger.class) {
205 newValue = new BigInteger("" + newValue);
206 }
207 else if (target == BigDecimal.class) {
208 newValue = new BigDecimal("" + newValue);
209 }
210 }
211 else if (newValue instanceof java.lang.Integer) {
212 if (target == Double.class) {
213 newValue = new Double(((Integer) newValue).intValue());
214 }
215 else if (target == Float.class) {
216 newValue = new Float(((Integer) newValue).floatValue());
217 }
218 else if (target == Long.class) {
219 newValue = new Long(((Integer) newValue).intValue());
220 }
221 else if (target == Short.class) {
222 newValue = new Short(((Integer) newValue).shortValue());
223 }
224 else if (target == Byte.class) {
225 newValue = new Byte(((Integer) newValue).byteValue());
226 }
227 else if (target == Character.class) {
228 newValue = new Character((char) ((Integer) newValue).intValue());
229 }
230 else if (target == BigDecimal.class) {
231 newValue = new BigDecimal("" + newValue);
232 }
233 else if (target == BigInteger.class) {
234 newValue = new BigInteger("" + newValue);
235 }
236 }
237 else if (newValue instanceof java.lang.Short) {
238 if (target == Double.class) {
239 newValue = new Double(((Short) newValue).shortValue());
240 }
241 else if (target == Float.class) {
242 newValue = new Float(((Short) newValue).shortValue());
243 }
244 else if (target == Long.class) {
245 newValue = new Long(((Short) newValue).shortValue());
246 }
247 else if (target == Integer.class) {
248 newValue = new Integer(((Short) newValue).shortValue());
249 }
250 else if (target == Byte.class) {
251 newValue = new Byte((byte) ((Short) newValue).shortValue());
252 }
253 else if (target == Character.class) {
254 newValue = new Character((char) ((Short) newValue).shortValue());
255 }
256 else if (target == BigDecimal.class) {
257 newValue = new BigDecimal("" + newValue);
258 }
259 else if (target == BigInteger.class) {
260 newValue = new BigInteger("" + newValue);
261 }
262 }
263 else if (newValue instanceof java.lang.Byte) {
264 if (target == Double.class) {
265 newValue = new Double(((Byte) newValue).byteValue());
266 }
267 else if (target == Float.class) {
268 newValue = new Float(((Byte) newValue).byteValue());
269 }
270 else if (target == Long.class) {
271 newValue = new Long(((Byte) newValue).byteValue());
272 }
273 else if (target == Integer.class) {
274 newValue = new Integer(((Byte) newValue).byteValue());
275 }
276 else if (target == Short.class) {
277 newValue = new Short(((Byte) newValue).byteValue());
278 }
279 else if (target == Character.class) {
280 newValue = new Character((char) ((Byte) newValue).byteValue());
281 }
282 else if (target == BigDecimal.class) {
283 newValue = new BigDecimal("" + newValue);
284 }
285 else if (target == BigInteger.class) {
286 newValue = new BigInteger("" + newValue);
287 }
288 }
289 else if (newValue instanceof java.lang.Character) {
290 if (target == Double.class) {
291 newValue = new Double(((int) ((Character) newValue).charValue() & 0xFFFF));
292 }
293 else if (target == Long.class) {
294 newValue = new Long((long) ((Character) newValue).charValue());
295 }
296 else if (target == Integer.class) {
297 newValue = new Integer((int) ((Character) newValue).charValue());
298 }
299 else if (target == Short.class) {
300 newValue = new Short((short) ((Character) newValue).charValue());
301 }
302 else if (target == BigDecimal.class) {
303 newValue = new BigDecimal("" + ((int) ((Character) newValue).charValue() & 0xFFFF));
304 }
305 else if (target == BigInteger.class) {
306 newValue = new BigInteger("" + ((int) ((Character) newValue).charValue() & 0xFFFF));
307 }
308 else if (target == String.class) {
309 newValue = new String("" + newValue);
310 }
311 }
312 return newValue;
313 }
314
315 private String toName(Class c) {
316 String s = c.toString();
317 if (s.startsWith("class ") && s.length() > 6) {
318 return s.substring(6);
319 }
320 else {
321 return s;
322 }
323 }
324
325
326 /***
327 * Get the getter method.
328 */
329 public MetaMethod getGetter() {
330 return getter;
331 }
332
333 /***
334 * Get the setter method.
335 */
336 public MetaMethod getSetter() {
337 return setter;
338 }
339
340 /***
341 * This is for MetaClass to patch up the object later when looking for get*() methods.
342 */
343 void setGetter(MetaMethod getter) {
344 this.getter = getter;
345 }
346
347 /***
348 * This is for MetaClass to patch up the object later when looking for set*() methods.
349 */
350 void setSetter(MetaMethod setter) {
351 this.setter = setter;
352 }
353 }