Skip to content

Commit

Permalink
Add support for wildcard types
Browse files Browse the repository at this point in the history
  • Loading branch information
beikov committed Oct 1, 2015
1 parent 4d7c643 commit 5d4fd63
Showing 1 changed file with 54 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -237,33 +238,44 @@ public static Class<?>[] resolveTypeArguments(Class<?> concreteClass,
Class<?>[] resolvedClasses = new Class<?>[argumentTypes.length];

for (int i = 0; i < argumentTypes.length; i++) {
if (argumentTypes[i] instanceof TypeVariable<?>) {
resolvedClasses[i] = resolveTypeVariable(concreteClass,
(TypeVariable<?>) argumentTypes[i]);
} else if (argumentTypes[i] instanceof ParameterizedType) {
resolvedClasses[i] = (Class<?>) ((ParameterizedType) argumentTypes[i]).getRawType();
} else if (argumentTypes[i] instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) argumentTypes[i]).getGenericComponentType();
Class<?> componentClass;
if (componentType instanceof Class) {
componentClass = (Class<?>) componentType;
} else if (componentType instanceof ParameterizedType) {
componentClass = (Class<?>) ((ParameterizedType) componentType).getRawType();
} else {
throw new IllegalArgumentException("Unsupported array component type: " + componentType);
}

Object o = Array.newInstance((Class<?>) componentClass, 0);
resolvedClasses[i] = (Class<?>) o.getClass();
} else {
// We assume here that only class types, type variables and parameterized types are
// possible as argument types for the parameterized type
resolvedClasses[i] = (Class<?>) argumentTypes[i];
}
resolvedClasses[i] = resolveType(concreteClass, argumentTypes[i]);
}

return resolvedClasses;
}

private static Class<?> resolveType(Class<?> concreteClass, Type type) {
if (type instanceof TypeVariable<?>) {
return resolveTypeVariable(concreteClass, (TypeVariable<?>) type);
} else if (type instanceof ParameterizedType) {
return (Class<?>) ((ParameterizedType) type).getRawType();
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class<?> componentClass;
if (componentType instanceof Class) {
componentClass = (Class<?>) componentType;
} else if (componentType instanceof ParameterizedType) {
componentClass = (Class<?>) ((ParameterizedType) componentType).getRawType();
} else {
throw new IllegalArgumentException("Unsupported array component type: " + componentType);
}

Object o = Array.newInstance((Class<?>) componentClass, 0);
return (Class<?>) o.getClass();
} else if (type instanceof WildcardType) {
WildcardType wildcardType = ((WildcardType) type);

if (wildcardType.getLowerBounds().length > 0) {
return resolveType(concreteClass, wildcardType.getLowerBounds()[0]);
} else {
return resolveType(concreteClass, wildcardType.getUpperBounds()[0]);
}
} else {
// We assume here that only class types, type variables and parameterized types are
// possible as argument types for the parameterized type
return (Class<?>) type;
}
}

private static Class<?> getClassThatContainsTypeVariable(TypeVariable<?> typeVariable) {
if (isSubtype(typeVariable.getGenericDeclaration().getClass(),
Expand Down Expand Up @@ -387,7 +399,16 @@ public static Class<?> resolveTypeVariable(Class<?> concreteClass,
// type
resolvedType = ((ParameterizedType) resolvedType).getRawType();
break;
} else if (resolvedType instanceof Class<?>) {
} else if (resolvedType instanceof WildcardType) {
WildcardType wildcardType = ((WildcardType) resolvedType);

if (wildcardType.getLowerBounds().length > 0) {
resolvedType = resolveType(concreteClass, wildcardType.getLowerBounds()[0]);
} else {
resolvedType = resolveType(concreteClass, wildcardType.getUpperBounds()[0]);
}
break;
} else if (resolvedType instanceof Class<?>) {
break;
}
}
Expand All @@ -405,7 +426,15 @@ public static Class<?> resolveTypeVariable(Class<?> concreteClass,
}
} else if (resolvedType instanceof ParameterizedType) {
return (Class<?>) ((ParameterizedType) resolvedType).getRawType();
}
} else if (resolvedType instanceof WildcardType) {
WildcardType wildcardType = ((WildcardType) resolvedType);

if (wildcardType.getLowerBounds().length > 0) {
return resolveType(concreteClass, wildcardType.getLowerBounds()[0]);
} else {
return resolveType(concreteClass, wildcardType.getUpperBounds()[0]);
}
}

throw new IllegalArgumentException("Could not resolve the type variable '" + typeVariable + "' for the concrete class " + concreteClass.getName() + ". The resolved type is unknown: " + resolvedType);
}
Expand Down

0 comments on commit 5d4fd63

Please sign in to comment.