EMMA Coverage Report (generated Sat Nov 03 21:53:04 GMT 2007)
[all classes][sf.qof.util]

COVERAGE SUMMARY FOR SOURCE FILE [ReflectionUtils.java]

nameclass, %method, %block, %line, %
ReflectionUtils.java100% (1/1)88%  (14/16)87%  (375/432)84%  (71.8/86)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ReflectionUtils100% (1/1)88%  (14/16)87%  (375/432)84%  (71.8/86)
ReflectionUtils (): void 0%   (0/1)0%   (0/3)0%   (0/1)
box (Class): Class 0%   (0/1)0%   (0/11)0%   (0/2)
getCollectionParameterizedType (Type): Class 100% (1/1)52%  (28/54)78%  (7/9)
findSetter (Class, String, Set): Method 100% (1/1)71%  (25/35)44%  (4/9)
unbox (Class): Class 100% (1/1)82%  (9/11)90%  (1.8/2)
findGetter (Class, String): Method 100% (1/1)85%  (28/33)64%  (7/11)
<static initializer> 100% (1/1)100% (70/70)100% (13/13)
createGetterName (String): String 100% (1/1)100% (17/17)100% (1/1)
createIsGetterName (String): String 100% (1/1)100% (17/17)100% (1/1)
createSetterName (String): String 100% (1/1)100% (17/17)100% (1/1)
findSetter (Class, String): Method 100% (1/1)100% (31/31)100% (6/6)
getArrayComponentType (Type): Class 100% (1/1)100% (28/28)100% (9/9)
getCollectionParameterizedKeyType (Type): Class 100% (1/1)100% (21/21)100% (6/6)
getCollectionType (Type): Class 100% (1/1)100% (23/23)100% (5/5)
getConstructorSignature (Constructor): Signature 100% (1/1)100% (29/29)100% (5/5)
getMethodSignature (Method): Signature 100% (1/1)100% (32/32)100% (5/5)

1/*
2 * Copyright 2007 brunella ltd
3 *
4 * Licensed under the LGPL Version 3 (the "License");
5 * you may not use this file except in compliance with the License.
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
11 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
12 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
15 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
16 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
17 * THE POSSIBILITY OF SUCH DAMAGE.
18 */
19package sf.qof.util;
20 
21import java.lang.reflect.Constructor;
22import java.lang.reflect.GenericArrayType;
23import java.lang.reflect.Method;
24import java.lang.reflect.ParameterizedType;
25import java.lang.reflect.Type;
26import java.util.Collection;
27import java.util.HashMap;
28import java.util.Map;
29import java.util.Set;
30 
31import net.sf.cglib.core.Signature;
32 
33import sf.qof.exception.ValidationException;
34 
35/**
36 * Utility class for reflection functionality.
37 */
38public final class ReflectionUtils {
39 
40  private ReflectionUtils() { }
41  
42  /**
43   * Returns the getter method for a field name in a specified class.
44   * 
45   * @param type       the class
46   * @param fieldName  field name
47   * @return           getter method for a field or null
48   */
49  public static Method findGetter(Class<?> type, String fieldName) {
50    try {
51      return type.getMethod(createGetterName(fieldName), (Class[]) null);
52    } catch (SecurityException e) {
53    } catch (NoSuchMethodException e) {
54    }
55    try {
56      Method method = type.getMethod(createIsGetterName(fieldName), (Class[]) null);
57      if (method.getReturnType() == Boolean.class || method.getReturnType() == Boolean.TYPE) {
58        return method;
59      }
60    } catch (SecurityException e) {
61    } catch (NoSuchMethodException e) {
62    }
63    return null;
64  }
65 
66  /**
67   * Returns the setter method for a field name in a specified class.
68   * 
69   * @param type       the class
70   * @param fieldName  field name
71   * @return           setter method for a field or null
72   */
73  public static Method findSetter(Class<?> type, String fieldName) {
74    String setterName = createSetterName(fieldName);
75    Method[] methods = type.getDeclaredMethods();
76    for (Method method : methods) {
77      if (method.getName().equals(setterName)) {
78        return method;
79      }
80    }
81    return null;
82  }
83 
84  /**
85   * Returns the setter method for a field name in a specified class
86   * that uses a parameter of a type in a set.
87   * 
88   * @param type           the class
89   * @param fieldName      field name
90   * @param mappableTypes  set of all mappable types
91   * @return               setter method for a field or null
92   */
93  public static Method findSetter(Class<?> type, String fieldName, Set<Class<?>> mappableTypes) {
94    if (mappableTypes == null) {
95      return findSetter(type, fieldName);
96    }
97    String setterName = createSetterName(fieldName);
98    for (Class<?> mappableType : mappableTypes) {
99      try {
100        return type.getMethod(setterName, new Class[] { mappableType });
101      } catch (SecurityException e) {
102        // ignore
103      } catch (NoSuchMethodException e) {
104        // ignore
105      }
106    }
107    return null;
108  }
109 
110  private static String createGetterName(String fieldName) {
111    return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
112  }
113 
114  private static String createIsGetterName(String fieldName) {
115    return "is" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
116  }
117 
118  private static String createSetterName(String fieldName) {
119    return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
120  }
121 
122  /**
123   * Returns the collection or map type of a type.
124   * 
125   * @param type  the type
126   * @return      the collection type or null
127   */
128  public static Class<?> getCollectionType(Type type) {
129    if (type instanceof ParameterizedType) {
130      Class<?> rawType = (Class<?>) ((ParameterizedType) type).getRawType();
131      if ((Collection.class.isAssignableFrom(rawType) || 
132           Map.class.isAssignableFrom(rawType)) && type != void.class) {
133        return rawType;
134      }
135    }
136    return null;
137  }
138 
139  /**
140   * Returns the array component type of a type.
141   * 
142   * @param type  the type
143   * @return      the array component type or null
144   */
145  public static Class<?> getArrayComponentType(Type type) {
146    if (type instanceof Class<?>) {
147      Class<?> clazz = (Class<?>)type;
148      if (clazz.isArray()) {
149        return clazz.getComponentType();
150      }
151    } else if (type instanceof GenericArrayType) {
152      Type componentType = ((GenericArrayType)type).getGenericComponentType();
153      if (componentType instanceof Class<?>) {
154        return (Class<?>)componentType;
155      }
156    }
157    return null;
158  }
159 
160  /**
161   * Returns the parameterized type of a collection type.
162   * For example if <code>type</code> is <code>List&lt;String&gt;</code>
163   * this method returns <code>String</code>. If <code>type</code> is 
164   * <code>Map&lt;int, String&gt;</code> it returns <code>String</code>. 
165   * 
166   * @param type  the parameterized type
167   * @return      the parameterized type
168   * @throws ValidationException if type is not parameterized
169   */
170  public static Class<?> getCollectionParameterizedType(Type type) {
171    if (type instanceof ParameterizedType) {
172      ParameterizedType parameterizedType = (ParameterizedType) type;
173      int numTypeArguments = parameterizedType.getActualTypeArguments().length;
174      if (numTypeArguments == 1) {
175        return (Class<?>) parameterizedType.getActualTypeArguments()[0];
176      } else if (numTypeArguments == 2) {
177        return (Class<?>) parameterizedType.getActualTypeArguments()[1];
178      } else {
179        throw new ValidationException("Collection parameterized type must be one for " + type);
180      }
181    } else {
182      throw new ValidationException("Collection " + type + " must be parameterized");
183    }
184  }
185 
186  /**
187   * Returns the key type of a parameterized type.
188   * For example if <code>type</code> is <code>Map&lt;int, String&gt;</code>
189   * it returns <code>int</code>.
190   * 
191   * @param type  the parameterized type
192   * @return      the key type
193   */
194  public static Class<?> getCollectionParameterizedKeyType(Type type) {
195    if (type instanceof ParameterizedType) {
196      ParameterizedType parameterizedType = (ParameterizedType) type;
197      if (parameterizedType.getActualTypeArguments().length != 2) {
198        return null;
199      }
200      return (Class<?>) parameterizedType.getActualTypeArguments()[0];
201    } else {
202      return null;
203    }
204  }
205 
206  private static final Map<Class<?>, Class<?>> BOXED_CLASSES;
207  private static final Map<Class<?>, Class<?>> UNBOXED_CLASSES;
208  static {
209    BOXED_CLASSES = new HashMap<Class<?>, Class<?>>(8);
210    BOXED_CLASSES.put(Byte.class, Byte.TYPE);
211    BOXED_CLASSES.put(Short.class, Short.TYPE);
212    BOXED_CLASSES.put(Integer.class, Integer.TYPE);
213    BOXED_CLASSES.put(Long.class, Long.TYPE);
214    BOXED_CLASSES.put(Boolean.class, Boolean.TYPE);
215    BOXED_CLASSES.put(Float.class, Float.TYPE);
216    BOXED_CLASSES.put(Double.class, Double.TYPE);
217    BOXED_CLASSES.put(Void.class, Void.TYPE);
218 
219    UNBOXED_CLASSES = new HashMap<Class<?>, Class<?>>(8);
220    for (Class<?> boxed : BOXED_CLASSES.keySet()) {
221      UNBOXED_CLASSES.put(BOXED_CLASSES.get(boxed), boxed);
222    }
223  }
224 
225  /**
226   * Returns the unboxed type of a specified type. 
227   * Types that are not boxed are returned unchanged.
228   * 
229   * @param type  the type
230   * @return      unboxed type
231   */
232  public static Class<?> unbox(Class<?> type) {
233    Class<?> returnClass = BOXED_CLASSES.get(type);
234    return returnClass == null ? type : returnClass;
235  }
236 
237  /**
238   * Returns the boxed type of a specified primitive type. 
239   * Types that are not primitive types are returned unchanged.
240   * 
241   * @param type  the type
242   * @return      boxed type
243   */
244  public static Class<?> box(Class<?> type) {
245    Class<?> returnClass = UNBOXED_CLASSES.get(type);
246    return returnClass == null ? type : returnClass;
247  }
248 
249  /**
250   * Returns a method <code>Signature</code> object for a <code>Method</code> parameter.
251   * 
252   * @param method  the method
253   * @return        a method signature
254   */
255  public static Signature getMethodSignature(Method method) {
256    Class<?>[] params = method.getParameterTypes();
257    org.objectweb.asm.Type[] paramTypes = new org.objectweb.asm.Type[params.length];
258    for (int i = 0; i < params.length; i++) {
259      paramTypes[i] = org.objectweb.asm.Type.getType(params[i]);
260    }
261 
262    return new Signature(method.getName(), org.objectweb.asm.Type.getType(method.getReturnType()), paramTypes);
263  }
264 
265  /**
266   * Returns a constructor <code>Signature</code> object for a <code>Constructor</code> parameter.
267   * 
268   * @param constructor  the constructor
269   * @return             a constructor signature
270   */
271  public static Signature getConstructorSignature(Constructor<?> constructor) {
272    Class<?>[] params = constructor.getParameterTypes();
273    org.objectweb.asm.Type[] paramTypes = new org.objectweb.asm.Type[params.length];
274    for (int i = 0; i < params.length; i++) {
275      paramTypes[i] = org.objectweb.asm.Type.getType(params[i]);
276    }
277 
278    return new Signature("<init>", org.objectweb.asm.Type.VOID_TYPE, paramTypes);
279  }
280 
281}

[all classes][sf.qof.util]
EMMA 2.0.5312 (C) Vladimir Roubtsov