added forNestedType(MethodParameter) for resolution of nested parameter types for collection, array, and map parameter types

This commit is contained in:
Keith Donald
2011-01-06 21:59:34 +00:00
parent 61cfb96d95
commit 4c9731d572
6 changed files with 91 additions and 35 deletions

View File

@@ -105,10 +105,26 @@ public class TypeDescriptor {
this.type = field.getType();
this.field = field;
}
/**
* Create a new type descriptor for the given class.
* Use this to instruct the conversion system to convert to an object to a specific target type, when no type location such as a method parameter or field is available to provide additional conversion context.
* Generally prefer use of {@link #forObject(Object)} for constructing source type descriptors for source objects.
* @param type the class
* @return the type descriptor
*/
public static TypeDescriptor valueOf(Class<?> type) {
if (type == null) {
return NULL;
}
TypeDescriptor desc = typeDescriptorCache.get(type);
return (desc != null ? desc : new TypeDescriptor(type));
}
/**
* Create a new type descriptor for object.
* Create a new type descriptor for an object.
* Use this factory method to introspect a source object's type before asking the conversion system to convert it to some another type.
* Builds in population of nested type descriptors for collection and map objects through object introspection.
* If the object is null, returns {@link TypeDescriptor#NULL}.
* If the object is not a collection, simply calls {@link #valueOf(Class)}.
* If the object is a collection, this factory method will derive the element type(s) by introspecting the collection.
@@ -132,6 +148,16 @@ public class TypeDescriptor {
}
}
/**
* Create a new type descriptor for a nested type declared on an array, collection, or map-based method parameter.
* Use this factory method when you've resolved a nested source object such as a collection element or map value and wish to have it converted.
* @param methodParameter the method parameter declaring the collection or map
* @return the nested type descriptor
*/
public static TypeDescriptor forNestedType(MethodParameter methodParameter) {
return new TypeDescriptor(resolveNestedType(methodParameter), methodParameter);
}
/**
* Create a new type descriptor for a nested type declared on an array, collection, or map-based method parameter.
* Use this factory method when you've resolved a nested source object such as a collection element or map value and wish to have it converted.
@@ -142,22 +168,7 @@ public class TypeDescriptor {
public static TypeDescriptor forNestedType(Class<?> nestedType, MethodParameter methodParameter) {
return new TypeDescriptor(nestedType, methodParameter);
}
/**
* Create a new type descriptor for the given class.
* Use this to instruct the conversion system to convert to an object to a specific target type, when no type location such as a method parameter or field is available.
* Generally prefer use of {@link #forObject(Object)} for constructing source type descriptors for source objects.
* @param type the class
* @return the type descriptor
*/
public static TypeDescriptor valueOf(Class<?> type) {
if (type == null) {
return NULL;
}
TypeDescriptor desc = typeDescriptorCache.get(type);
return (desc != null ? desc : new TypeDescriptor(type));
}
/**
* Determine the declared (non-generic) type of the wrapped parameter/field.
* @return the declared type, or <code>null</code> if this is {@link TypeDescriptor#NULL}
@@ -436,6 +447,18 @@ public class TypeDescriptor {
return new TypeDescriptor(nestedType, nested);
}
protected static Class<?> resolveNestedType(MethodParameter methodParameter) {
if (Collection.class.isAssignableFrom(methodParameter.getParameterType())) {
return GenericCollectionTypeResolver.getCollectionParameterType(methodParameter);
} else if (Map.class.isAssignableFrom(methodParameter.getParameterType())) {
return GenericCollectionTypeResolver.getMapValueParameterType(methodParameter);
} else if (methodParameter.getParameterType().isArray()) {
return methodParameter.getParameterType().getComponentType();
} else {
throw new IllegalStateException("Not a collection, map, or array method parameter type " + methodParameter.getParameterType());
}
}
// internal helpers
private TypeDescriptor resolveElementTypeDescriptor() {

View File

@@ -20,9 +20,11 @@ import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.ReflectionUtils;
@@ -51,18 +53,29 @@ public class PropertyTypeDescriptor extends TypeDescriptor {
this.propertyDescriptor = propertyDescriptor;
}
/**
* Create a new type descriptor for a nested type declared on an array, collection, or map-based property.
* Use this factory method when you've resolved a nested source object such as a collection element or map value and wish to have it converted.
* Builds in protection for increasing the nesting level of the provided MethodParameter if the nestedType is itself a collection.
* @param methodParameter the method parameter
* @return the property descriptor
*/
public static PropertyTypeDescriptor forNestedType(MethodParameter methodParameter, PropertyDescriptor propertyDescriptor) {
return forNestedType(resolveNestedType(methodParameter), methodParameter, propertyDescriptor);
}
/**
* Create a new type descriptor for a nested type declared on an array, collection, or map-based property.
* Use this factory method when you've resolved a nested source object such as a collection element or map value and wish to have it converted.
* Builds in protection for increasing the nesting level of the provided MethodParameter if the nestedType is itself a collection.
* @param nestedType the nested type
* @param parentMethodParameter the method parameter
* @param methodParameter the method parameter
* @return the property descriptor
*/
public static PropertyTypeDescriptor forNestedType(Class<?> nestedType, MethodParameter methodParameter, PropertyDescriptor propertyDescriptor) {
return new PropertyTypeDescriptor(nestedType, methodParameter, propertyDescriptor);
}
/**
* Return the underlying PropertyDescriptor.
*/