private static Class<?> resolveReturnType(Method method, Class<? extends Decoder> decoder) {
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof Class) {
return (Class<?>) genericReturnType;
} else if (genericReturnType instanceof TypeVariable) {
TypeVariable type = ((TypeVariable) genericReturnType);
List<Class> classes = new ArrayList<>();
Class c = decoder;
while (c != method.getDeclaringClass() && c != null) {
classes.add(c);
c = c.getSuperclass();
}
Collections.reverse(classes);
String currentName = type.getName();
int currentPos = -1;
for (Class clz : classes) {
for (int i = 0; i < clz.getSuperclass().getTypeParameters().length; ++i) {
TypeVariable<? extends Class<?>> param = clz.getSuperclass().getTypeParameters()[i];
if (param.getName().equals(currentName)) {
currentPos = i;
break;
}
}
Type gs = clz.getGenericSuperclass();
if (gs instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) gs;
Type at = pt.getActualTypeArguments()[currentPos];
if (at instanceof Class) {
return (Class<?>) at;
} else if (at instanceof TypeVariable) {
TypeVariable tv = (TypeVariable) at;
currentName = tv.getName();
}
}
}
//todo: should we throw an exception here? It should never actually be reached
return method.getReturnType();