Skip to content

Commit

Permalink
project review to keep compatibiliy with spring-boot-1
Browse files Browse the repository at this point in the history
  • Loading branch information
bnasslahsen committed Apr 5, 2020
1 parent 4860655 commit 43d943f
Showing 1 changed file with 85 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,99 @@

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

public interface ReturnTypeParser {

default Type getReturnType(MethodParameter methodParameter) {
if (methodParameter.getGenericParameterType() instanceof ParameterizedType)
return GenericTypeResolver.resolveType(methodParameter.getGenericParameterType(),methodParameter.getContainingClass());
return ReturnTypeParser.resolveType(methodParameter.getGenericParameterType(), methodParameter.getContainingClass());
return methodParameter.getParameterType();
}

/**
* This is a copy of GenericTypeResolver.resolveType which is not available on spring 4.
* This also keeps compatibility with spring-boot 1 applications.
* Resolve the given generic type against the given context class,
* substituting type variables as far as possible.
* @param genericType the (potentially) generic type
* @param contextClass a context class for the target type, for example a class
* in which the target type appears in a method signature (can be {@code null})
* @return the resolved type (possibly the given generic type as-is)
* @since 5.0
*/
static Type resolveType(Type genericType, @Nullable Class<?> contextClass) {
if (contextClass != null) {
if (genericType instanceof TypeVariable) {
ResolvableType resolvedTypeVariable = resolveVariable(
(TypeVariable<?>) genericType, ResolvableType.forClass(contextClass));
if (resolvedTypeVariable != ResolvableType.NONE) {
Class<?> resolved = resolvedTypeVariable.resolve();
if (resolved != null) {
return resolved;
}
}
}
else if (genericType instanceof ParameterizedType) {
ResolvableType resolvedType = ResolvableType.forType(genericType);
if (resolvedType.hasUnresolvableGenerics()) {
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Class<?>[] generics = new Class<?>[parameterizedType.getActualTypeArguments().length];
Type[] typeArguments = parameterizedType.getActualTypeArguments();
ResolvableType contextType = ResolvableType.forClass(contextClass);
for (int i = 0; i < typeArguments.length; i++) {
Type typeArgument = typeArguments[i];
if (typeArgument instanceof TypeVariable) {
ResolvableType resolvedTypeArgument = resolveVariable(
(TypeVariable<?>) typeArgument, contextType);
if (resolvedTypeArgument != ResolvableType.NONE) {
generics[i] = resolvedTypeArgument.resolve();
}
else {
generics[i] = ResolvableType.forType(typeArgument).resolve();
}
}
else {
generics[i] = ResolvableType.forType(typeArgument).resolve();
}
}
Class<?> rawClass = resolvedType.getRawClass();
if (rawClass != null) {
return ResolvableType.forClassWithGenerics(rawClass, generics).getType();
}
}
}
}
return genericType;
}

static ResolvableType resolveVariable(TypeVariable<?> typeVariable, ResolvableType contextType) {
ResolvableType resolvedType;
if (contextType.hasGenerics()) {
resolvedType = ResolvableType.forType(typeVariable, contextType);
if (resolvedType.resolve() != null) {
return resolvedType;
}
}

ResolvableType superType = contextType.getSuperType();
if (superType != ResolvableType.NONE) {
resolvedType = resolveVariable(typeVariable, superType);
if (resolvedType.resolve() != null) {
return resolvedType;
}
}
for (ResolvableType ifc : contextType.getInterfaces()) {
resolvedType = resolveVariable(typeVariable, ifc);
if (resolvedType.resolve() != null) {
return resolvedType;
}
}
return ResolvableType.NONE;
}
}

0 comments on commit 43d943f

Please sign in to comment.