Browse Source

Alignment with ResolvableType revision in master

pull/761/head
Juergen Hoeller 11 years ago
parent
commit
6892ad42d6
  1. 217
      spring-core/src/main/java/org/springframework/core/ResolvableType.java

217
spring-core/src/main/java/org/springframework/core/ResolvableType.java

@ -123,27 +123,27 @@ public final class ResolvableType implements Serializable {
/** /**
* Private constructor used to create a new {@link ResolvableType} for resolution purposes. * Private constructor used to create a new {@link ResolvableType} for cache key purposes.
*/ */
private ResolvableType( private ResolvableType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) {
Type type, TypeProvider typeProvider, VariableResolver variableResolver, ResolvableType componentType) {
this.type = type; this.type = type;
this.typeProvider = typeProvider; this.typeProvider = typeProvider;
this.variableResolver = variableResolver; this.variableResolver = variableResolver;
this.componentType = componentType; this.componentType = null;
this.resolved = resolveClass(); this.resolved = null;
} }
/** /**
* Private constructor used to create a new {@link ResolvableType} for cache key purposes. * Private constructor used to create a new {@link ResolvableType} for resolution purposes.
*/ */
private ResolvableType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) { private ResolvableType(
Type type, TypeProvider typeProvider, VariableResolver variableResolver, ResolvableType componentType) {
this.type = type; this.type = type;
this.typeProvider = typeProvider; this.typeProvider = typeProvider;
this.variableResolver = variableResolver; this.variableResolver = variableResolver;
this.componentType = null; this.componentType = componentType;
this.resolved = null; this.resolved = resolveClass();
} }
@ -598,7 +598,7 @@ public final class ResolvableType implements Serializable {
return EMPTY_TYPES_ARRAY; return EMPTY_TYPES_ARRAY;
} }
if (this.generics == null) { if (this.generics == null) {
if (this.type instanceof Class<?>) { if (this.type instanceof Class) {
Class<?> typeClass = (Class<?>) this.type; Class<?> typeClass = (Class<?>) this.type;
this.generics = forTypes(SerializableTypeWrapper.forTypeParameters(typeClass), this.variableResolver); this.generics = forTypes(SerializableTypeWrapper.forTypeParameters(typeClass), this.variableResolver);
} }
@ -691,7 +691,7 @@ public final class ResolvableType implements Serializable {
} }
private Class<?> resolveClass() { private Class<?> resolveClass() {
if (this.type instanceof Class<?> || this.type == null) { if (this.type instanceof Class || this.type == null) {
return (Class<?>) this.type; return (Class<?>) this.type;
} }
if (this.type instanceof GenericArrayType) { if (this.type instanceof GenericArrayType) {
@ -762,48 +762,20 @@ public final class ResolvableType implements Serializable {
return null; return null;
} }
/**
* Return a String representation of this type in its fully resolved form
* (including any generic parameters).
*/
@Override
public String toString() {
if (isArray()) {
return getComponentType() + "[]";
}
if (this.resolved == null) {
return "?";
}
if (this.type instanceof TypeVariable) {
TypeVariable<?> variable = (TypeVariable<?>) this.type;
if (this.variableResolver == null || this.variableResolver.resolveVariable(variable) == null) {
// Don't bother with variable boundaries for toString()...
// Can cause infinite recursions in case of self-references
return "?";
}
}
StringBuilder result = new StringBuilder(this.resolved.getName());
if (hasGenerics()) {
result.append('<');
result.append(StringUtils.arrayToDelimitedString(getGenerics(), ", "));
result.append('>');
}
return result.toString();
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object other) {
if (this == obj) { if (this == other) {
return true; return true;
} }
if (!(obj instanceof ResolvableType)) { if (!(other instanceof ResolvableType)) {
return false; return false;
} }
ResolvableType other = (ResolvableType) obj; ResolvableType otherType = (ResolvableType) other;
return (ObjectUtils.nullSafeEquals(this.type, other.type) && return (ObjectUtils.nullSafeEquals(this.type, otherType.type) &&
ObjectUtils.nullSafeEquals(getSource(), other.getSource()) && ObjectUtils.nullSafeEquals(getSource(), otherType.getSource()) &&
variableResolverSourceEquals(other.variableResolver) && variableResolverSourceEquals(otherType.variableResolver) &&
ObjectUtils.nullSafeEquals(this.componentType, other.componentType)); ObjectUtils.nullSafeEquals(this.componentType, otherType.componentType));
} }
@Override @Override
@ -815,23 +787,6 @@ public final class ResolvableType implements Serializable {
return hashCode; return hashCode;
} }
/**
* Custom serialization support for {@link #NONE}.
*/
private Object readResolve() throws ObjectStreamException {
return (this.type == null ? NONE : this);
}
/**
* Adapts this {@link ResolvableType} to a {@link VariableResolver}.
*/
VariableResolver asVariableResolver() {
if (this == NONE) {
return null;
}
return new DefaultVariableResolver();
}
private boolean variableResolverSourceEquals(VariableResolver other) { private boolean variableResolverSourceEquals(VariableResolver other) {
if (this.variableResolver == null) { if (this.variableResolver == null) {
return (other == null); return (other == null);
@ -850,17 +805,59 @@ public final class ResolvableType implements Serializable {
return hashCode; return hashCode;
} }
private static ResolvableType[] forTypes(Type[] types, VariableResolver owner) { /**
ResolvableType[] result = new ResolvableType[types.length]; * Adapts this {@link ResolvableType} to a {@link VariableResolver}.
for (int i = 0; i < types.length; i++) { */
result[i] = forType(types[i], owner); VariableResolver asVariableResolver() {
if (this == NONE) {
return null;
} }
return result; return new DefaultVariableResolver();
}
/**
* Custom serialization support for {@link #NONE}.
*/
private Object readResolve() throws ObjectStreamException {
return (this.type == null ? NONE : this);
} }
/** /**
* Return a {@link ResolvableType} for the specified {@link Class}. For example * Return a String representation of this type in its fully resolved form
* {@code ResolvableType.forClass(MyArrayList.class)}. * (including any generic parameters).
*/
@Override
public String toString() {
if (isArray()) {
return getComponentType() + "[]";
}
if (this.resolved == null) {
return "?";
}
if (this.type instanceof TypeVariable) {
TypeVariable<?> variable = (TypeVariable<?>) this.type;
if (this.variableResolver == null || this.variableResolver.resolveVariable(variable) == null) {
// Don't bother with variable boundaries for toString()...
// Can cause infinite recursions in case of self-references
return "?";
}
}
StringBuilder result = new StringBuilder(this.resolved.getName());
if (hasGenerics()) {
result.append('<');
result.append(StringUtils.arrayToDelimitedString(getGenerics(), ", "));
result.append('>');
}
return result.toString();
}
// Factory methods
/**
* Return a {@link ResolvableType} for the specified {@link Class},
* using the full generic type information for assignability checks.
* For example: {@code ResolvableType.forClass(MyArrayList.class)}.
* @param sourceClass the source class (must not be {@code null} * @param sourceClass the source class (must not be {@code null}
* @return a {@link ResolvableType} for the specified class * @return a {@link ResolvableType} for the specified class
* @see #forClass(Class, Class) * @see #forClass(Class, Class)
@ -872,9 +869,9 @@ public final class ResolvableType implements Serializable {
} }
/** /**
* Return a {@link ResolvableType} for the specified {@link Class} with a given * Return a {@link ResolvableType} for the specified {@link Class}
* implementation. For example * with a given implementation.
* {@code ResolvableType.forClass(List.class, MyArrayList.class)}. * For example: {@code ResolvableType.forClass(List.class, MyArrayList.class)}.
* @param sourceClass the source class (must not be {@code null} * @param sourceClass the source class (must not be {@code null}
* @param implementationClass the implementation class * @param implementationClass the implementation class
* @return a {@link ResolvableType} for the specified class backed by the given * @return a {@link ResolvableType} for the specified class backed by the given
@ -888,6 +885,38 @@ public final class ResolvableType implements Serializable {
return (asType == NONE ? forType(sourceClass) : asType); return (asType == NONE ? forType(sourceClass) : asType);
} }
/**
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
* @param sourceClass the source class
* @param generics the generics of the class
* @return a {@link ResolvableType} for the specific class and generics
* @see #forClassWithGenerics(Class, ResolvableType...)
*/
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, Class<?>... generics) {
Assert.notNull(sourceClass, "Source class must not be null");
Assert.notNull(generics, "Generics must not be null");
ResolvableType[] resolvableGenerics = new ResolvableType[generics.length];
for (int i = 0; i < generics.length; i++) {
resolvableGenerics[i] = forClass(generics[i]);
}
return forClassWithGenerics(sourceClass, resolvableGenerics);
}
/**
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
* @param sourceClass the source class
* @param generics the generics of the class
* @return a {@link ResolvableType} for the specific class and generics
* @see #forClassWithGenerics(Class, Class...)
*/
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, ResolvableType... generics) {
Assert.notNull(sourceClass, "Source class must not be null");
Assert.notNull(generics, "Generics must not be null");
TypeVariable<?>[] variables = sourceClass.getTypeParameters();
Assert.isTrue(variables.length == generics.length, "Mismatched number of generics specified");
return forType(sourceClass, new TypeVariablesVariableResolver(variables, generics));
}
/** /**
* Return a {@link ResolvableType} for the specified {@link Field}. * Return a {@link ResolvableType} for the specified {@link Field}.
* @param field the source field * @param field the source field
@ -1102,41 +1131,17 @@ public final class ResolvableType implements Serializable {
* @return a {@link ResolvableType} as an array of the specified component type * @return a {@link ResolvableType} as an array of the specified component type
*/ */
public static ResolvableType forArrayComponent(ResolvableType componentType) { public static ResolvableType forArrayComponent(ResolvableType componentType) {
Assert.notNull(componentType, "ComponentType must not be null"); Assert.notNull(componentType, "componentType must not be null");
Class<?> arrayClass = Array.newInstance(componentType.resolve(), 0).getClass(); Class<?> arrayClass = Array.newInstance(componentType.resolve(), 0).getClass();
return new ResolvableType(arrayClass, null, null, componentType); return new ResolvableType(arrayClass, null, null, componentType);
} }
/** private static ResolvableType[] forTypes(Type[] types, VariableResolver owner) {
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics. ResolvableType[] result = new ResolvableType[types.length];
* @param sourceClass the source class for (int i = 0; i < types.length; i++) {
* @param generics the generics of the class result[i] = forType(types[i], owner);
* @return a {@link ResolvableType} for the specific class and generics
* @see #forClassWithGenerics(Class, ResolvableType...)
*/
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, Class<?>... generics) {
Assert.notNull(sourceClass, "Source class must not be null");
Assert.notNull(generics, "Generics must not be null");
ResolvableType[] resolvableGenerics = new ResolvableType[generics.length];
for (int i = 0; i < generics.length; i++) {
resolvableGenerics[i] = forClass(generics[i]);
} }
return forClassWithGenerics(sourceClass, resolvableGenerics); return result;
}
/**
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
* @param sourceClass the source class
* @param generics the generics of the class
* @return a {@link ResolvableType} for the specific class and generics
* @see #forClassWithGenerics(Class, Class...)
*/
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, ResolvableType... generics) {
Assert.notNull(sourceClass, "Source class must not be null");
Assert.notNull(generics, "Generics must not be null");
TypeVariable<?>[] variables = sourceClass.getTypeParameters();
Assert.isTrue(variables.length == generics.length, "Mismatched number of generics specified");
return forType(sourceClass, new TypeVariablesVariableResolver(variables, generics));
} }
/** /**
@ -1198,7 +1203,7 @@ public final class ResolvableType implements Serializable {
// For simple Class references, build the wrapper right away - // For simple Class references, build the wrapper right away -
// no expensive resolution necessary, so not worth caching... // no expensive resolution necessary, so not worth caching...
if (type instanceof Class<?>) { if (type instanceof Class) {
return new ResolvableType(type, typeProvider, variableResolver, null); return new ResolvableType(type, typeProvider, variableResolver, null);
} }

Loading…
Cancel
Save