1/**
2 *
3 */
4package org.junit.experimental.theories;
5
6import java.lang.annotation.Annotation;
7import java.lang.reflect.Constructor;
8import java.lang.reflect.Method;
9import java.util.ArrayList;
10import java.util.Arrays;
11import java.util.List;
12
13public class ParameterSignature {
14	public static ArrayList<ParameterSignature> signatures(Method method) {
15		return signatures(method.getParameterTypes(), method
16				.getParameterAnnotations());
17	}
18
19	public static List<ParameterSignature> signatures(Constructor<?> constructor) {
20		return signatures(constructor.getParameterTypes(), constructor
21				.getParameterAnnotations());
22	}
23
24	private static ArrayList<ParameterSignature> signatures(
25			Class<?>[] parameterTypes, Annotation[][] parameterAnnotations) {
26		ArrayList<ParameterSignature> sigs= new ArrayList<ParameterSignature>();
27		for (int i= 0; i < parameterTypes.length; i++) {
28			sigs.add(new ParameterSignature(parameterTypes[i],
29					parameterAnnotations[i]));
30		}
31		return sigs;
32	}
33
34	private final Class<?> type;
35
36	private final Annotation[] annotations;
37
38	private ParameterSignature(Class<?> type, Annotation[] annotations) {
39		this.type= type;
40		this.annotations= annotations;
41	}
42
43	public boolean canAcceptType(Class<?> candidate) {
44		return type.isAssignableFrom(candidate);
45	}
46
47	public Class<?> getType() {
48		return type;
49	}
50
51	public List<Annotation> getAnnotations() {
52		return Arrays.asList(annotations);
53	}
54
55	public boolean canAcceptArrayType(Class<?> type) {
56		return type.isArray() && canAcceptType(type.getComponentType());
57	}
58
59	public boolean hasAnnotation(Class<? extends Annotation> type) {
60		return getAnnotation(type) != null;
61	}
62
63	public <T extends Annotation> T findDeepAnnotation(Class<T> annotationType) {
64		Annotation[] annotations2= annotations;
65		return findDeepAnnotation(annotations2, annotationType, 3);
66	}
67
68	private <T extends Annotation> T findDeepAnnotation(
69			Annotation[] annotations, Class<T> annotationType, int depth) {
70		if (depth == 0)
71			return null;
72		for (Annotation each : annotations) {
73			if (annotationType.isInstance(each))
74				return annotationType.cast(each);
75			Annotation candidate= findDeepAnnotation(each.annotationType()
76					.getAnnotations(), annotationType, depth - 1);
77			if (candidate != null)
78				return annotationType.cast(candidate);
79		}
80
81		return null;
82	}
83
84	public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
85		for (Annotation each : getAnnotations())
86			if (annotationType.isInstance(each))
87				return annotationType.cast(each);
88		return null;
89	}
90}