Skip to content

TypeParameterResolver : refactoring, improvements #3380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 3, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 77 additions & 46 deletions src/main/java/org/apache/ibatis/reflection/TypeParameterResolver.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2024 the original author or authors.
* Copyright 2009-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -24,9 +24,11 @@
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.Objects;

/**
* @author Iwao AVE!
* @author Vladimir Sitnikov
*/
public class TypeParameterResolver {

Expand Down Expand Up @@ -79,21 +81,26 @@ public static Type resolveReturnType(Method method, Type srcType) {
public static Type[] resolveParamTypes(Method method, Type srcType) {
Type[] paramTypes = method.getGenericParameterTypes();
Class<?> declaringClass = method.getDeclaringClass();
Type[] result = new Type[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
result[i] = resolveType(paramTypes[i], srcType, declaringClass);
return resolveTypes(paramTypes, srcType, declaringClass);
}

private static Type[] resolveTypes(Type[] types, Type srcType, Class<?> declaringClass) {
Type[] args = new Type[types.length];
for (int i = 0; i < types.length; i++) {
args[i] = resolveType(types[i], srcType, declaringClass);
}
return result;
return args;
}

private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
}
if (type instanceof ParameterizedType) {
} else if (type instanceof ParameterizedType) {
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
} else if (type instanceof GenericArrayType) {
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else if (type instanceof WildcardType) {
return resolveWildcardType((WildcardType) type, srcType, declaringClass);
} else {
return type;
}
Expand All @@ -102,61 +109,28 @@ private static Type resolveType(Type type, Type srcType, Class<?> declaringClass
private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType,
Class<?> declaringClass) {
Type componentType = genericArrayType.getGenericComponentType();
Type resolvedComponentType = null;
if (componentType instanceof TypeVariable) {
resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
} else if (componentType instanceof GenericArrayType) {
resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
} else if (componentType instanceof ParameterizedType) {
resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType, declaringClass);
}
Type resolvedComponentType = resolveType(componentType, srcType, declaringClass);
if (resolvedComponentType instanceof Class) {
return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
} else {
return new GenericArrayTypeImpl(resolvedComponentType);
}
return new GenericArrayTypeImpl(resolvedComponentType);
}

private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType,
Class<?> declaringClass) {
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
Type[] typeArgs = parameterizedType.getActualTypeArguments();
Type[] args = new Type[typeArgs.length];
for (int i = 0; i < typeArgs.length; i++) {
if (typeArgs[i] instanceof TypeVariable) {
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof ParameterizedType) {
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof WildcardType) {
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
args[i] = typeArgs[i];
}
}
Type[] args = resolveTypes(typeArgs, srcType, declaringClass);
return new ParameterizedTypeImpl(rawType, null, args);
}

private static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {
Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);
Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);
Type[] lowerBounds = resolveTypes(wildcardType.getLowerBounds(), srcType, declaringClass);
Type[] upperBounds = resolveTypes(wildcardType.getUpperBounds(), srcType, declaringClass);
return new WildcardTypeImpl(lowerBounds, upperBounds);
}

private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type srcType, Class<?> declaringClass) {
Type[] result = new Type[bounds.length];
for (int i = 0; i < bounds.length; i++) {
if (bounds[i] instanceof TypeVariable) {
result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof ParameterizedType) {
result[i] = resolveParameterizedType((ParameterizedType) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof WildcardType) {
result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
} else {
result[i] = bounds[i];
}
}
return result;
}

private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
Type result;
Class<?> clazz;
Expand Down Expand Up @@ -243,6 +217,7 @@ private static ParameterizedType translateParentTypeVars(ParameterizedType srcTy
}

private TypeParameterResolver() {
super();
}

static class ParameterizedTypeImpl implements ParameterizedType {
Expand All @@ -253,6 +228,7 @@ static class ParameterizedTypeImpl implements ParameterizedType {
private final Type[] actualTypeArguments;

public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) {
super();
this.rawType = rawType;
this.ownerType = ownerType;
this.actualTypeArguments = actualTypeArguments;
Expand All @@ -273,6 +249,21 @@ public Type getRawType() {
return rawType;
}

@Override
public int hashCode() {
return (ownerType == null ? 0 : ownerType.hashCode()) ^ Arrays.hashCode(actualTypeArguments) ^ rawType.hashCode();
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof ParameterizedType)) {
return false;
}
ParameterizedType other = (ParameterizedType) obj;
return rawType.equals(other.getRawType()) && Objects.equals(ownerType, other.getOwnerType())
&& Arrays.equals(actualTypeArguments, other.getActualTypeArguments());
}

@Override
public String toString() {
return "ParameterizedTypeImpl [rawType=" + rawType + ", ownerType=" + ownerType + ", actualTypeArguments="
Expand All @@ -286,6 +277,7 @@ static class WildcardTypeImpl implements WildcardType {
private final Type[] upperBounds;

WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
super();
this.lowerBounds = lowerBounds;
this.upperBounds = upperBounds;
}
Expand All @@ -299,18 +291,57 @@ public Type[] getLowerBounds() {
public Type[] getUpperBounds() {
return upperBounds;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(lowerBounds);
result = prime * result + Arrays.hashCode(upperBounds);
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof WildcardTypeImpl)) {
return false;
}
WildcardTypeImpl other = (WildcardTypeImpl) obj;
return Arrays.equals(lowerBounds, other.lowerBounds) && Arrays.equals(upperBounds, other.upperBounds);
}
}

static class GenericArrayTypeImpl implements GenericArrayType {
private final Type genericComponentType;

GenericArrayTypeImpl(Type genericComponentType) {
super();
this.genericComponentType = genericComponentType;
}

@Override
public Type getGenericComponentType() {
return genericComponentType;
}

@Override
public int hashCode() {
return Objects.hash(genericComponentType);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof GenericArrayTypeImpl)) {
return false;
}
GenericArrayTypeImpl other = (GenericArrayTypeImpl) obj;
return Objects.equals(genericComponentType, other.genericComponentType);
}
}
}
Loading