Skip to content

Commit

Permalink
Merge pull request #3380 from harawata/type-param-resolver-cleanup
Browse files Browse the repository at this point in the history
TypeParameterResolver : refactoring, improvements
  • Loading branch information
harawata authored Jan 3, 2025
2 parents 34fd2bd + fde8a23 commit bba03cc
Showing 1 changed file with 77 additions and 46 deletions.
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);
}
}
}

0 comments on commit bba03cc

Please sign in to comment.