|
19 | 19 | import java.lang.reflect.ParameterizedType;
|
20 | 20 | import java.lang.reflect.Type;
|
21 | 21 | import java.lang.reflect.TypeVariable;
|
| 22 | +import java.lang.reflect.WildcardType; |
22 | 23 |
|
23 | 24 | public class TypeParameterResolver {
|
24 | 25 |
|
25 |
| - public static Type resolveReturnType(Method method, Type mapper) { |
26 |
| - Type returnType = method.getGenericReturnType(); |
| 26 | + public static Type[] resolveParamTypes(Method method, Type mapper) { |
| 27 | + Type[] paramTypes = method.getGenericParameterTypes(); |
27 | 28 | Class<?> declaringClass = method.getDeclaringClass();
|
28 |
| - return getReturnType(returnType, mapper, declaringClass); |
| 29 | + Type[] result = new Type[paramTypes.length]; |
| 30 | + for (int i = 0; i < paramTypes.length; i++) { |
| 31 | + if (paramTypes[i] instanceof Class) { |
| 32 | + result[i] = paramTypes[i]; |
| 33 | + } else if (paramTypes[i] instanceof TypeVariable) { |
| 34 | + result[i] = resolveTypeVar((TypeVariable<?>) paramTypes[i], mapper, declaringClass); |
| 35 | + } else if (paramTypes[i] instanceof ParameterizedType) { |
| 36 | + result[i] = resolveParameterizedType((ParameterizedType) paramTypes[i], mapper, declaringClass); |
| 37 | + } else { |
| 38 | + // TODO: other types? |
| 39 | + } |
| 40 | + } |
| 41 | + return result; |
29 | 42 | }
|
30 | 43 |
|
31 |
| - private static Type getReturnType(Type returnType, Type mapper, Class<?> declaringClass) { |
| 44 | + public static Type resolveReturnType(Method method, Type mapper) { |
| 45 | + Type returnType = method.getGenericReturnType(); |
| 46 | + Class<?> declaringClass = method.getDeclaringClass(); |
32 | 47 | Type result = null;
|
33 |
| - if (returnType instanceof Class) { |
34 |
| - result = returnType; |
35 |
| - } else if (returnType instanceof TypeVariable) { |
36 |
| - if (mapper instanceof Class) { |
37 |
| - result = resolveTypeVar((TypeVariable<?>) returnType, mapper, declaringClass); |
38 |
| - } |
| 48 | + if (returnType instanceof TypeVariable) { |
| 49 | + result = resolveTypeVar((TypeVariable<?>) returnType, mapper, declaringClass); |
39 | 50 | } else if (returnType instanceof ParameterizedType) {
|
40 |
| - result = scanParameterizedType((ParameterizedType) returnType, mapper, declaringClass); |
| 51 | + result = resolveParameterizedType((ParameterizedType) returnType, mapper, declaringClass); |
| 52 | + } else { |
| 53 | + result = returnType; |
41 | 54 | }
|
42 |
| - assert result != null; |
43 | 55 | return result;
|
44 | 56 | }
|
45 | 57 |
|
46 |
| - private static ParameterizedType scanParameterizedType(ParameterizedType parameterizedType, Type mapper, Class<?> declaringClass) { |
| 58 | + private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type mapper, Class<?> declaringClass) { |
47 | 59 | Class<?> rawType = (Class<?>) parameterizedType.getRawType();
|
48 | 60 | Type[] typeArgs = parameterizedType.getActualTypeArguments();
|
49 | 61 | Type[] args = new Type[typeArgs.length];
|
50 | 62 | for (int i = 0; i < typeArgs.length; i++) {
|
51 |
| - if (typeArgs[i] instanceof Class) { |
52 |
| - args[i] = typeArgs[i]; |
53 |
| - } else if (typeArgs[i] instanceof TypeVariable) { |
| 63 | + if (typeArgs[i] instanceof TypeVariable) { |
54 | 64 | args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], mapper, declaringClass);
|
55 | 65 | } else if (typeArgs[i] instanceof ParameterizedType) {
|
56 |
| - args[i] = scanParameterizedType((ParameterizedType) typeArgs[i], mapper, declaringClass); |
| 66 | + args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], mapper, declaringClass); |
| 67 | + } else if (typeArgs[i] instanceof WildcardType) { |
| 68 | + args[i] = resolveWildcardType((WildcardType) typeArgs[i], mapper, declaringClass); |
| 69 | + } else { |
| 70 | + args[i] = typeArgs[i]; |
57 | 71 | }
|
58 | 72 | }
|
59 | 73 | return new ParameterizedTypeImpl(rawType, null, args);
|
60 | 74 | }
|
61 | 75 |
|
62 |
| - private static Type resolveTypeVar(TypeVariable<?> typeVar, Type mapper, Class<?> declaringClass) { |
| 76 | + private static Type resolveWildcardType(WildcardType wildcardType, Type mapper, Class<?> declaringClass) { |
| 77 | + Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), mapper, declaringClass); |
| 78 | + Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), mapper, declaringClass); |
| 79 | + return new WildcardTypeImpl(lowerBounds, upperBounds); |
| 80 | + } |
| 81 | + |
| 82 | + private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type mapper, Class<?> declaringClass) { |
| 83 | + Type[] result = new Type[bounds.length]; |
| 84 | + for (int i = 0; i < bounds.length; i++) { |
| 85 | + if (bounds[i] instanceof TypeVariable) { |
| 86 | + result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], mapper, declaringClass); |
| 87 | + } else if (bounds[i] instanceof ParameterizedType) { |
| 88 | + result[i] = resolveParameterizedType((ParameterizedType) bounds[i], mapper, declaringClass); |
| 89 | + } else if (bounds[i] instanceof WildcardType) { |
| 90 | + result[i] = resolveWildcardType((WildcardType) bounds[i], mapper, declaringClass); |
| 91 | + } else { |
| 92 | + result[i] = bounds[i]; |
| 93 | + } |
| 94 | + } |
| 95 | + return result; |
| 96 | + } |
| 97 | + |
| 98 | + private static Type resolveTypeVar(TypeVariable<?> typeVar, Type type, Class<?> declaringClass) { |
63 | 99 | Type result = null;
|
64 |
| - Class<?> mapperClass = null; |
65 |
| - if (mapper instanceof Class) { |
66 |
| - mapperClass = (Class<?>) mapper; |
67 |
| - } else if (mapper instanceof ParameterizedType) { |
68 |
| - ParameterizedType parameterizedType = (ParameterizedType) mapper; |
69 |
| - mapperClass = (Class<?>) parameterizedType.getRawType(); |
| 100 | + Class<?> clazz = null; |
| 101 | + if (type instanceof Class) { |
| 102 | + clazz = (Class<?>) type; |
| 103 | + } else if (type instanceof ParameterizedType) { |
| 104 | + ParameterizedType parameterizedType = (ParameterizedType) type; |
| 105 | + clazz = (Class<?>) parameterizedType.getRawType(); |
70 | 106 | } else {
|
71 |
| - throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + mapper.getClass()); |
| 107 | + throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + type.getClass()); |
| 108 | + } |
| 109 | + |
| 110 | + if (clazz == declaringClass) { |
| 111 | + return typeVar; |
72 | 112 | }
|
73 | 113 |
|
74 |
| - Type[] superInterfaces = mapperClass.getGenericInterfaces(); |
| 114 | + Type[] superInterfaces = clazz.getGenericInterfaces(); |
75 | 115 | for (Type superInterface : superInterfaces) {
|
76 |
| - Class<?> parentAsClass = null; |
77 | 116 | if (superInterface instanceof ParameterizedType) {
|
78 | 117 | ParameterizedType parentAsType = (ParameterizedType) superInterface;
|
79 |
| - parentAsClass = (Class<?>) parentAsType.getRawType(); |
80 |
| - Type[] typeArgs = parentAsType.getActualTypeArguments(); |
| 118 | + Class<?> parentAsClass = (Class<?>) parentAsType.getRawType(); |
81 | 119 | if (declaringClass == parentAsClass) {
|
| 120 | + Type[] typeArgs = parentAsType.getActualTypeArguments(); |
82 | 121 | TypeVariable<?>[] declaredTypeVars = declaringClass.getTypeParameters();
|
83 | 122 | for (int i = 0; i < declaredTypeVars.length; i++) {
|
84 | 123 | if (declaredTypeVars[i] == typeVar) {
|
85 | 124 | if (typeArgs[i] instanceof TypeVariable) {
|
86 |
| - TypeVariable<?>[] mapperTypeParams = mapperClass.getTypeParameters(); |
87 |
| - for (int j = 0; j < mapperTypeParams.length; j++) { |
88 |
| - if (mapperTypeParams[j] == typeArgs[i]) { |
89 |
| - result = ((ParameterizedType) mapper).getActualTypeArguments()[j]; |
| 125 | + TypeVariable<?>[] typeParams = clazz.getTypeParameters(); |
| 126 | + for (int j = 0; j < typeParams.length; j++) { |
| 127 | + if (typeParams[j] == typeArgs[i]) { |
| 128 | + result = ((ParameterizedType) type).getActualTypeArguments()[j]; |
| 129 | + break; |
90 | 130 | }
|
91 | 131 | }
|
92 | 132 | } else {
|
93 | 133 | result = typeArgs[i];
|
94 | 134 | }
|
95 | 135 | }
|
96 | 136 | }
|
97 |
| - } else { |
| 137 | + } else if (declaringClass.isAssignableFrom(parentAsClass)) { |
98 | 138 | result = resolveTypeVar(typeVar, parentAsType, declaringClass);
|
99 | 139 | }
|
100 | 140 | } else if (superInterface instanceof Class) {
|
101 |
| - result = resolveTypeVar(typeVar, superInterface, declaringClass); |
| 141 | + if (declaringClass.isAssignableFrom((Class<?>) superInterface)) { |
| 142 | + result = resolveTypeVar(typeVar, superInterface, declaringClass); |
| 143 | + } |
102 | 144 | }
|
103 | 145 | }
|
104 |
| - assert result != null; |
| 146 | + if (result == null) { |
| 147 | + return typeVar; |
| 148 | + } |
105 | 149 | return result;
|
106 | 150 | }
|
107 | 151 |
|
108 | 152 | private TypeParameterResolver() {
|
109 | 153 | super();
|
110 | 154 | }
|
| 155 | + |
| 156 | + static class ParameterizedTypeImpl implements ParameterizedType { |
| 157 | + private Class<?> rawType; |
| 158 | + |
| 159 | + private Type ownerType; |
| 160 | + |
| 161 | + private Type[] actualTypeArguments; |
| 162 | + |
| 163 | + public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) { |
| 164 | + super(); |
| 165 | + this.rawType = rawType; |
| 166 | + this.ownerType = ownerType; |
| 167 | + this.actualTypeArguments = actualTypeArguments; |
| 168 | + } |
| 169 | + |
| 170 | + @Override |
| 171 | + public Type[] getActualTypeArguments() { |
| 172 | + return actualTypeArguments; |
| 173 | + } |
| 174 | + |
| 175 | + @Override |
| 176 | + public Type getOwnerType() { |
| 177 | + return ownerType; |
| 178 | + } |
| 179 | + |
| 180 | + @Override |
| 181 | + public Type getRawType() { |
| 182 | + return rawType; |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + static class WildcardTypeImpl implements WildcardType { |
| 187 | + private Type[] lowerBounds; |
| 188 | + |
| 189 | + private Type[] upperBounds; |
| 190 | + |
| 191 | + private WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) { |
| 192 | + super(); |
| 193 | + this.lowerBounds = lowerBounds; |
| 194 | + this.upperBounds = upperBounds; |
| 195 | + } |
| 196 | + |
| 197 | + @Override |
| 198 | + public Type[] getLowerBounds() { |
| 199 | + return lowerBounds; |
| 200 | + } |
| 201 | + |
| 202 | + @Override |
| 203 | + public Type[] getUpperBounds() { |
| 204 | + return upperBounds; |
| 205 | + } |
| 206 | + } |
111 | 207 | }
|
0 commit comments