restored TypeDescriptor getElementType, getMapKeyType, and getMapValueType compatibility; StringToCollection and Array Converters are now conditional and check targetElementType if present; TypeDesciptor#isAssignable no longer bothers with element type and map key/value types in checking assignability for consistency elsewhere; improved javadoc
This commit is contained in:
parent
a1a7c32052
commit
5e3a5202fb
|
|
@ -147,7 +147,7 @@ class TypeConverterDelegate {
|
|||
// Value not of required type?
|
||||
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
|
||||
if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
|
||||
TypeDescriptor elementType = typeDescriptor.getElementType();
|
||||
TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
|
||||
if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) {
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
|
||||
}
|
||||
|
|
@ -465,7 +465,7 @@ class TypeConverterDelegate {
|
|||
return original;
|
||||
}
|
||||
typeDescriptor = typeDescriptor.narrow(original);
|
||||
TypeDescriptor elementType = typeDescriptor.getElementType();
|
||||
TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
|
||||
if (elementType == null && originalAllowed &&
|
||||
!this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
|
||||
return original;
|
||||
|
|
@ -512,7 +512,7 @@ class TypeConverterDelegate {
|
|||
Object element = it.next();
|
||||
String indexedPropertyName = buildIndexedPropertyName(propertyName, i);
|
||||
Object convertedElement = convertIfNecessary(
|
||||
indexedPropertyName, null, element, elementType != null ? elementType.getType() : null , typeDescriptor.getElementType());
|
||||
indexedPropertyName, null, element, elementType != null ? elementType.getType() : null , typeDescriptor.getElementTypeDescriptor());
|
||||
try {
|
||||
convertedCopy.add(convertedElement);
|
||||
}
|
||||
|
|
@ -537,8 +537,8 @@ class TypeConverterDelegate {
|
|||
return original;
|
||||
}
|
||||
typeDescriptor = typeDescriptor.narrow(original);
|
||||
TypeDescriptor keyType = typeDescriptor.getMapKeyType();
|
||||
TypeDescriptor valueType = typeDescriptor.getMapValueType();
|
||||
TypeDescriptor keyType = typeDescriptor.getMapKeyTypeDescriptor();
|
||||
TypeDescriptor valueType = typeDescriptor.getMapValueTypeDescriptor();
|
||||
if (keyType == null && valueType == null && originalAllowed &&
|
||||
!this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
|
||||
return original;
|
||||
|
|
@ -585,8 +585,8 @@ class TypeConverterDelegate {
|
|||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
String keyedPropertyName = buildKeyedPropertyName(propertyName, key);
|
||||
Object convertedKey = convertIfNecessary(keyedPropertyName, null, key, keyType != null ? keyType.getType() : null, typeDescriptor.getMapKeyType());
|
||||
Object convertedValue = convertIfNecessary(keyedPropertyName, null, value, valueType!= null ? valueType.getType() : null, typeDescriptor.getMapValueType());
|
||||
Object convertedKey = convertIfNecessary(keyedPropertyName, null, key, keyType != null ? keyType.getType() : null, typeDescriptor.getMapKeyTypeDescriptor());
|
||||
Object convertedValue = convertIfNecessary(keyedPropertyName, null, value, valueType!= null ? valueType.getType() : null, typeDescriptor.getMapValueTypeDescriptor());
|
||||
try {
|
||||
convertedCopy.put(convertedKey, convertedValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ abstract class AbstractDescriptor {
|
|||
return type;
|
||||
}
|
||||
|
||||
public TypeDescriptor getElementType() {
|
||||
public TypeDescriptor getElementTypeDescriptor() {
|
||||
if (isCollection()) {
|
||||
Class<?> elementType = resolveCollectionElementType();
|
||||
return elementType != null ? new TypeDescriptor(nested(elementType, 0)) : null;
|
||||
|
|
@ -46,7 +46,7 @@ abstract class AbstractDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
public TypeDescriptor getMapKeyType() {
|
||||
public TypeDescriptor getMapKeyTypeDescriptor() {
|
||||
if (isMap()) {
|
||||
Class<?> keyType = resolveMapKeyType();
|
||||
return keyType != null ? new TypeDescriptor(nested(keyType, 0)) : null;
|
||||
|
|
@ -55,7 +55,7 @@ abstract class AbstractDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
public TypeDescriptor getMapValueType() {
|
||||
public TypeDescriptor getMapValueTypeDescriptor() {
|
||||
if (isMap()) {
|
||||
Class<?> valueType = resolveMapValueType();
|
||||
return valueType != null ? new TypeDescriptor(nested(valueType, 1)) : null;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ class FieldDescriptor extends AbstractDescriptor {
|
|||
super(type);
|
||||
this.field = field;
|
||||
this.nestingLevel = nestingLevel;
|
||||
// TODO typeIndex is not preserved at current nestingLevel is not preserved: see SPR-8394
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -60,11 +60,11 @@ public class TypeDescriptor {
|
|||
|
||||
private final Class<?> type;
|
||||
|
||||
private final TypeDescriptor elementType;
|
||||
private final TypeDescriptor elementTypeDescriptor;
|
||||
|
||||
private final TypeDescriptor mapKeyType;
|
||||
private final TypeDescriptor mapKeyTypeDescriptor;
|
||||
|
||||
private final TypeDescriptor mapValueType;
|
||||
private final TypeDescriptor mapValueTypeDescriptor;
|
||||
|
||||
private final Annotation[] annotations;
|
||||
|
||||
|
|
@ -113,14 +113,14 @@ public class TypeDescriptor {
|
|||
* For example, a List<String> could be converted to a List<EmailAddress> by converting to a targetType built with this method.
|
||||
* The method call to construct such a TypeDescriptor would look something like: collection(List.class, TypeDescriptor.valueOf(EmailAddress.class));
|
||||
* @param collectionType the collection type, which must implement {@link Collection}.
|
||||
* @param elementType the collection's element type, used to convert collection elements
|
||||
* @param elementTypeDescriptor a descriptor for the collection's element type, used to convert collection elements
|
||||
* @return the collection type descriptor
|
||||
*/
|
||||
public static TypeDescriptor collection(Class<?> collectionType, TypeDescriptor elementType) {
|
||||
public static TypeDescriptor collection(Class<?> collectionType, TypeDescriptor elementTypeDescriptor) {
|
||||
if (!Collection.class.isAssignableFrom(collectionType)) {
|
||||
throw new IllegalArgumentException("collectionType must be a java.util.Collection");
|
||||
}
|
||||
return new TypeDescriptor(collectionType, elementType);
|
||||
return new TypeDescriptor(collectionType, elementTypeDescriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,15 +129,15 @@ public class TypeDescriptor {
|
|||
* For example, a Map<String, String> could be converted to a Map<Id, EmailAddress> by converting to a targetType built with this method:
|
||||
* The method call to construct such a TypeDescriptor would look something like: map(Map.class, TypeDescriptor.valueOf(Id.class), TypeDescriptor.valueOf(EmailAddress.class));
|
||||
* @param mapType the map type, which must implement {@link Map}.
|
||||
* @param keyType the map's key type, used to convert map keys
|
||||
* @param valueType the map's value type, used to convert map values
|
||||
* @param keyTypeDescriptor a descriptor for the map's key type, used to convert map keys
|
||||
* @param valueTypeDescriptor the map's value type, used to convert map values
|
||||
* @return the map type descriptor
|
||||
*/
|
||||
public static TypeDescriptor map(Class<?> mapType, TypeDescriptor keyType, TypeDescriptor valueType) {
|
||||
public static TypeDescriptor map(Class<?> mapType, TypeDescriptor keyTypeDescriptor, TypeDescriptor valueTypeDescriptor) {
|
||||
if (!Map.class.isAssignableFrom(mapType)) {
|
||||
throw new IllegalArgumentException("mapType must be a java.util.Map");
|
||||
}
|
||||
return new TypeDescriptor(mapType, keyType, valueType);
|
||||
return new TypeDescriptor(mapType, keyTypeDescriptor, valueTypeDescriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,9 +151,13 @@ public class TypeDescriptor {
|
|||
* @param methodParameter the method parameter with a nestingLevel of 1
|
||||
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the method parameter.
|
||||
* @return the nested type descriptor at the specified nesting level, or null if it could not be obtained.
|
||||
* @throws IllegalArgumentException if the nesting level of the input {@link MethodParameter} argument is not 1.
|
||||
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types.
|
||||
*/
|
||||
public static TypeDescriptor nested(MethodParameter methodParameter, int nestingLevel) {
|
||||
if (methodParameter.getNestingLevel() != 1) {
|
||||
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 ParameterDescriptor(methodParameter), nestingLevel);
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +240,7 @@ public class TypeDescriptor {
|
|||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
return new TypeDescriptor(value.getClass(), elementType, mapKeyType, mapValueType, annotations);
|
||||
return new TypeDescriptor(value.getClass(), elementTypeDescriptor, mapKeyTypeDescriptor, mapValueTypeDescriptor, annotations);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -275,24 +279,13 @@ public class TypeDescriptor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if an object of this type can be assigned to a reference of given targetType.
|
||||
* @param targetType the target type
|
||||
* @return true if this type is assignable to the target
|
||||
* Returns true if an object of this type can be assigned to a reference of the given type.
|
||||
* @param typeDescriptor the descriptor for the target type
|
||||
* @return true if this type is assignable to the type represented by the provided type descriptor.
|
||||
* @see #getObjectType()
|
||||
*/
|
||||
public boolean isAssignableTo(TypeDescriptor targetType) {
|
||||
boolean typesAssignable = targetType.getObjectType().isAssignableFrom(getObjectType());
|
||||
if (!typesAssignable) {
|
||||
return false;
|
||||
}
|
||||
if (isArray() && targetType.isArray()) {
|
||||
return getElementType().isAssignableTo(targetType.getElementType());
|
||||
}
|
||||
if (isCollection() && targetType.isCollection()) {
|
||||
return collectionElementsAssignable(targetType.getElementType());
|
||||
} else if (isMap() && targetType.isMap()) {
|
||||
return mapKeysAssignable(targetType.getMapKeyType()) && mapValuesAssignable(targetType.getMapValueType());
|
||||
}
|
||||
return true;
|
||||
public boolean isAssignableTo(TypeDescriptor typeDescriptor) {
|
||||
return typeDescriptor.getObjectType().isAssignableFrom(getObjectType());
|
||||
}
|
||||
|
||||
// indexable type descriptor operations
|
||||
|
|
@ -318,14 +311,14 @@ public class TypeDescriptor {
|
|||
* @return the array component type or Collection element type, or <code>null</code> if this type is a Collection but its element type is not parameterized.
|
||||
* @throws IllegalStateException if this type is not a java.util.Collection or Array type
|
||||
*/
|
||||
public TypeDescriptor getElementType() {
|
||||
public TypeDescriptor getElementTypeDescriptor() {
|
||||
assertCollectionOrArray();
|
||||
return this.elementType;
|
||||
return this.elementTypeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this type is a {@link Collection} or an Array, creates a elementType descriptor from the provided collection or array element.
|
||||
* Narrows the {@link #getElementType() elementType} property to the class of the provided collection or array element.
|
||||
* If this type is a {@link Collection} or an Array, creates a element TypeDescriptor from the provided collection or array element.
|
||||
* Narrows the {@link #getElementTypeDescriptor() elementType} property to the class of the provided collection or array element.
|
||||
* For example, if this describes a java.util.List<java.lang.Number< and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||
* If this describes a java.util.List<?> and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
||||
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
||||
|
|
@ -334,13 +327,8 @@ public class TypeDescriptor {
|
|||
* @throws IllegalStateException if this type is not a java.util.Collection or Array type
|
||||
* @see #narrow(Object)
|
||||
*/
|
||||
public TypeDescriptor elementType(Object element) {
|
||||
assertCollectionOrArray();
|
||||
if (elementType != null) {
|
||||
return elementType.narrow(element);
|
||||
} else {
|
||||
return element != null ? new TypeDescriptor(element.getClass(), null, null, null, annotations) : null;
|
||||
}
|
||||
public TypeDescriptor elementTypeDescriptor(Object element) {
|
||||
return narrow(element, getElementTypeDescriptor());
|
||||
}
|
||||
|
||||
// map type descriptor operations
|
||||
|
|
@ -358,14 +346,14 @@ public class TypeDescriptor {
|
|||
* @return the Map key type, or <code>null</code> if this type is a Map but its key type is not parameterized.
|
||||
* @throws IllegalStateException if this type is not a java.util.Map.
|
||||
*/
|
||||
public TypeDescriptor getMapKeyType() {
|
||||
public TypeDescriptor getMapKeyTypeDescriptor() {
|
||||
assertMap();
|
||||
return this.mapKeyType;
|
||||
return this.mapKeyTypeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this type is a {@link Map}, creates a mapKeyType descriptor from the provided map key.
|
||||
* Narrows the {@link #getMapKeyType() mapKeyType} property to the class of the provided map key.
|
||||
* If this type is a {@link Map}, creates a mapKey {@link TypeDescriptor} from the provided map key.
|
||||
* Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property to the class of the provided map key.
|
||||
* For example, if this describes a java.util.Map<java.lang.Number, java.lang.String< and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||
* If this describes a java.util.Map<?, ?> and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
||||
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
||||
|
|
@ -374,13 +362,8 @@ public class TypeDescriptor {
|
|||
* @throws IllegalStateException if this type is not a java.util.Map.
|
||||
* @see #narrow(Object)
|
||||
*/
|
||||
public TypeDescriptor mapKeyType(Object mapKey) {
|
||||
assertMap();
|
||||
if (mapKeyType != null) {
|
||||
return mapKeyType.narrow(mapKey);
|
||||
} else {
|
||||
return mapKey != null ? new TypeDescriptor(mapKey.getClass(), null, null, null, annotations) : null;
|
||||
}
|
||||
public TypeDescriptor mapKeyTypeDescriptor(Object mapKey) {
|
||||
return narrow(mapKey, getMapKeyTypeDescriptor());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -389,14 +372,14 @@ public class TypeDescriptor {
|
|||
* @return the Map value type, or <code>null</code> if this type is a Map but its value type is not parameterized.
|
||||
* @throws IllegalStateException if this type is not a java.util.Map.
|
||||
*/
|
||||
public TypeDescriptor getMapValueType() {
|
||||
public TypeDescriptor getMapValueTypeDescriptor() {
|
||||
assertMap();
|
||||
return this.mapValueType;
|
||||
return this.mapValueTypeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this type is a {@link Map}, creates a mapValueType descriptor from the provided map value.
|
||||
* Narrows the {@link #getMapValueType() mapValueType} property to the class of the provided map value.
|
||||
* If this type is a {@link Map}, creates a mapValue {@link TypeDescriptor} from the provided map value.
|
||||
* Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property to the class of the provided map value.
|
||||
* For example, if this describes a java.util.Map<java.lang.String, java.lang.Number< and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||
* If this describes a java.util.Map<?, ?> and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
||||
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
||||
|
|
@ -404,13 +387,8 @@ public class TypeDescriptor {
|
|||
* @return the map value type descriptor
|
||||
* @throws IllegalStateException if this type is not a java.util.Map.
|
||||
*/
|
||||
public TypeDescriptor mapValueType(Object mapValue) {
|
||||
assertMap();
|
||||
if (mapValueType != null) {
|
||||
return mapValueType.narrow(mapValue);
|
||||
} else {
|
||||
return mapValue != null ? new TypeDescriptor(mapValue.getClass(), null, null, null, annotations) : null;
|
||||
}
|
||||
public TypeDescriptor mapValueTypeDescriptor(Object mapValue) {
|
||||
return narrow(mapValue, getMapValueTypeDescriptor());
|
||||
}
|
||||
|
||||
// extending Object
|
||||
|
|
@ -423,16 +401,14 @@ public class TypeDescriptor {
|
|||
return false;
|
||||
}
|
||||
TypeDescriptor other = (TypeDescriptor) obj;
|
||||
boolean annotatedTypeEquals = ObjectUtils.nullSafeEquals(getType(), other.getType())
|
||||
&& ObjectUtils.nullSafeEquals(getAnnotations(), other.getAnnotations());
|
||||
boolean annotatedTypeEquals = ObjectUtils.nullSafeEquals(getType(), other.getType()) && ObjectUtils.nullSafeEquals(getAnnotations(), other.getAnnotations());
|
||||
if (!annotatedTypeEquals) {
|
||||
return false;
|
||||
}
|
||||
if (isCollection() || isArray()) {
|
||||
return ObjectUtils.nullSafeEquals(getElementType(), other.getElementType());
|
||||
return ObjectUtils.nullSafeEquals(getElementTypeDescriptor(), other.getElementTypeDescriptor());
|
||||
} else if (isMap()) {
|
||||
return ObjectUtils.nullSafeEquals(getMapKeyType(), other.getMapKeyType())
|
||||
&& ObjectUtils.nullSafeEquals(getMapValueType(), other.getMapValueType());
|
||||
return ObjectUtils.nullSafeEquals(getMapKeyTypeDescriptor(), other.getMapKeyTypeDescriptor()) && ObjectUtils.nullSafeEquals(getMapValueTypeDescriptor(), other.getMapValueTypeDescriptor());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -450,21 +426,53 @@ public class TypeDescriptor {
|
|||
}
|
||||
builder.append(ClassUtils.getQualifiedName(getType()));
|
||||
if (isMap()) {
|
||||
builder.append("<").append(wildcard(getMapKeyType()));
|
||||
builder.append(", ").append(wildcard(getMapValueType())).append(">");
|
||||
builder.append("<").append(wildcard(getMapKeyTypeDescriptor()));
|
||||
builder.append(", ").append(wildcard(getMapValueTypeDescriptor())).append(">");
|
||||
} else if (isCollection()) {
|
||||
builder.append("<").append(wildcard(getElementType())).append(">");
|
||||
builder.append("<").append(wildcard(getElementTypeDescriptor())).append(">");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
// helper public class
|
||||
// deprecations in Spring 3.1
|
||||
|
||||
/**
|
||||
* Returns the value of {@link TypeDescriptor#getType() getType()} for the {@link #getElementTypeDescriptor() elementTypeDescriptor}.
|
||||
* @deprecated in Spring 3.1 in favor of {@link #getElementTypeDescriptor()}.
|
||||
* @throws IllegalStateException if this type is not a java.util.Collection or Array type
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getElementType() {
|
||||
return getElementTypeDescriptor().getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of {@link TypeDescriptor#getType() getType()} for the {@link #getMapKeyTypeDescriptor() mapKeyTypeDescriptor}.
|
||||
* @deprecated in Spring 3.1 in favor of {@link #getMapKeyTypeDescriptor()}.
|
||||
* @throws IllegalStateException if this type is not a java.util.Map.
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getMapKeyType() {
|
||||
return getMapKeyTypeDescriptor().getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of {@link TypeDescriptor#getType() getType()} for the {@link #getMapValueTypeDescriptor() mapValueTypeDescriptor}.
|
||||
* @deprecated in Spring 3.1 in favor of {@link #getMapValueTypeDescriptor()}.
|
||||
* @throws IllegalStateException if this type is not a java.util.Map.
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getMapValueType() {
|
||||
return getMapValueTypeDescriptor().getType();
|
||||
}
|
||||
|
||||
// package private helpers
|
||||
|
||||
TypeDescriptor(AbstractDescriptor descriptor) {
|
||||
this.type = descriptor.getType();
|
||||
this.elementType = descriptor.getElementType();
|
||||
this.mapKeyType = descriptor.getMapKeyType();
|
||||
this.mapValueType = descriptor.getMapValueType();
|
||||
this.elementTypeDescriptor = descriptor.getElementTypeDescriptor();
|
||||
this.mapKeyTypeDescriptor = descriptor.getMapKeyTypeDescriptor();
|
||||
this.mapValueTypeDescriptor = descriptor.getMapValueTypeDescriptor();
|
||||
this.annotations = descriptor.getAnnotations();
|
||||
}
|
||||
|
||||
|
|
@ -478,20 +486,20 @@ public class TypeDescriptor {
|
|||
this(new ClassDescriptor(type));
|
||||
}
|
||||
|
||||
private TypeDescriptor(Class<?> collectionType, TypeDescriptor elementType) {
|
||||
this(collectionType, elementType, null, null, EMPTY_ANNOTATION_ARRAY);
|
||||
private TypeDescriptor(Class<?> collectionType, TypeDescriptor elementTypeDescriptor) {
|
||||
this(collectionType, elementTypeDescriptor, null, null, EMPTY_ANNOTATION_ARRAY);
|
||||
}
|
||||
|
||||
private TypeDescriptor(Class<?> mapType, TypeDescriptor keyType, TypeDescriptor valueType) {
|
||||
this(mapType, null, keyType, valueType, EMPTY_ANNOTATION_ARRAY);
|
||||
private TypeDescriptor(Class<?> mapType, TypeDescriptor keyTypeDescriptor, TypeDescriptor valueTypeDescriptor) {
|
||||
this(mapType, null, keyTypeDescriptor, valueTypeDescriptor, EMPTY_ANNOTATION_ARRAY);
|
||||
}
|
||||
|
||||
private TypeDescriptor(Class<?> type, TypeDescriptor elementType, TypeDescriptor mapKeyType,
|
||||
TypeDescriptor mapValueType, Annotation[] annotations) {
|
||||
private TypeDescriptor(Class<?> type, TypeDescriptor elementTypeDescriptor, TypeDescriptor mapKeyTypeDescriptor,
|
||||
TypeDescriptor mapValueTypeDescriptor, Annotation[] annotations) {
|
||||
this.type = type;
|
||||
this.elementType = elementType;
|
||||
this.mapKeyType = mapKeyType;
|
||||
this.mapValueType = mapValueType;
|
||||
this.elementTypeDescriptor = elementTypeDescriptor;
|
||||
this.mapKeyTypeDescriptor = mapKeyTypeDescriptor;
|
||||
this.mapValueTypeDescriptor = mapValueTypeDescriptor;
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
|
|
@ -507,39 +515,6 @@ public class TypeDescriptor {
|
|||
|
||||
// internal helpers
|
||||
|
||||
private boolean mapKeysAssignable(TypeDescriptor targetKeyType) {
|
||||
TypeDescriptor keyType = getMapKeyType();
|
||||
if (targetKeyType == null) {
|
||||
return true;
|
||||
}
|
||||
if (keyType == null) {
|
||||
return false;
|
||||
}
|
||||
return keyType.isAssignableTo(targetKeyType);
|
||||
}
|
||||
|
||||
private boolean collectionElementsAssignable(TypeDescriptor targetElementType) {
|
||||
TypeDescriptor elementType = getElementType();
|
||||
if (targetElementType == null) {
|
||||
return true;
|
||||
}
|
||||
if (elementType == null) {
|
||||
return false;
|
||||
}
|
||||
return elementType.isAssignableTo(targetElementType);
|
||||
}
|
||||
|
||||
private boolean mapValuesAssignable(TypeDescriptor targetValueType) {
|
||||
TypeDescriptor valueType = getMapValueType();
|
||||
if (targetValueType == null) {
|
||||
return true;
|
||||
}
|
||||
if (valueType == null) {
|
||||
return false;
|
||||
}
|
||||
return valueType.isAssignableTo(targetValueType);
|
||||
}
|
||||
|
||||
private void assertCollectionOrArray() {
|
||||
if (!isCollection() && !isArray()) {
|
||||
throw new IllegalStateException("Not a java.util.Collection or Array");
|
||||
|
|
@ -552,8 +527,16 @@ public class TypeDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
private String wildcard(TypeDescriptor nestedType) {
|
||||
return nestedType != null ? nestedType.toString() : "?";
|
||||
private TypeDescriptor narrow(Object value, TypeDescriptor typeDescriptor) {
|
||||
if (typeDescriptor != null) {
|
||||
return typeDescriptor.narrow(value);
|
||||
} else {
|
||||
return value != null ? new TypeDescriptor(value.getClass(), null, null, null, annotations) : null;
|
||||
}
|
||||
}
|
||||
|
||||
private String wildcard(TypeDescriptor typeDescriptor) {
|
||||
return typeDescriptor != null ? typeDescriptor.toString() : "?";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ final class ArrayToCollectionConverter implements GenericConverter {
|
|||
}
|
||||
int length = Array.getLength(source);
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), length);
|
||||
if (targetType.getElementType() == null) {
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
target.add(sourceElement);
|
||||
|
|
@ -63,7 +63,7 @@ final class ArrayToCollectionConverter implements GenericConverter {
|
|||
} else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementType(sourceElement), targetType.getElementType());
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||
target.add(targetElement);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ final class CollectionToArrayConverter implements GenericConverter {
|
|||
return null;
|
||||
}
|
||||
Collection<?> sourceCollection = (Collection<?>) source;
|
||||
Object array = Array.newInstance(targetType.getElementType().getType(), sourceCollection.size());
|
||||
Object array = Array.newInstance(targetType.getElementTypeDescriptor().getType(), sourceCollection.size());
|
||||
int i = 0;
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementType(sourceElement), targetType.getElementType());
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||
Array.set(array, i++, targetElement);
|
||||
}
|
||||
return array;
|
||||
|
|
|
|||
|
|
@ -55,13 +55,13 @@ final class CollectionToCollectionConverter implements GenericConverter {
|
|||
}
|
||||
Collection<?> sourceCollection = (Collection<?>) source;
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||
if (targetType.getElementType() == null) {
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
for (Object element : sourceCollection) {
|
||||
target.add(element);
|
||||
}
|
||||
} else {
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementType(sourceElement), targetType.getElementType());
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||
target.add(targetElement);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ final class CollectionToObjectConverter implements GenericConverter {
|
|||
return null;
|
||||
}
|
||||
Object firstElement = sourceCollection.iterator().next();
|
||||
return this.conversionService.convert(firstElement, sourceType.elementType(firstElement), targetType);
|
||||
return this.conversionService.convert(firstElement, sourceType.elementTypeDescriptor(firstElement), targetType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ final class CollectionToStringConverter implements GenericConverter {
|
|||
if (i > 0) {
|
||||
sb.append(DELIMITER);
|
||||
}
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementType(sourceElement), targetType);
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementTypeDescriptor(sourceElement), targetType);
|
||||
sb.append(targetElement);
|
||||
i++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ final class MapToMapConverter implements GenericConverter {
|
|||
for (Map.Entry<Object, Object> entry : sourceMap.entrySet()) {
|
||||
Object sourceKey = entry.getKey();
|
||||
Object sourceValue = entry.getValue();
|
||||
Object targetKey = convertKey(sourceKey, sourceType, targetType.getMapKeyType());
|
||||
Object targetValue = convertValue(sourceValue, sourceType, targetType.getMapValueType());
|
||||
Object targetKey = convertKey(sourceKey, sourceType, targetType.getMapKeyTypeDescriptor());
|
||||
Object targetValue = convertValue(sourceValue, sourceType, targetType.getMapValueTypeDescriptor());
|
||||
targetMap.put(targetKey, targetValue);
|
||||
}
|
||||
return targetMap;
|
||||
|
|
@ -71,14 +71,14 @@ final class MapToMapConverter implements GenericConverter {
|
|||
if (targetType == null) {
|
||||
return sourceKey;
|
||||
}
|
||||
return this.conversionService.convert(sourceKey, sourceType.mapKeyType(sourceKey), targetType);
|
||||
return this.conversionService.convert(sourceKey, sourceType.mapKeyTypeDescriptor(sourceKey), targetType);
|
||||
}
|
||||
|
||||
private Object convertValue(Object sourceValue, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType == null) {
|
||||
return sourceValue;
|
||||
}
|
||||
return this.conversionService.convert(sourceValue, sourceType.mapValueType(sourceValue), targetType);
|
||||
return this.conversionService.convert(sourceValue, sourceType.mapValueTypeDescriptor(sourceValue), targetType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -47,8 +47,8 @@ final class ObjectToArrayConverter implements GenericConverter {
|
|||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Object target = Array.newInstance(targetType.getElementType().getType(), 1);
|
||||
Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementType());
|
||||
Object target = Array.newInstance(targetType.getElementTypeDescriptor().getType(), 1);
|
||||
Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor());
|
||||
Array.set(target, 0, targetElement);
|
||||
return target;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ final class ObjectToCollectionConverter implements GenericConverter {
|
|||
return null;
|
||||
}
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), 1);
|
||||
if (targetType.getElementType() == null || targetType.getElementType().isCollection()) {
|
||||
if (targetType.getElementTypeDescriptor() == null || targetType.getElementTypeDescriptor().isCollection()) {
|
||||
target.add(source);
|
||||
} else {
|
||||
Object singleElement = this.conversionService.convert(source, sourceType, targetType.getElementType());
|
||||
Object singleElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor());
|
||||
target.add(singleElement);
|
||||
}
|
||||
return target;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ final class StringToArrayConverter implements ConditionalGenericConverter {
|
|||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.conversionService.canConvert(sourceType, targetType.getElementType());
|
||||
return this.conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor());
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
|
@ -54,10 +54,10 @@ final class StringToArrayConverter implements ConditionalGenericConverter {
|
|||
}
|
||||
String string = (String) source;
|
||||
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
||||
Object target = Array.newInstance(targetType.getElementType().getType(), fields.length);
|
||||
Object target = Array.newInstance(targetType.getElementTypeDescriptor().getType(), fields.length);
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
String sourceElement = fields[i];
|
||||
Object targetElement = this.conversionService.convert(sourceElement.trim(), sourceType, targetType.getElementType());
|
||||
Object targetElement = this.conversionService.convert(sourceElement.trim(), sourceType, targetType.getElementTypeDescriptor());
|
||||
Array.set(target, i, targetElement);
|
||||
}
|
||||
return target;
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ final class StringToCollectionConverter implements ConditionalGenericConverter {
|
|||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType.getElementType() != null) {
|
||||
return this.conversionService.canConvert(sourceType, targetType.getElementType());
|
||||
if (targetType.getElementTypeDescriptor() != null) {
|
||||
return this.conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -61,13 +61,13 @@ final class StringToCollectionConverter implements ConditionalGenericConverter {
|
|||
String string = (String) source;
|
||||
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), fields.length);
|
||||
if (targetType.getElementType() == null) {
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
for (String field : fields) {
|
||||
target.add(field.trim());
|
||||
}
|
||||
} else {
|
||||
for (String field : fields) {
|
||||
Object targetElement = this.conversionService.convert(field.trim(), sourceType, targetType.getElementType());
|
||||
Object targetElement = this.conversionService.convert(field.trim(), sourceType, targetType.getElementTypeDescriptor());
|
||||
target.add(targetElement);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,12 +106,12 @@ public class TypeDescriptorTests {
|
|||
assertEquals(0, desc.getAnnotations().length);
|
||||
assertTrue(desc.isCollection());
|
||||
assertFalse(desc.isArray());
|
||||
assertEquals(List.class, desc.getElementType().getType());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 1), desc.getElementType());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 2), desc.getElementType().getElementType());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 3), desc.getElementType().getElementType().getMapValueType());
|
||||
assertEquals(Integer.class, desc.getElementType().getElementType().getMapKeyType().getType());
|
||||
assertEquals(Enum.class, desc.getElementType().getElementType().getMapValueType().getType());
|
||||
assertEquals(List.class, desc.getElementTypeDescriptor().getType());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 1), desc.getElementTypeDescriptor());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 2), desc.getElementTypeDescriptor().getElementTypeDescriptor());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 3), desc.getElementTypeDescriptor().getElementTypeDescriptor().getMapValueTypeDescriptor());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getElementTypeDescriptor().getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(Enum.class, desc.getElementTypeDescriptor().getElementTypeDescriptor().getMapValueTypeDescriptor().getType());
|
||||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ public class TypeDescriptorTests {
|
|||
assertEquals(0, desc.getAnnotations().length);
|
||||
assertTrue(desc.isCollection());
|
||||
assertFalse(desc.isArray());
|
||||
assertNull(desc.getElementType());
|
||||
assertNull(desc.getElementTypeDescriptor());
|
||||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
|
|
@ -151,8 +151,8 @@ public class TypeDescriptorTests {
|
|||
assertEquals(0, desc.getAnnotations().length);
|
||||
assertFalse(desc.isCollection());
|
||||
assertTrue(desc.isArray());
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementType());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor());
|
||||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
|
|
@ -173,11 +173,11 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isCollection());
|
||||
assertFalse(desc.isArray());
|
||||
assertTrue(desc.isMap());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 1), desc.getMapValueType());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 2), desc.getMapValueType().getElementType());
|
||||
assertEquals(Integer.class, desc.getMapKeyType().getType());
|
||||
assertEquals(List.class, desc.getMapValueType().getType());
|
||||
assertEquals(String.class, desc.getMapValueType().getElementType().getType());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 1), desc.getMapValueTypeDescriptor());
|
||||
assertEquals(TypeDescriptor.nested(methodParameter, 2), desc.getMapValueTypeDescriptor().getElementTypeDescriptor());
|
||||
assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(List.class, desc.getMapValueTypeDescriptor().getType());
|
||||
assertEquals(String.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public void testParameterMap(Map<Integer, List<String>> map) {
|
||||
|
|
@ -206,8 +206,8 @@ public class TypeDescriptorTests {
|
|||
public void propertyComplex() throws Exception {
|
||||
Property property = new Property(getClass(), getClass().getMethod("getComplexProperty", null), getClass().getMethod("setComplexProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(String.class, desc.getMapKeyType().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueType().getElementType().getElementType().getType());
|
||||
assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public Map<String, List<List<Integer>>> getComplexProperty() {
|
||||
|
|
@ -232,7 +232,7 @@ public class TypeDescriptorTests {
|
|||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getListProperty", null), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(List.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
public interface GenericType<T> {
|
||||
|
|
@ -276,7 +276,7 @@ public class TypeDescriptorTests {
|
|||
Property property = new Property(genericBean.getClass(), genericBean.getClass().getMethod("getListProperty", null), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(List.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
assertNotNull(desc.getAnnotation(MethodAnnotation1.class));
|
||||
}
|
||||
|
||||
|
|
@ -308,8 +308,8 @@ public class TypeDescriptorTests {
|
|||
Property property = new Property(getClass(), getClass().getMethod("getProperty", null), getClass().getMethod("setProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(Map.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getMapKeyType().getElementType().getType());
|
||||
assertEquals(Long.class, desc.getMapValueType().getElementType().getType());
|
||||
assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
assertEquals(Long.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
assertNotNull(desc.getAnnotation(MethodAnnotation1.class));
|
||||
assertNotNull(desc.getAnnotation(MethodAnnotation2.class));
|
||||
assertNotNull(desc.getAnnotation(MethodAnnotation3.class));
|
||||
|
|
@ -364,7 +364,7 @@ public class TypeDescriptorTests {
|
|||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("listOfString"));
|
||||
assertFalse(typeDescriptor.isArray());
|
||||
assertEquals(List.class, typeDescriptor.getType());
|
||||
assertEquals(String.class, typeDescriptor.getElementType().getType());
|
||||
assertEquals(String.class, typeDescriptor.getElementTypeDescriptor().getType());
|
||||
assertEquals("java.util.List<java.lang.String>", typeDescriptor.toString());
|
||||
}
|
||||
|
||||
|
|
@ -373,8 +373,8 @@ public class TypeDescriptorTests {
|
|||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("listOfListOfString"));
|
||||
assertFalse(typeDescriptor.isArray());
|
||||
assertEquals(List.class, typeDescriptor.getType());
|
||||
assertEquals(List.class, typeDescriptor.getElementType().getType());
|
||||
assertEquals(String.class, typeDescriptor.getElementType().getElementType().getType());
|
||||
assertEquals(List.class, typeDescriptor.getElementTypeDescriptor().getType());
|
||||
assertEquals(String.class, typeDescriptor.getElementTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
assertEquals("java.util.List<java.util.List<java.lang.String>>", typeDescriptor.toString());
|
||||
}
|
||||
|
||||
|
|
@ -383,8 +383,8 @@ public class TypeDescriptorTests {
|
|||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("listOfListOfUnknown"));
|
||||
assertFalse(typeDescriptor.isArray());
|
||||
assertEquals(List.class, typeDescriptor.getType());
|
||||
assertEquals(List.class, typeDescriptor.getElementType().getType());
|
||||
assertNull(typeDescriptor.getElementType().getElementType());
|
||||
assertEquals(List.class, typeDescriptor.getElementTypeDescriptor().getType());
|
||||
assertNull(typeDescriptor.getElementTypeDescriptor().getElementTypeDescriptor());
|
||||
assertEquals("java.util.List<java.util.List<?>>", typeDescriptor.toString());
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +392,7 @@ public class TypeDescriptorTests {
|
|||
public void fieldArray() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("intArray"));
|
||||
assertTrue(typeDescriptor.isArray());
|
||||
assertEquals(Integer.TYPE,typeDescriptor.getElementType().getType());
|
||||
assertEquals(Integer.TYPE,typeDescriptor.getElementTypeDescriptor().getType());
|
||||
assertEquals("int[]",typeDescriptor.toString());
|
||||
}
|
||||
|
||||
|
|
@ -401,8 +401,8 @@ public class TypeDescriptorTests {
|
|||
public void fieldComplexTypeDescriptor() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("arrayOfListOfString"));
|
||||
assertTrue(typeDescriptor.isArray());
|
||||
assertEquals(List.class,typeDescriptor.getElementType());
|
||||
assertEquals(String.class, typeDescriptor.getElementType().getElementType());
|
||||
assertEquals(List.class,typeDescriptor.getElementTypeDescriptor());
|
||||
assertEquals(String.class, typeDescriptor.getElementTypeDescriptor().getElementTypeDescriptor());
|
||||
assertEquals("java.util.List[]",typeDescriptor.toString());
|
||||
}
|
||||
|
||||
|
|
@ -410,9 +410,9 @@ public class TypeDescriptorTests {
|
|||
public void fieldComplexTypeDescriptor2() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("nestedMapField"));
|
||||
assertTrue(typeDescriptor.isMap());
|
||||
assertEquals(String.class,typeDescriptor.getMapKeyType().getType());
|
||||
assertEquals(List.class, typeDescriptor.getMapValueType().getType());
|
||||
assertEquals(Integer.class, typeDescriptor.getMapValueType().getElementType().getType());
|
||||
assertEquals(String.class,typeDescriptor.getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(List.class, typeDescriptor.getMapValueTypeDescriptor().getType());
|
||||
assertEquals(Integer.class, typeDescriptor.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
assertEquals("java.util.Map<java.lang.String, java.util.List<java.lang.Integer>>", typeDescriptor.toString());
|
||||
}
|
||||
|
||||
|
|
@ -422,8 +422,8 @@ public class TypeDescriptorTests {
|
|||
// TODO: SPR-8394: typeIndex handling not currently supported by fields
|
||||
TypeDescriptor desc = new TypeDescriptor(getClass().getField("fieldMap"));
|
||||
assertTrue(desc.isMap());
|
||||
assertEquals(Integer.class, desc.getMapKeyType().getElementType());
|
||||
assertEquals(Long.class, desc.getMapValueType().getElementType());
|
||||
assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor());
|
||||
assertEquals(Long.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor());
|
||||
}
|
||||
|
||||
public Map<List<Integer>, List<Long>> fieldMap;
|
||||
|
|
@ -472,7 +472,7 @@ public class TypeDescriptorTests {
|
|||
assertTrue(typeDescriptor.isArray());
|
||||
assertFalse(typeDescriptor.isCollection());
|
||||
assertFalse(typeDescriptor.isMap());
|
||||
assertEquals(Integer.TYPE, typeDescriptor.getElementType().getType());
|
||||
assertEquals(Integer.TYPE, typeDescriptor.getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -481,7 +481,7 @@ public class TypeDescriptorTests {
|
|||
assertTrue(typeDescriptor.isCollection());
|
||||
assertFalse(typeDescriptor.isArray());
|
||||
assertFalse(typeDescriptor.isMap());
|
||||
assertNull(typeDescriptor.getElementType());
|
||||
assertNull(typeDescriptor.getElementTypeDescriptor());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -514,6 +514,11 @@ public class TypeDescriptorTests {
|
|||
assertEquals(String.class, t1.getType());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void nestedMethodParameterNot1NestedLevel() throws Exception {
|
||||
TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test4", List.class), 0, 2), 2);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void nestedTooManyLevels() throws Exception {
|
||||
TypeDescriptor t1 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test4", List.class), 0), 3);
|
||||
|
|
@ -597,8 +602,8 @@ public class TypeDescriptorTests {
|
|||
assertEquals(0, desc.getAnnotations().length);
|
||||
assertTrue(desc.isCollection());
|
||||
assertFalse(desc.isArray());
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementType());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor());
|
||||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
|
|
@ -613,8 +618,8 @@ public class TypeDescriptorTests {
|
|||
assertEquals(0, desc.getAnnotations().length);
|
||||
assertTrue(desc.isCollection());
|
||||
assertFalse(desc.isArray());
|
||||
assertEquals(List.class, desc.getElementType().getType());
|
||||
assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementType().getElementType());
|
||||
assertEquals(List.class, desc.getElementTypeDescriptor().getType());
|
||||
assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor().getElementTypeDescriptor());
|
||||
assertFalse(desc.isMap());
|
||||
}
|
||||
|
||||
|
|
@ -630,8 +635,8 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isCollection());
|
||||
assertFalse(desc.isArray());
|
||||
assertTrue(desc.isMap());
|
||||
assertEquals(String.class, desc.getMapKeyType().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueType().getType());
|
||||
assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -647,9 +652,9 @@ public class TypeDescriptorTests {
|
|||
assertFalse(desc.isCollection());
|
||||
assertFalse(desc.isArray());
|
||||
assertTrue(desc.isMap());
|
||||
assertEquals(String.class, desc.getMapKeyType().getType());
|
||||
assertEquals(String.class, desc.getMapValueType().getMapKeyType().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueType().getMapValueType().getType());
|
||||
assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(String.class, desc.getMapValueTypeDescriptor().getMapKeyTypeDescriptor().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getMapValueTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -664,17 +669,17 @@ public class TypeDescriptorTests {
|
|||
public void elementType() {
|
||||
TypeDescriptor desc = TypeDescriptor.valueOf(List.class);
|
||||
Integer value = new Integer(3);
|
||||
desc = desc.elementType(value);
|
||||
desc = desc.elementTypeDescriptor(value);
|
||||
assertEquals(Integer.class, desc.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void elementTypePreserveContext() throws Exception {
|
||||
TypeDescriptor desc = new TypeDescriptor(getClass().getField("listPreserveContext"));
|
||||
assertEquals(Integer.class, desc.getElementType().getElementType().getType());
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
List<Integer> value = new ArrayList<Integer>(3);
|
||||
desc = desc.elementType(value);
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
desc = desc.elementTypeDescriptor(value);
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
|
||||
}
|
||||
|
||||
|
|
@ -685,17 +690,17 @@ public class TypeDescriptorTests {
|
|||
public void mapKeyType() {
|
||||
TypeDescriptor desc = TypeDescriptor.valueOf(Map.class);
|
||||
Integer value = new Integer(3);
|
||||
desc = desc.mapKeyType(value);
|
||||
desc = desc.mapKeyTypeDescriptor(value);
|
||||
assertEquals(Integer.class, desc.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapKeyTypePreserveContext() throws Exception {
|
||||
TypeDescriptor desc = new TypeDescriptor(getClass().getField("mapPreserveContext"));
|
||||
assertEquals(Integer.class, desc.getMapKeyType().getElementType().getType());
|
||||
assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
List<Integer> value = new ArrayList<Integer>(3);
|
||||
desc = desc.mapKeyType(value);
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
desc = desc.mapKeyTypeDescriptor(value);
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
|
||||
}
|
||||
|
||||
|
|
@ -706,17 +711,17 @@ public class TypeDescriptorTests {
|
|||
public void mapValueType() {
|
||||
TypeDescriptor desc = TypeDescriptor.valueOf(Map.class);
|
||||
Integer value = new Integer(3);
|
||||
desc = desc.mapValueType(value);
|
||||
desc = desc.mapValueTypeDescriptor(value);
|
||||
assertEquals(Integer.class, desc.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapValueTypePreserveContext() throws Exception {
|
||||
TypeDescriptor desc = new TypeDescriptor(getClass().getField("mapPreserveContext"));
|
||||
assertEquals(Integer.class, desc.getMapValueType().getElementType().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
List<Integer> value = new ArrayList<Integer>(3);
|
||||
desc = desc.mapValueType(value);
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
desc = desc.mapValueTypeDescriptor(value);
|
||||
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
|
||||
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
|
||||
}
|
||||
|
||||
|
|
@ -744,4 +749,29 @@ public class TypeDescriptorTests {
|
|||
assertEquals(t11, t12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAssignableTypes() {
|
||||
assertTrue(TypeDescriptor.valueOf(Integer.class).isAssignableTo(TypeDescriptor.valueOf(Number.class)));
|
||||
assertFalse(TypeDescriptor.valueOf(Number.class).isAssignableTo(TypeDescriptor.valueOf(Integer.class)));
|
||||
assertFalse(TypeDescriptor.valueOf(String.class).isAssignableTo(TypeDescriptor.valueOf(String[].class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAssignableElementTypes() throws Exception {
|
||||
assertTrue(new TypeDescriptor(getClass().getField("listField")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
|
||||
assertTrue(new TypeDescriptor(getClass().getField("isAssignableElementTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
|
||||
assertTrue(TypeDescriptor.valueOf(List.class).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
|
||||
}
|
||||
|
||||
public List<Number> isAssignableElementTypes;
|
||||
|
||||
@Test
|
||||
public void isAssignableMapKeyValueTypes() throws Exception {
|
||||
assertTrue(new TypeDescriptor(getClass().getField("mapField")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
|
||||
assertTrue(new TypeDescriptor(getClass().getField("isAssignableMapKeyValueTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
|
||||
assertTrue(TypeDescriptor.valueOf(Map.class).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
|
||||
}
|
||||
|
||||
public Map<CharSequence, Number> isAssignableMapKeyValueTypes;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,11 +91,11 @@ public class Indexer extends SpelNodeImpl {
|
|||
// Indexing into a Map
|
||||
if (targetObject instanceof Map) {
|
||||
Object key = index;
|
||||
if (targetObjectTypeDescriptor.getMapKeyType() != null) {
|
||||
key = state.convertValue(key, targetObjectTypeDescriptor.getMapKeyType());
|
||||
if (targetObjectTypeDescriptor.getMapKeyTypeDescriptor() != null) {
|
||||
key = state.convertValue(key, targetObjectTypeDescriptor.getMapKeyTypeDescriptor());
|
||||
}
|
||||
Object value = ((Map<?, ?>) targetObject).get(key);
|
||||
return new TypedValue(value, targetObjectTypeDescriptor.mapValueType(value));
|
||||
return new TypedValue(value, targetObjectTypeDescriptor.mapValueTypeDescriptor(value));
|
||||
}
|
||||
|
||||
if (targetObject == null) {
|
||||
|
|
@ -107,7 +107,7 @@ public class Indexer extends SpelNodeImpl {
|
|||
int idx = (Integer) state.convertValue(index, TypeDescriptor.valueOf(Integer.class));
|
||||
if (targetObject.getClass().isArray()) {
|
||||
Object arrayElement = accessArrayElement(targetObject, idx);
|
||||
return new TypedValue(arrayElement, targetObjectTypeDescriptor.elementType(arrayElement));
|
||||
return new TypedValue(arrayElement, targetObjectTypeDescriptor.elementTypeDescriptor(arrayElement));
|
||||
} else if (targetObject instanceof Collection) {
|
||||
Collection c = (Collection) targetObject;
|
||||
if (idx >= c.size()) {
|
||||
|
|
@ -118,7 +118,7 @@ public class Indexer extends SpelNodeImpl {
|
|||
int pos = 0;
|
||||
for (Object o : c) {
|
||||
if (pos == idx) {
|
||||
return new TypedValue(o, targetObjectTypeDescriptor.elementType(o));
|
||||
return new TypedValue(o, targetObjectTypeDescriptor.elementTypeDescriptor(o));
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
|
@ -187,11 +187,11 @@ public class Indexer extends SpelNodeImpl {
|
|||
if (targetObject instanceof Map) {
|
||||
Map map = (Map) targetObject;
|
||||
Object key = index.getValue();
|
||||
if (targetObjectTypeDescriptor.getMapKeyType() != null) {
|
||||
key = state.convertValue(index, targetObjectTypeDescriptor.getMapKeyType());
|
||||
if (targetObjectTypeDescriptor.getMapKeyTypeDescriptor() != null) {
|
||||
key = state.convertValue(index, targetObjectTypeDescriptor.getMapKeyTypeDescriptor());
|
||||
}
|
||||
if (targetObjectTypeDescriptor.getMapValueType() != null) {
|
||||
newValue = state.convertValue(newValue, targetObjectTypeDescriptor.getMapValueType());
|
||||
if (targetObjectTypeDescriptor.getMapValueTypeDescriptor() != null) {
|
||||
newValue = state.convertValue(newValue, targetObjectTypeDescriptor.getMapValueTypeDescriptor());
|
||||
}
|
||||
map.put(key, newValue);
|
||||
return;
|
||||
|
|
@ -199,7 +199,7 @@ public class Indexer extends SpelNodeImpl {
|
|||
|
||||
if (targetObjectTypeDescriptor.isArray()) {
|
||||
int idx = (Integer)state.convertValue(index, TypeDescriptor.valueOf(Integer.class));
|
||||
setArrayElement(state, contextObject.getValue(), idx, newValue, targetObjectTypeDescriptor.getElementType().getType());
|
||||
setArrayElement(state, contextObject.getValue(), idx, newValue, targetObjectTypeDescriptor.getElementTypeDescriptor().getType());
|
||||
return;
|
||||
}
|
||||
else if (targetObject instanceof Collection) {
|
||||
|
|
@ -212,8 +212,8 @@ public class Indexer extends SpelNodeImpl {
|
|||
}
|
||||
if (targetObject instanceof List) {
|
||||
List list = (List) targetObject;
|
||||
if (targetObjectTypeDescriptor.getElementType() != null) {
|
||||
newValue = state.convertValue(newValue, targetObjectTypeDescriptor.getElementType());
|
||||
if (targetObjectTypeDescriptor.getElementTypeDescriptor() != null) {
|
||||
newValue = state.convertValue(newValue, targetObjectTypeDescriptor.getElementTypeDescriptor());
|
||||
}
|
||||
list.set(idx, newValue);
|
||||
return;
|
||||
|
|
@ -271,10 +271,10 @@ public class Indexer extends SpelNodeImpl {
|
|||
private boolean growCollection(ExpressionState state, TypeDescriptor targetType, int index,
|
||||
Collection collection) {
|
||||
if (state.getConfiguration().isAutoGrowCollections()) {
|
||||
if (targetType.getElementType() == null) {
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.UNABLE_TO_GROW_COLLECTION_UNKNOWN_ELEMENT_TYPE);
|
||||
}
|
||||
TypeDescriptor elementType = targetType.getElementType();
|
||||
TypeDescriptor elementType = targetType.getElementTypeDescriptor();
|
||||
Object newCollectionElement = null;
|
||||
try {
|
||||
int newElements = index - collection.size();
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ public class Selection extends SpelNodeImpl {
|
|||
return new TypedValue(result);
|
||||
}
|
||||
else {
|
||||
Class<?> elementType = ClassUtils.resolvePrimitiveIfNecessary(op.getTypeDescriptor().getElementType().getType());
|
||||
Class<?> elementType = ClassUtils.resolvePrimitiveIfNecessary(op.getTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
Object resultArray = Array.newInstance(elementType, result.size());
|
||||
System.arraycopy(result.toArray(), 0, resultArray, 0, result.size());
|
||||
return new TypedValue(resultArray);
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ public class ReflectionHelper {
|
|||
else {
|
||||
// Now... we have the final argument in the method we are checking as a match and we have 0 or more other
|
||||
// arguments left to pass to it.
|
||||
Class varargsParameterType = expectedArgTypes.get(expectedArgTypes.size() - 1).getElementType().getType();
|
||||
Class varargsParameterType = expectedArgTypes.get(expectedArgTypes.size() - 1).getElementTypeDescriptor().getType();
|
||||
|
||||
// All remaining parameters must be of this type or convertable to this type
|
||||
for (int i = expectedArgTypes.size() - 1; i < suppliedArgTypes.size(); i++) {
|
||||
|
|
|
|||
|
|
@ -74,13 +74,13 @@ public class ExpressionTestsUsingCoreConversionService extends ExpressionTestCas
|
|||
TypeConvertorUsingConversionService tcs = new TypeConvertorUsingConversionService();
|
||||
|
||||
// ArrayList containing List<Integer> to List<String>
|
||||
Class<?> clazz = typeDescriptorForListOfString.getElementType().getType();
|
||||
Class<?> clazz = typeDescriptorForListOfString.getElementTypeDescriptor().getType();
|
||||
assertEquals(String.class,clazz);
|
||||
List l = (List) tcs.convertValue(listOfInteger, TypeDescriptor.forObject(listOfInteger), typeDescriptorForListOfString);
|
||||
assertNotNull(l);
|
||||
|
||||
// ArrayList containing List<String> to List<Integer>
|
||||
clazz = typeDescriptorForListOfInteger.getElementType().getType();
|
||||
clazz = typeDescriptorForListOfInteger.getElementTypeDescriptor().getType();
|
||||
assertEquals(Integer.class,clazz);
|
||||
|
||||
l = (List) tcs.convertValue(listOfString, TypeDescriptor.forObject(listOfString), typeDescriptorForListOfString);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public class SelectionAndProjectionTests {
|
|||
Object value = expression.getValue(context);
|
||||
assertTrue(value.getClass().isArray());
|
||||
TypedValue typedValue = new TypedValue(value);
|
||||
assertEquals(Integer.class, typedValue.getTypeDescriptor().getElementType().getType());
|
||||
assertEquals(Integer.class, typedValue.getTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
Integer[] array = (Integer[]) value;
|
||||
assertEquals(5, array.length);
|
||||
assertEquals(new Integer(0), array[0]);
|
||||
|
|
@ -148,7 +148,7 @@ public class SelectionAndProjectionTests {
|
|||
Object value = expression.getValue(context);
|
||||
assertTrue(value.getClass().isArray());
|
||||
TypedValue typedValue = new TypedValue(value);
|
||||
assertEquals(Integer.class, typedValue.getTypeDescriptor().getElementType().getType());
|
||||
assertEquals(Integer.class, typedValue.getTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
Integer[] array = (Integer[]) value;
|
||||
assertEquals(5, array.length);
|
||||
assertEquals(new Integer(0), array[0]);
|
||||
|
|
@ -250,7 +250,7 @@ public class SelectionAndProjectionTests {
|
|||
Object value = expression.getValue(context);
|
||||
assertTrue(value.getClass().isArray());
|
||||
TypedValue typedValue = new TypedValue(value);
|
||||
assertEquals(Number.class, typedValue.getTypeDescriptor().getElementType().getType());
|
||||
assertEquals(Number.class, typedValue.getTypeDescriptor().getElementTypeDescriptor().getType());
|
||||
Number[] array = (Number[]) value;
|
||||
assertEquals(3, array.length);
|
||||
assertEquals(new Integer(5), array[0]);
|
||||
|
|
|
|||
|
|
@ -729,7 +729,7 @@ public class SpringEL300Tests extends ExpressionTestCase {
|
|||
// value is list containing [true,false]
|
||||
Assert.assertEquals(Boolean.class,value.get(0).getClass());
|
||||
TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx);
|
||||
Assert.assertEquals(null, evaluated.getElementType());
|
||||
Assert.assertEquals(null, evaluated.getElementTypeDescriptor());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -742,7 +742,7 @@ public class SpringEL300Tests extends ExpressionTestCase {
|
|||
// value is array containing [true,false]
|
||||
Assert.assertEquals(Boolean.class,value[0].getClass());
|
||||
TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx);
|
||||
Assert.assertEquals(Boolean.class, evaluated.getElementType().getType());
|
||||
Assert.assertEquals(Boolean.class, evaluated.getElementTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -755,7 +755,7 @@ public class SpringEL300Tests extends ExpressionTestCase {
|
|||
// value is list containing [true,false]
|
||||
Assert.assertEquals(Boolean.class,value.get(0).getClass());
|
||||
TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx);
|
||||
Assert.assertEquals(null, evaluated.getElementType());
|
||||
Assert.assertEquals(null, evaluated.getElementTypeDescriptor());
|
||||
}
|
||||
|
||||
static class C {
|
||||
|
|
|
|||
Loading…
Reference in New Issue