Skip to content

Commit 3e8ca88

Browse files
committed
Implemented resolveParamTypes() (but it was not necessary to fix #321) and added more test cases.
1 parent 74c817e commit 3e8ca88

File tree

14 files changed

+474
-131
lines changed

14 files changed

+474
-131
lines changed

src/main/java/org/apache/ibatis/reflection/ParameterizedTypeImpl.java

Lines changed: 0 additions & 52 deletions
This file was deleted.

src/main/java/org/apache/ibatis/reflection/TypeParameterResolver.java

Lines changed: 132 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,93 +19,189 @@
1919
import java.lang.reflect.ParameterizedType;
2020
import java.lang.reflect.Type;
2121
import java.lang.reflect.TypeVariable;
22+
import java.lang.reflect.WildcardType;
2223

2324
public class TypeParameterResolver {
2425

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();
2728
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;
2942
}
3043

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();
3247
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);
3950
} else if (returnType instanceof ParameterizedType) {
40-
result = scanParameterizedType((ParameterizedType) returnType, mapper, declaringClass);
51+
result = resolveParameterizedType((ParameterizedType) returnType, mapper, declaringClass);
52+
} else {
53+
result = returnType;
4154
}
42-
assert result != null;
4355
return result;
4456
}
4557

46-
private static ParameterizedType scanParameterizedType(ParameterizedType parameterizedType, Type mapper, Class<?> declaringClass) {
58+
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type mapper, Class<?> declaringClass) {
4759
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
4860
Type[] typeArgs = parameterizedType.getActualTypeArguments();
4961
Type[] args = new Type[typeArgs.length];
5062
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) {
5464
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], mapper, declaringClass);
5565
} 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];
5771
}
5872
}
5973
return new ParameterizedTypeImpl(rawType, null, args);
6074
}
6175

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) {
6399
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();
70106
} 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;
72112
}
73113

74-
Type[] superInterfaces = mapperClass.getGenericInterfaces();
114+
Type[] superInterfaces = clazz.getGenericInterfaces();
75115
for (Type superInterface : superInterfaces) {
76-
Class<?> parentAsClass = null;
77116
if (superInterface instanceof ParameterizedType) {
78117
ParameterizedType parentAsType = (ParameterizedType) superInterface;
79-
parentAsClass = (Class<?>) parentAsType.getRawType();
80-
Type[] typeArgs = parentAsType.getActualTypeArguments();
118+
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
81119
if (declaringClass == parentAsClass) {
120+
Type[] typeArgs = parentAsType.getActualTypeArguments();
82121
TypeVariable<?>[] declaredTypeVars = declaringClass.getTypeParameters();
83122
for (int i = 0; i < declaredTypeVars.length; i++) {
84123
if (declaredTypeVars[i] == typeVar) {
85124
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;
90130
}
91131
}
92132
} else {
93133
result = typeArgs[i];
94134
}
95135
}
96136
}
97-
} else {
137+
} else if (declaringClass.isAssignableFrom(parentAsClass)) {
98138
result = resolveTypeVar(typeVar, parentAsType, declaringClass);
99139
}
100140
} else if (superInterface instanceof Class) {
101-
result = resolveTypeVar(typeVar, superInterface, declaringClass);
141+
if (declaringClass.isAssignableFrom((Class<?>) superInterface)) {
142+
result = resolveTypeVar(typeVar, superInterface, declaringClass);
143+
}
102144
}
103145
}
104-
assert result != null;
146+
if (result == null) {
147+
return typeVar;
148+
}
105149
return result;
106150
}
107151

108152
private TypeParameterResolver() {
109153
super();
110154
}
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+
}
111207
}

0 commit comments

Comments
 (0)