KickJava   Java API By Example, From Geeks To Geeks.

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


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.InvocationTargetException JavaDoc;
19 import java.lang.reflect.Method JavaDoc;
20 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
21 import java.math.BigDecimal JavaDoc;
22 import java.math.BigInteger JavaDoc;
23 import java.util.*;
24
25 /**
26  * This class represents a cached set of class definition information that
27  * allows for easy mapping between property names and getter/setter methods.
28  */

29 public class ClassInfo {
30
31   private static final String JavaDoc[] EMPTY_STRING_ARRAY = new String JavaDoc[0];
32   private static final Set SIMPLE_TYPE_SET = new HashSet();
33   private static final Map CLASS_INFO_MAP = Collections.synchronizedMap(new HashMap());
34
35   private String JavaDoc className;
36   private String JavaDoc[] readablePropertyNames = EMPTY_STRING_ARRAY;
37   private String JavaDoc[] writeablePropertyNames = EMPTY_STRING_ARRAY;
38   private HashMap setMethods = new HashMap();
39   private HashMap getMethods = new HashMap();
40   private HashMap setTypes = new HashMap();
41   private HashMap getTypes = new HashMap();
42
43   static {
44     SIMPLE_TYPE_SET.add(String JavaDoc.class);
45     SIMPLE_TYPE_SET.add(Byte JavaDoc.class);
46     SIMPLE_TYPE_SET.add(Short JavaDoc.class);
47     SIMPLE_TYPE_SET.add(Character JavaDoc.class);
48     SIMPLE_TYPE_SET.add(Integer JavaDoc.class);
49     SIMPLE_TYPE_SET.add(Long JavaDoc.class);
50     SIMPLE_TYPE_SET.add(Float JavaDoc.class);
51     SIMPLE_TYPE_SET.add(Double JavaDoc.class);
52     SIMPLE_TYPE_SET.add(Boolean JavaDoc.class);
53     SIMPLE_TYPE_SET.add(Date.class);
54     SIMPLE_TYPE_SET.add(Class JavaDoc.class);
55     SIMPLE_TYPE_SET.add(BigInteger JavaDoc.class);
56     SIMPLE_TYPE_SET.add(BigDecimal JavaDoc.class);
57
58     SIMPLE_TYPE_SET.add(Collection.class);
59     SIMPLE_TYPE_SET.add(Set.class);
60     SIMPLE_TYPE_SET.add(Map.class);
61     SIMPLE_TYPE_SET.add(List.class);
62     SIMPLE_TYPE_SET.add(HashMap.class);
63     SIMPLE_TYPE_SET.add(TreeMap.class);
64     SIMPLE_TYPE_SET.add(ArrayList.class);
65     SIMPLE_TYPE_SET.add(LinkedList.class);
66     SIMPLE_TYPE_SET.add(HashSet.class);
67     SIMPLE_TYPE_SET.add(TreeSet.class);
68     SIMPLE_TYPE_SET.add(Vector.class);
69     SIMPLE_TYPE_SET.add(Hashtable.class);
70     SIMPLE_TYPE_SET.add(Enumeration.class);
71   }
72
73   private ClassInfo(Class JavaDoc clazz) {
74     className = clazz.getName();
75     addMethods(clazz);
76     Class JavaDoc superClass = clazz.getSuperclass();
77     while (superClass != null) {
78       addMethods(superClass);
79       superClass = superClass.getSuperclass();
80     }
81     readablePropertyNames = (String JavaDoc[]) getMethods.keySet().toArray(new String JavaDoc[getMethods.keySet().size()]);
82     writeablePropertyNames = (String JavaDoc[]) setMethods.keySet().toArray(new String JavaDoc[setMethods.keySet().size()]);
83   }
84
85   private void addMethods(Class JavaDoc cls) {
86     Method JavaDoc[] methods = cls.getMethods();
87     for (int i = 0; i < methods.length; i++) {
88       String JavaDoc name = methods[i].getName();
89       if (name.startsWith("set") && name.length() > 3) {
90         if (methods[i].getParameterTypes().length == 1) {
91           name = dropCase(name);
92           setMethods.put(name, methods[i]);
93           setTypes.put(name, methods[i].getParameterTypes()[0]);
94         }
95       } else if (name.startsWith("get") && name.length() > 3) {
96         if (methods[i].getParameterTypes().length == 0) {
97           name = dropCase(name);
98           getMethods.put(name, methods[i]);
99           getTypes.put(name, methods[i].getReturnType());
100         }
101       } else if (name.startsWith("is") && name.length() > 2) {
102         if (methods[i].getParameterTypes().length == 0) {
103           name = dropCase(name);
104           getMethods.put(name, methods[i]);
105           getTypes.put(name, methods[i].getReturnType());
106         }
107       }
108       name = null;
109     }
110   }
111
112   private static String JavaDoc dropCase(String JavaDoc name) {
113     if (name.startsWith("is")) {
114       name = name.substring(2);
115     } else if (name.startsWith("get") || name.startsWith("set")) {
116       name = name.substring(3);
117     } else {
118       throw new ProbeException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
119     }
120
121     if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
122       name = name.substring(0, 1).toLowerCase(Locale.US) + name.substring(1);
123     }
124
125     return name;
126   }
127
128   /**
129    * Gets the name of the class the instance provides information for
130    *
131    * @return The class name
132    */

133   public String JavaDoc getClassName() {
134     return className;
135   }
136
137   /**
138    * Gets the setter for a property as a Method object
139    *
140    * @param propertyName - the property
141    * @return The Method
142    */

143   public Method JavaDoc getSetter(String JavaDoc propertyName) {
144     Method JavaDoc method = (Method JavaDoc) setMethods.get(propertyName);
145     if (method == null) {
146       throw new ProbeException("There is no WRITEABLE property named '" + propertyName + "' in class '" + className + "'");
147     }
148     return method;
149   }
150
151   /**
152    * Gets the getter for a property as a Method object
153    *
154    * @param propertyName - the property
155    * @return The Method
156    */

157   public Method JavaDoc getGetter(String JavaDoc propertyName) {
158     Method JavaDoc method = (Method JavaDoc) getMethods.get(propertyName);
159     if (method == null) {
160       throw new ProbeException("There is no READABLE property named '" + propertyName + "' in class '" + className + "'");
161     }
162     return method;
163   }
164
165   /**
166    * Gets the type for a property setter
167    *
168    * @param propertyName - the name of the property
169    * @return The Class of the propery setter
170    */

171   public Class JavaDoc getSetterType(String JavaDoc propertyName) {
172     Class JavaDoc clazz = (Class JavaDoc) setTypes.get(propertyName);
173     if (clazz == null) {
174       throw new ProbeException("There is no WRITEABLE property named '" + propertyName + "' in class '" + className + "'");
175     }
176     return clazz;
177   }
178
179   /**
180    * Gets the type for a property getter
181    *
182    * @param propertyName - the name of the property
183    * @return The Class of the propery getter
184    */

185   public Class JavaDoc getGetterType(String JavaDoc propertyName) {
186     Class JavaDoc clazz = (Class JavaDoc) getTypes.get(propertyName);
187     if (clazz == null) {
188       throw new ProbeException("There is no READABLE property named '" + propertyName + "' in class '" + className + "'");
189     }
190     return clazz;
191   }
192
193   /**
194    * Gets an array of the readable properties for an object
195    *
196    * @return The array
197    */

198   public String JavaDoc[] getReadablePropertyNames() {
199     return readablePropertyNames;
200   }
201
202   /**
203    * Gets an array of the writeable properties for an object
204    *
205    * @return The array
206    */

207   public String JavaDoc[] getWriteablePropertyNames() {
208     return writeablePropertyNames;
209   }
210
211   /**
212    * Check to see if a class has a writeable property by name
213    *
214    * @param propertyName - the name of the property to check
215    * @return True if the object has a writeable property by the name
216    */

217   public boolean hasWritableProperty(String JavaDoc propertyName) {
218     return setMethods.keySet().contains(propertyName);
219   }
220
221   /**
222    * Check to see if a class has a readable property by name
223    *
224    * @param propertyName - the name of the property to check
225    * @return True if the object has a readable property by the name
226    */

227   public boolean hasReadableProperty(String JavaDoc propertyName) {
228     return getMethods.keySet().contains(propertyName);
229   }
230
231   /**
232    * Tells us if the class passed in is a knwon common type
233    *
234    * @param clazz The class to check
235    * @return True if the class is known
236    */

237   public static boolean isKnownType(Class JavaDoc clazz) {
238     if (SIMPLE_TYPE_SET.contains(clazz)) {
239       return true;
240     } else if (Collection.class.isAssignableFrom(clazz)) {
241       return true;
242     } else if (Map.class.isAssignableFrom(clazz)) {
243       return true;
244     } else if (List.class.isAssignableFrom(clazz)) {
245       return true;
246     } else if (Set.class.isAssignableFrom(clazz)) {
247       return true;
248     } else if (Iterator.class.isAssignableFrom(clazz)) {
249       return true;
250     } else {
251       return false;
252     }
253   }
254
255   /**
256    * Gets an instance of ClassInfo for the specified class.
257    *
258    * @param clazz The class for which to lookup the method cache.
259    * @return The method cache for the class
260    */

261   public static ClassInfo getInstance(Class JavaDoc clazz) {
262     synchronized (clazz) {
263       ClassInfo cache = (ClassInfo) CLASS_INFO_MAP.get(clazz);
264       if (cache == null) {
265         cache = new ClassInfo(clazz);
266         CLASS_INFO_MAP.put(clazz, cache);
267       }
268       return cache;
269     }
270   }
271
272   /**
273    * Examines a Throwable object and gets it's root cause
274    *
275    * @param t - the exception to examine
276    * @return The root cause
277    */

278   public static Throwable JavaDoc unwrapThrowable(Throwable JavaDoc t) {
279     Throwable JavaDoc t2 = t;
280     while (true) {
281       if (t2 instanceof InvocationTargetException JavaDoc) {
282         t2 = ((InvocationTargetException JavaDoc) t).getTargetException();
283       } else if (t instanceof UndeclaredThrowableException JavaDoc) {
284         t2 = ((UndeclaredThrowableException JavaDoc) t).getUndeclaredThrowable();
285       } else {
286         return t2;
287       }
288     }
289   }
290
291
292 }
293
294
295
296
Popular Tags