TypeDescriptor/ResolvableType cache in GenericTypeAwarePropertyDescriptor
Closes gh-31490
This commit is contained in:
@@ -170,6 +170,33 @@ public class TypeDescriptor implements Serializable {
|
||||
return this.resolvableType.getSource();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a type descriptor for a nested type declared within this descriptor.
|
||||
* @param nestingLevel the nesting level of the collection/array element or
|
||||
* map key/value declaration within the property
|
||||
* @return the nested type descriptor at the specified nesting level, or
|
||||
* {@code null} if it could not be obtained
|
||||
* @since 6.1
|
||||
*/
|
||||
@Nullable
|
||||
public TypeDescriptor nested(int nestingLevel) {
|
||||
ResolvableType nested = this.resolvableType;
|
||||
for (int i = 0; i < nestingLevel; i++) {
|
||||
if (Object.class == nested.getType()) {
|
||||
// Could be a collection type but we don't know about its element type,
|
||||
// so let's just assume there is an element type of type Object...
|
||||
}
|
||||
else {
|
||||
nested = nested.getNested(2);
|
||||
}
|
||||
}
|
||||
if (nested == ResolvableType.NONE) {
|
||||
return null;
|
||||
}
|
||||
return getRelatedIfResolvable(nested);
|
||||
}
|
||||
|
||||
/**
|
||||
* Narrows this {@link TypeDescriptor} by setting its type to the class of the
|
||||
* provided value.
|
||||
@@ -335,9 +362,9 @@ public class TypeDescriptor implements Serializable {
|
||||
return new TypeDescriptor(getResolvableType().getComponentType(), null, getAnnotations());
|
||||
}
|
||||
if (Stream.class.isAssignableFrom(getType())) {
|
||||
return getRelatedIfResolvable(this, getResolvableType().as(Stream.class).getGeneric(0));
|
||||
return getRelatedIfResolvable(getResolvableType().as(Stream.class).getGeneric(0));
|
||||
}
|
||||
return getRelatedIfResolvable(this, getResolvableType().asCollection().getGeneric(0));
|
||||
return getRelatedIfResolvable(getResolvableType().asCollection().getGeneric(0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,7 +407,7 @@ public class TypeDescriptor implements Serializable {
|
||||
@Nullable
|
||||
public TypeDescriptor getMapKeyTypeDescriptor() {
|
||||
Assert.state(isMap(), "Not a [java.util.Map]");
|
||||
return getRelatedIfResolvable(this, getResolvableType().asMap().getGeneric(0));
|
||||
return getRelatedIfResolvable(getResolvableType().asMap().getGeneric(0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,7 +444,7 @@ public class TypeDescriptor implements Serializable {
|
||||
@Nullable
|
||||
public TypeDescriptor getMapValueTypeDescriptor() {
|
||||
Assert.state(isMap(), "Not a [java.util.Map]");
|
||||
return getRelatedIfResolvable(this, getResolvableType().asMap().getGeneric(1));
|
||||
return getRelatedIfResolvable(getResolvableType().asMap().getGeneric(1));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,6 +469,14 @@ public class TypeDescriptor implements Serializable {
|
||||
return narrow(mapValue, getMapValueTypeDescriptor());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TypeDescriptor getRelatedIfResolvable(ResolvableType type) {
|
||||
if (type.resolve() == null) {
|
||||
return null;
|
||||
}
|
||||
return new TypeDescriptor(type, null, getAnnotations());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TypeDescriptor narrow(@Nullable Object value, @Nullable TypeDescriptor typeDescriptor) {
|
||||
if (typeDescriptor != null) {
|
||||
@@ -645,7 +680,7 @@ public class TypeDescriptor implements Serializable {
|
||||
throw new IllegalArgumentException("MethodParameter nesting level must be 1: " +
|
||||
"use the nestingLevel parameter to specify the desired nestingLevel for nested type traversal");
|
||||
}
|
||||
return nested(new TypeDescriptor(methodParameter), nestingLevel);
|
||||
return new TypeDescriptor(methodParameter).nested(nestingLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -671,7 +706,7 @@ public class TypeDescriptor implements Serializable {
|
||||
*/
|
||||
@Nullable
|
||||
public static TypeDescriptor nested(Field field, int nestingLevel) {
|
||||
return nested(new TypeDescriptor(field), nestingLevel);
|
||||
return new TypeDescriptor(field).nested(nestingLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -697,33 +732,7 @@ public class TypeDescriptor implements Serializable {
|
||||
*/
|
||||
@Nullable
|
||||
public static TypeDescriptor nested(Property property, int nestingLevel) {
|
||||
return nested(new TypeDescriptor(property), nestingLevel);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TypeDescriptor nested(TypeDescriptor typeDescriptor, int nestingLevel) {
|
||||
ResolvableType nested = typeDescriptor.resolvableType;
|
||||
for (int i = 0; i < nestingLevel; i++) {
|
||||
if (Object.class == nested.getType()) {
|
||||
// Could be a collection type but we don't know about its element type,
|
||||
// so let's just assume there is an element type of type Object...
|
||||
}
|
||||
else {
|
||||
nested = nested.getNested(2);
|
||||
}
|
||||
}
|
||||
if (nested == ResolvableType.NONE) {
|
||||
return null;
|
||||
}
|
||||
return getRelatedIfResolvable(typeDescriptor, nested);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TypeDescriptor getRelatedIfResolvable(TypeDescriptor source, ResolvableType type) {
|
||||
if (type.resolve() == null) {
|
||||
return null;
|
||||
}
|
||||
return new TypeDescriptor(type, null, source.getAnnotations());
|
||||
return new TypeDescriptor(property).nested(nestingLevel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user