1 package net.sf.josceleton.commons.reflect;
2
3 import java.lang.reflect.Constructor;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.Map;
7
8
9
10
11 public final class ReflectUtil {
12
13 private static final Map<Class<?>, Class<?>> PRIMITIVES_TO_BOXED;
14 static {
15 final Map<Class<?>, Class<?>> tmp = new HashMap<Class<?>, Class<?>>();
16 tmp.put(Boolean.TYPE, Boolean.class);
17 tmp.put(Float.TYPE, Float.class);
18 tmp.put(Double.TYPE, Double.class);
19 tmp.put(Byte.TYPE, Byte.class);
20 tmp.put(Character.TYPE, Character.class);
21 tmp.put(Integer.TYPE, Integer.class);
22 tmp.put(Long.TYPE, Long.class);
23 PRIMITIVES_TO_BOXED = Collections.unmodifiableMap(tmp);
24 }
25
26 private ReflectUtil() {
27
28
29
30
31 @SuppressWarnings("unchecked")
32 public static <T> Constructor<T> findConstructor(final ClassAdapter<T> clazz, final Object[] arguments) {
33 final Constructor<T>[] constructors = (Constructor<T>[]) clazz.getConstructors();
34
35 for (final Constructor<T> currentConstructor : constructors) {
36
37 final Class<?>[] parameterTypes = currentConstructor.getParameterTypes();
38 if(ReflectUtil.typesAreCompatible(ReflectUtil.adapt(parameterTypes), arguments) == true) {
39
40 return currentConstructor;
41 }
42 }
43
44 throw DynamicInstantiationException.newForNotFoundConstructor(clazz, arguments);
45 }
46
47 private static ClassAdapter<?>[] adapt(final Class<?>[] raw) {
48 final ClassAdapter<?>[] result = new ClassAdapter<?>[raw.length];
49 for (int i = 0; i < result.length; i++) {
50 result[i] = ClassAdapterImpl.create(raw[i]);
51 }
52 return result;
53 }
54
55 private static boolean typesAreCompatible(final ClassAdapter<?>[] parameterTypes, final Object[] givenArguments) {
56 if(parameterTypes.length != givenArguments.length) {
57 return false;
58 }
59 for (int i = 0; i < parameterTypes.length; i++) {
60 final ClassAdapter<?> parameterType = parameterTypes[i];
61 final Class<?> argumentClass = givenArguments[i].getClass();
62 final ClassAdapter<?> argumentType = ClassAdapterImpl.create(argumentClass);
63 if(ReflectUtil.isAssignable(argumentType, parameterType) == false) {
64 return false;
65 }
66 }
67 return true;
68 }
69
70
71
72
73
74
75
76
77
78 public static boolean isAssignable(final ClassAdapter<?> typeUnderInspection, final ClassAdapter<?> superType) {
79 if(superType.isPrimitive() == false) {
80 return superType.isAssignableFrom(typeUnderInspection);
81 }
82
83 final Class<?> boxedSourceType = PRIMITIVES_TO_BOXED.get(superType.getInnerClass());
84 if(boxedSourceType == null) {
85 throw new RuntimeException("Could not find assignable for primitive type [" + superType + "]!");
86 }
87
88 return boxedSourceType == typeUnderInspection.getInnerClass();
89 }
90 }