View Javadoc

1   package net.sf.twip.util;
2   
3   import java.lang.annotation.Annotation;
4   import java.lang.reflect.*;
5   import java.util.List;
6   
7   /**
8    * In <code>java.lang.reflect</code> the parameters are not first class citizens: you can only
9    * access them by several index methods, and the name is not kept in the class file. This class
10   * tries to fill that gap as good as it goes.
11   */
12  public abstract class Parameter {
13  
14  	public static List<Parameter> of(Method method) {
15  		return MethodParameter.of(method);
16  	}
17  
18  	public static List<Parameter> of(Constructor<?> constructor) {
19  		return ConstructorParameter.of(constructor);
20  	}
21  
22  	protected final int index;
23  
24  	public Parameter(int index) {
25  		this.index = index;
26  	}
27  
28  	public int getIndex() {
29  		return index;
30  	}
31  
32  	/**
33  	 * @return the annotation of that type or <code>null</code> if the parameter is not annotated
34  	 *         with that type.
35  	 */
36  	public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
37  		for (final Annotation annotation : getAnnotations()) {
38  			if (annotationType.isInstance(annotation)) {
39  				return annotationType.cast(annotation);
40  			}
41  		}
42  		return null;
43  	}
44  
45  	public abstract Annotation[] getAnnotations();
46  
47  	public abstract Class<?> getType();
48  
49  	public abstract Method getMethod();
50  
51  	public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) {
52  		return getAnnotation(annotationType) != null;
53  	}
54  
55  	/**
56  	 * Can that value be passed as this parameter? I.e. is it an instance of the correct type or (if
57  	 * it's not really primitive) <code>null</code>; correctly handles primitive types where
58  	 * {@link Class#isInstance(Object)} returns <code>false</code> for.
59  	 */
60  	public boolean isCallable(Object value) {
61  		Class<?> parameterType = getType();
62  		if (parameterType.isPrimitive()) {
63  			if (parameterType == Boolean.TYPE)
64  				return value.getClass() == Boolean.class;
65  			if (parameterType == Byte.TYPE)
66  				return value.getClass() == Byte.class;
67  			if (parameterType == Character.TYPE)
68  				return value.getClass() == Character.class;
69  			if (parameterType == Short.TYPE)
70  				return value.getClass() == Short.class;
71  			if (parameterType == Integer.TYPE)
72  				return value.getClass() == Integer.class;
73  			if (parameterType == Long.TYPE)
74  				return value.getClass() == Long.class;
75  			if (parameterType == Float.TYPE)
76  				return value.getClass() == Float.class;
77  			if (parameterType == Double.TYPE)
78  				return value.getClass() == Double.class;
79  			throw new AssertionError("unsupported primitive type: " + parameterType);
80  		} else {
81  			return value == null || parameterType.isInstance(value);
82  		}
83  	}
84  
85  	@Override
86  	public String toString() {
87  		return Parameter.class.getSimpleName() + "#" + getIndex() + " of "
88  				+ getMethod().toGenericString();
89  	}
90  
91  }