KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibatis > common > beans > ComplexBeanProbe


1 /*
2  * Copyright 2004 Clinton Begin
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package com.ibatis.common.beans;
17
18 import java.lang.reflect.Method JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.StringTokenizer JavaDoc;
21
22 /**
23  * StaticBeanProbe provides methods that allow simple, reflective access to
24  * JavaBeans style properties. Methods are provided for all simple types as
25  * well as object types.
26  * <p/>
27  * Examples:
28  * <p/>
29  * StaticBeanProbe.setObject(object, propertyName, value);
30  * <P>
31  * Object value = StaticBeanProbe.getObject(object, propertyName);
32  */

33 public class ComplexBeanProbe extends BaseProbe {
34
35   private static final Object JavaDoc[] NO_ARGUMENTS = new Object JavaDoc[0];
36
37   protected ComplexBeanProbe() {
38   }
39
40   /**
41    * Returns an array of the readable properties exposed by a bean
42    *
43    * @param object The bean
44    * @return The properties
45    */

46   public String JavaDoc[] getReadablePropertyNames(Object JavaDoc object) {
47     return ClassInfo.getInstance(object.getClass()).getReadablePropertyNames();
48   }
49
50   /**
51    * Returns an array of the writeable properties exposed by a bean
52    *
53    * @param object The bean
54    * @return The properties
55    */

56   public String JavaDoc[] getWriteablePropertyNames(Object JavaDoc object) {
57     return ClassInfo.getInstance(object.getClass()).getReadablePropertyNames();
58   }
59
60   /**
61    * Returns the class that the setter expects to receive as a parameter when
62    * setting a property value.
63    *
64    * @param object The bean to check
65    * @param name The name of the property
66    * @return The type of the property
67    */

68   public Class JavaDoc getPropertyTypeForSetter(Object JavaDoc object, String JavaDoc name) {
69     Class JavaDoc type = object.getClass();
70
71     if (object instanceof Class JavaDoc) {
72       type = getClassPropertyTypeForSetter((Class JavaDoc) object, name);
73     } else if (object instanceof Map JavaDoc) {
74       Map JavaDoc map = (Map JavaDoc) object;
75       Object JavaDoc value = map.get(name);
76       if (value == null) {
77         type = Object JavaDoc.class;
78       } else {
79         type = value.getClass();
80       }
81     } else {
82       if (name.indexOf('.') > -1) {
83         StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(name, ".");
84         while (parser.hasMoreTokens()) {
85           name = parser.nextToken();
86           type = ClassInfo.getInstance(type).getSetterType(name);
87         }
88       } else {
89         type = ClassInfo.getInstance(type).getSetterType(name);
90       }
91     }
92
93     return type;
94   }
95
96   /**
97    * Returns the class that the getter will return when reading a property value.
98    *
99    * @param object The bean to check
100    * @param name The name of the property
101    * @return The type of the property
102    */

103   public Class JavaDoc getPropertyTypeForGetter(Object JavaDoc object, String JavaDoc name) {
104     Class JavaDoc type = object.getClass();
105
106     if (object instanceof Class JavaDoc) {
107       type = getClassPropertyTypeForGetter((Class JavaDoc) object, name);
108     } else if (object instanceof Map JavaDoc) {
109       Map JavaDoc map = (Map JavaDoc) object;
110       Object JavaDoc value = map.get(name);
111       if (value == null) {
112         type = Object JavaDoc.class;
113       } else {
114         type = value.getClass();
115       }
116     } else {
117       if (name.indexOf('.') > -1) {
118         StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(name, ".");
119         while (parser.hasMoreTokens()) {
120           name = parser.nextToken();
121           type = ClassInfo.getInstance(type).getGetterType(name);
122         }
123       } else {
124         type = ClassInfo.getInstance(type).getGetterType(name);
125       }
126     }
127
128     return type;
129   }
130
131   /**
132    * Returns the class that the getter will return when reading a property value.
133    *
134    * @param type The class to check
135    * @param name The name of the property
136    * @return The type of the property
137    */

138   private Class JavaDoc getClassPropertyTypeForGetter(Class JavaDoc type, String JavaDoc name) {
139
140     if (name.indexOf('.') > -1) {
141       StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(name, ".");
142       while (parser.hasMoreTokens()) {
143         name = parser.nextToken();
144         type = ClassInfo.getInstance(type).getGetterType(name);
145       }
146     } else {
147       type = ClassInfo.getInstance(type).getGetterType(name);
148     }
149
150     return type;
151   }
152
153   /**
154    * Returns the class that the setter expects to receive as a parameter when
155    * setting a property value.
156    *
157    * @param type The class to check
158    * @param name The name of the property
159    * @return The type of the property
160    */

161   private Class JavaDoc getClassPropertyTypeForSetter(Class JavaDoc type, String JavaDoc name) {
162
163     if (name.indexOf('.') > -1) {
164       StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(name, ".");
165       while (parser.hasMoreTokens()) {
166         name = parser.nextToken();
167         type = ClassInfo.getInstance(type).getSetterType(name);
168       }
169     } else {
170       type = ClassInfo.getInstance(type).getSetterType(name);
171     }
172
173     return type;
174   }
175
176   /**
177    * Gets an Object property from a bean
178    *
179    * @param object The bean
180    * @param name The property name
181    * @return The property value (as an Object)
182    */

183   public Object JavaDoc getObject(Object JavaDoc object, String JavaDoc name) {
184     if (name.indexOf('.') > -1) {
185       StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(name, ".");
186       Object JavaDoc value = object;
187       while (parser.hasMoreTokens()) {
188         value = getProperty(value, parser.nextToken());
189
190         if (value == null) {
191           break;
192         }
193
194       }
195       return value;
196     } else {
197       return getProperty(object, name);
198     }
199   }
200
201   /**
202    * Sets the value of a bean property to an Object
203    *
204    * @param object The bean to change
205    * @param name The name of the property to set
206    * @param value The new value to set
207    */

208   public void setObject(Object JavaDoc object, String JavaDoc name, Object JavaDoc value) {
209     if (name.indexOf('.') > -1) {
210       StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(name, ".");
211       String JavaDoc property = parser.nextToken();
212       Object JavaDoc child = object;
213       while (parser.hasMoreTokens()) {
214         Class JavaDoc type = getPropertyTypeForSetter(child, property);
215         Object JavaDoc parent = child;
216         child = getProperty(parent, property);
217         if (child == null) {
218           if (value == null) {
219             return; // don't instantiate child path if value is null
220
} else {
221             try {
222               child = type.newInstance();
223               setObject(parent, property, child);
224             } catch (Exception JavaDoc e) {
225               throw new ProbeException("Cannot set value of property '" + name + "' because '" + property + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
226             }
227           }
228         }
229         property = parser.nextToken();
230       }
231       setProperty(child, property, value);
232     } else {
233       setProperty(object, name, value);
234     }
235   }
236
237
238   /**
239    * Checks to see if a bean has a writable property be a given name
240    *
241    * @param object The bean to check
242    * @param propertyName The property to check for
243    * @return True if the property exists and is writable
244    */

245   public boolean hasWritableProperty(Object JavaDoc object, String JavaDoc propertyName) {
246     boolean hasProperty = false;
247     if (object instanceof Map JavaDoc) {
248       hasProperty = true;//((Map) object).containsKey(propertyName);
249
} else {
250       if (propertyName.indexOf('.') > -1) {
251         StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(propertyName, ".");
252         Class JavaDoc type = object.getClass();
253         while (parser.hasMoreTokens()) {
254           propertyName = parser.nextToken();
255           type = ClassInfo.getInstance(type).getGetterType(propertyName);
256           hasProperty = ClassInfo.getInstance(type).hasWritableProperty(propertyName);
257         }
258       } else {
259         hasProperty = ClassInfo.getInstance(object.getClass()).hasWritableProperty(propertyName);
260       }
261     }
262     return hasProperty;
263   }
264
265   /**
266    * Checks to see if a bean has a readable property be a given name
267    *
268    * @param object The bean to check
269    * @param propertyName The property to check for
270    * @return True if the property exists and is readable
271    */

272   public boolean hasReadableProperty(Object JavaDoc object, String JavaDoc propertyName) {
273     boolean hasProperty = false;
274     if (object instanceof Map JavaDoc) {
275       hasProperty = true;//((Map) object).containsKey(propertyName);
276
} else {
277       if (propertyName.indexOf('.') > -1) {
278         StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(propertyName, ".");
279         Class JavaDoc type = object.getClass();
280         while (parser.hasMoreTokens()) {
281           propertyName = parser.nextToken();
282           type = ClassInfo.getInstance(type).getGetterType(propertyName);
283           hasProperty = ClassInfo.getInstance(type).hasReadableProperty(propertyName);
284         }
285       } else {
286         hasProperty = ClassInfo.getInstance(object.getClass()).hasReadableProperty(propertyName);
287       }
288     }
289     return hasProperty;
290   }
291
292   protected Object JavaDoc getProperty(Object JavaDoc object, String JavaDoc name) {
293     ClassInfo classCache = ClassInfo.getInstance(object.getClass());
294     try {
295       Object JavaDoc value = null;
296       if (name.indexOf("[") > -1) {
297         value = getIndexedProperty(object, name);
298       } else {
299         if (object instanceof Map JavaDoc) {
300           value = ((Map JavaDoc) object).get(name);
301         } else {
302           Method JavaDoc method = classCache.getGetter(name);
303           if (method == null) {
304             throw new NoSuchMethodException JavaDoc("No GET method for property " + name + " on instance of " + object.getClass().getName());
305           }
306           try {
307             value = method.invoke(object, NO_ARGUMENTS);
308           } catch (Throwable JavaDoc t) {
309             throw ClassInfo.unwrapThrowable(t);
310           }
311         }
312       }
313       return value;
314     } catch (ProbeException e) {
315       throw e;
316     } catch (Throwable JavaDoc t) {
317       if (object == null) {
318         throw new ProbeException("Could not get property '" + name + "' from null reference. Cause: " + t.toString(), t);
319       } else {
320         throw new ProbeException("Could not get property '" + name + "' from " + object.getClass().getName() + ". Cause: " + t.toString(), t);
321       }
322     }
323   }
324
325   protected void setProperty(Object JavaDoc object, String JavaDoc name, Object JavaDoc value) {
326     ClassInfo classCache = ClassInfo.getInstance(object.getClass());
327     try {
328       if (name.indexOf("[") > -1) {
329         setIndexedProperty(object, name, value);
330       } else {
331         if (object instanceof Map JavaDoc) {
332           ((Map JavaDoc) object).put(name, value);
333         } else {
334           Method JavaDoc method = classCache.getSetter(name);
335           if (method == null) {
336             throw new NoSuchMethodException JavaDoc("No SET method for property " + name + " on instance of " + object.getClass().getName());
337           }
338           Object JavaDoc[] params = new Object JavaDoc[1];
339           params[0] = value;
340           try {
341             method.invoke(object, params);
342           } catch (Throwable JavaDoc t) {
343             throw ClassInfo.unwrapThrowable(t);
344           }
345         }
346       }
347     } catch (ProbeException e) {
348       throw e;
349     } catch (Throwable JavaDoc t) {
350       if (object == null) {
351         throw new ProbeException("Could not set property '" + name + "' for null reference. Cause: " + t.toString(), t);
352       } else {
353         throw new ProbeException("Could not set property '" + name + "' for " + object.getClass().getName() + ". Cause: " + t.toString(), t);
354       }
355     }
356   }
357
358 }
359
360
361
Popular Tags