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