From eca3e5d0b8b1711e2803da96fb31f7878d7f74ea Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Sat, 17 Apr 2010 04:43:28 +0000 Subject: [PATCH] improved conversion system logging, collection converter simplification/polish, several optimizations, annotation-driven formatting caching git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3255 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../support/FormattingConversionService.java | 76 +++++++++--- .../core/convert/TypeDescriptor.java | 113 +++++++----------- .../support/ArrayToArrayConverter.java | 3 +- .../support/ArrayToCollectionConverter.java | 38 ++---- .../support/ArrayToObjectConverter.java | 3 +- .../support/ArrayToStringConverter.java | 3 +- .../support/CollectionToArrayConverter.java | 38 ++---- .../CollectionToCollectionConverter.java | 34 ++---- .../support/CollectionToObjectConverter.java | 30 ++--- .../support/CollectionToStringConverter.java | 52 ++------ .../support/GenericConversionService.java | 62 ++++++++-- .../convert/support/MapToMapConverter.java | 55 ++------- .../support/ObjectToArrayConverter.java | 24 ++-- .../support/ObjectToCollectionConverter.java | 22 +--- .../support/ObjectToObjectConverter.java | 3 - .../support/ObjectToStringConverter.java | 8 +- .../support/PropertyTypeDescriptor.java | 4 +- .../support/StringToArrayConverter.java | 29 ++--- .../support/StringToCollectionConverter.java | 28 ++--- .../core/convert/TypeDescriptorTests.java | 2 +- .../GenericConversionServiceTests.java | 9 +- .../expression/TypedValue.java | 2 +- .../expression/spel/HelperTests.java | 4 +- 23 files changed, 263 insertions(+), 379 deletions(-) diff --git a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java index 97eed37afb5..1830ef212e2 100644 --- a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java +++ b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java @@ -17,12 +17,14 @@ package org.springframework.format.support; import java.lang.annotation.Annotation; +import java.text.ParseException; import java.util.Collections; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.GenericTypeResolver; -import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; @@ -66,6 +68,9 @@ public class FormattingConversionService extends GenericConversionService implem } Set> fieldTypes = annotationFormatterFactory.getFieldTypes(); + final Map cachedPrinters = new ConcurrentHashMap(); + final Map cachedParsers = new ConcurrentHashMap(); + for (final Class fieldType : fieldTypes) { addConverter(new ConditionalGenericConverter() { public Set getConvertibleTypes() { @@ -75,8 +80,14 @@ public class FormattingConversionService extends GenericConversionService implem return (sourceType.getAnnotation(annotationType) != null); } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { - Printer printer = annotationFormatterFactory.getPrinter(sourceType.getAnnotation(annotationType), sourceType.getType()); - return new PrinterConverter(fieldType, printer, FormattingConversionService.this).convert(source, sourceType, targetType); + FieldFormatterKey key = new FieldFormatterKey(sourceType.getAnnotation(annotationType), fieldType); + GenericConverter converter = cachedPrinters.get(key); + if (converter == null) { + Printer printer = annotationFormatterFactory.getPrinter(key.getAnnotation(), key.getFieldType()); + converter = new PrinterConverter(fieldType, printer, FormattingConversionService.this); + cachedPrinters.put(key, converter); + } + return converter.convert(source, sourceType, targetType); } public String toString() { return "@" + annotationType.getName() + " " + fieldType.getName() + " -> " + @@ -91,8 +102,14 @@ public class FormattingConversionService extends GenericConversionService implem return (targetType.getAnnotation(annotationType) != null); } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { - Parser parser = annotationFormatterFactory.getParser(targetType.getAnnotation(annotationType), targetType.getType()); - return new ParserConverter(fieldType, parser, FormattingConversionService.this).convert(source, sourceType, targetType); + FieldFormatterKey key = new FieldFormatterKey(targetType.getAnnotation(annotationType), fieldType); + GenericConverter converter = cachedParsers.get(key); + if (converter == null) { + Parser printer = annotationFormatterFactory.getParser(key.getAnnotation(), key.getFieldType()); + converter = new ParserConverter(fieldType, printer, FormattingConversionService.this); + cachedParsers.put(key, converter); + } + return converter.convert(source, sourceType, targetType); } public String toString() { return String.class.getName() + " -> @" + annotationType.getName() + " " + @@ -102,6 +119,38 @@ public class FormattingConversionService extends GenericConversionService implem } } + private static final class FieldFormatterKey { + + private final Annotation annotation; + + private final Class fieldType; + + public FieldFormatterKey(Annotation annotation, Class fieldType) { + this.annotation = annotation; + this.fieldType = fieldType; + } + + public Annotation getAnnotation() { + return annotation; + } + + public Class getFieldType() { + return fieldType; + } + + public boolean equals(Object o) { + if (!(o instanceof FieldFormatterKey)) { + return false; + } + FieldFormatterKey key = (FieldFormatterKey) o; + return this.annotation.equals(key.annotation) && this.fieldType.equals(key.fieldType); + } + + public int hashCode() { + return this.annotation.hashCode() + this.fieldType.hashCode(); + } + + } private static class PrinterConverter implements GenericConverter { @@ -142,7 +191,6 @@ public class FormattingConversionService extends GenericConversionService implem } } - private static class ParserConverter implements GenericConverter { private Class fieldType; @@ -166,17 +214,17 @@ public class FormattingConversionService extends GenericConversionService implem if (text == null || text.length() == 0) { return null; } + Object result; try { - Object result = this.parser.parse(text, LocaleContextHolder.getLocale()); - TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass()); - if (!resultType.isAssignableTo(targetType)) { - result = this.conversionService.convert(result, resultType, targetType); - } - return result; + result = this.parser.parse(text, LocaleContextHolder.getLocale()); + } catch (ParseException e) { + throw new IllegalArgumentException("Unable to parse '" + text + "'", e); } - catch (Exception ex) { - throw new ConversionFailedException(sourceType, targetType, source, ex); + TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass()); + if (!resultType.isAssignableTo(targetType)) { + result = this.conversionService.convert(result, resultType, targetType); } + return result; } public String toString() { diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java index e5108a4ea1e..0fb2bda2314 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java @@ -231,7 +231,7 @@ public class TypeDescriptor { * Is this type a {@link Collection} type? */ public boolean isCollection() { - return isTypeAssignableTo(Collection.class); + return Collection.class.isAssignableFrom(getType()); } /** @@ -257,6 +257,15 @@ public class TypeDescriptor { return TypeDescriptor.valueOf(getElementType()); } + /** + * Return the element type as a type descriptor; if the element type is null (cannot be determined), the type descriptor is derived from the element argument. + * @param element the element + * @return the element type descriptor + */ + public TypeDescriptor getElementTypeDescriptor(Object element) { + return getElementType() != null ? getElementTypeDescriptor() : TypeDescriptor.forObject(element); + } + /** * Create a copy of this type descriptor, preserving the context information * but exposing the specified element type (e.g. an array/collection element). @@ -280,7 +289,7 @@ public class TypeDescriptor { * Is this type a {@link Map} type? */ public boolean isMap() { - return isTypeAssignableTo(Map.class); + return Map.class.isAssignableFrom(getType()); } /** @@ -355,6 +364,15 @@ public class TypeDescriptor { return TypeDescriptor.valueOf(getMapKeyType()); } + /** + * Return the map key type as a type descriptor; if the key type is null (cannot be determined), the type descriptor is derived from the key argument. + * @param key the key + * @return the map key type descriptor + */ + public TypeDescriptor getMapKeyTypeDescriptor(Object key) { + return getMapKeyType() != null ? getMapKeyTypeDescriptor() : TypeDescriptor.forObject(key); + } + /** * Returns map value type as a type descriptor. */ @@ -362,6 +380,15 @@ public class TypeDescriptor { return TypeDescriptor.valueOf(getMapValueType()); } + /** + * Return the map value type as a type descriptor; if the value type is null (cannot be determined), the type descriptor is derived from the value argument. + * @param value the value + * @return the map value type descriptor + */ + public TypeDescriptor getMapValueTypeDescriptor(Object value) { + return getMapValueType() != null ? getMapValueTypeDescriptor() : TypeDescriptor.forObject(value); + } + /** * Obtain the annotations associated with the wrapped parameter/field, if any. */ @@ -374,8 +401,6 @@ public class TypeDescriptor { } else if (this.methodParameter != null) { if (this.methodParameter.getParameterIndex() < 0) { - // The best we can do for return type metadata is to expose - // method-level annotations when the target is the return type... return this.methodParameter.getMethodAnnotations(); } else { @@ -400,76 +425,22 @@ public class TypeDescriptor { } /** - * Returns true if an object this type can be assigned to a reference of given targetType. + * 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 */ public boolean isAssignableTo(TypeDescriptor targetType) { - Class targetClass = targetType.getType(); - if (!isTypeAssignableTo(targetClass)) { - return false; + if (this == TypeDescriptor.NULL || targetType == TypeDescriptor.NULL) { + return true; } - if (targetClass != null) { - if (Collection.class.isAssignableFrom(targetClass)) { - Class elementType = targetType.getCollectionElementType(); - if (elementType != null) { - Class sourceElementType = getCollectionElementType(); - if (sourceElementType == null || !elementType.isAssignableFrom(sourceElementType)) { - return false; - } - } - } - else if (Map.class.isAssignableFrom(targetClass)) { - Class keyType = targetType.getMapKeyType(); - if (keyType != null) { - Class sourceKeyType = getMapKeyType(); - if (sourceKeyType == null || !keyType.isAssignableFrom(sourceKeyType)) { - return false; - } - } - Class valueType = targetType.getMapValueType(); - if (valueType != null) { - Class sourceValueType = getMapValueType(); - if (sourceValueType == null || !valueType.isAssignableFrom(sourceValueType)) { - return false; - } - } - } - } - return true; + return targetType.getObjectType().isAssignableFrom(getObjectType()); } /** * A textual representation of the type descriptor (eg. Map) for use in messages */ public String asString() { - StringBuffer stringValue = new StringBuffer(); - if (isArray()) { - // TODO should properly handle multi dimensional arrays - stringValue.append(getArrayComponentType().getName()).append("[]"); - } - else { - Class clazz = getType(); - if (clazz == null) { - return "null"; - } - stringValue.append(clazz.getName()); - if (isCollection()) { - Class collectionType = getCollectionElementType(); - if (collectionType != null) { - stringValue.append("<").append(collectionType.getName()).append(">"); - } - } - else if (isMap()) { - Class keyType = getMapKeyType(); - Class valType = getMapValueType(); - if (keyType != null && valType != null) { - stringValue.append("<").append(keyType.getName()).append(","); - stringValue.append(valType).append(">"); - } - } - } - return stringValue.toString(); + return toString(); } public String toString() { @@ -484,6 +455,14 @@ public class TypeDescriptor { builder.append("@").append(ann.annotationType().getName()).append(' '); } builder.append(ClassUtils.getQualifiedName(getType())); + if (isMap()) { + Class mapKeyType = getMapKeyType(); + Class valueKeyType = getMapValueType(); + builder.append("<").append(mapKeyType != null ? ClassUtils.getQualifiedName(mapKeyType) : "?").append(", ").append(valueKeyType != null ? ClassUtils.getQualifiedName(valueKeyType) : "?").append(">"); + } else if (isCollection()) { + Class elementType = getElementType(); + builder.append("<").append(elementType != null ? ClassUtils.getQualifiedName(elementType) : "?").append(">"); + } builder.append("]"); return builder.toString(); } @@ -521,12 +500,6 @@ public class TypeDescriptor { } } - private boolean isTypeAssignableTo(Class clazz) { - Class type = getType(); - return (type != null && (clazz == null || ClassUtils.isAssignable(clazz, type))); - } - - // static factory methods /** @@ -551,7 +524,7 @@ public class TypeDescriptor { if (object == null) { return NULL; } - else if (object instanceof Collection || object instanceof Map) { + else if (object instanceof Collection || object instanceof Map) { return new TypeDescriptor(object); } else { diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArrayConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArrayConverter.java index d721304e570..70eabb2a6e4 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArrayConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToArrayConverter.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Set; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.GenericConverter; import org.springframework.util.ObjectUtils; @@ -35,7 +36,7 @@ final class ArrayToArrayConverter implements GenericConverter { private final CollectionToArrayConverter helperConverter; - public ArrayToArrayConverter(GenericConversionService conversionService) { + public ArrayToArrayConverter(ConversionService conversionService) { this.helperConverter = new CollectionToArrayConverter(conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java index eaf8a9bf84d..5608a4ed575 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java @@ -22,27 +22,25 @@ import java.util.Collections; import java.util.Set; import org.springframework.core.CollectionFactory; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; /** * Converts an Array to a Collection. * *

First, creates a new Collection of the requested targetType. * Then adds each array element to the target collection. - * Will perform an element conversion from the source component type - * to the collection's parameterized type if necessary. + * Will perform an element conversion from the source component type to the collection's parameterized type if necessary. * * @author Keith Donald * @since 3.0 */ final class ArrayToCollectionConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public ArrayToCollectionConverter(GenericConversionService conversionService) { + public ArrayToCollectionConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -57,30 +55,16 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter { @SuppressWarnings("unchecked") public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } int length = Array.getLength(source); - Collection collection = CollectionFactory.createCollection(targetType.getType(), length); - TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - if (targetElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetElementType)) { - for (int i = 0; i < length; i++) { - collection.add(Array.get(source, i)); - } + Collection target = CollectionFactory.createCollection(targetType.getType(), length); + for (int i = 0; i < length; i++) { + Object sourceElement = Array.get(source, i); + Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(sourceElement)); + target.add(targetElement); } - else { - GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceElementType, targetElementType); - } - for (int i = 0; i < length; i++) { - Object sourceElement = Array.get(source, i); - Object targetElement = ConversionUtils.invokeConverter( - converter, sourceElement, sourceElementType, targetElementType); - collection.add(targetElement); - } - } - return collection; + return target; } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToObjectConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToObjectConverter.java index 6f8bc42c570..404218ef542 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToObjectConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToObjectConverter.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Set; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; import org.springframework.util.ObjectUtils; @@ -35,7 +36,7 @@ final class ArrayToObjectConverter implements ConditionalGenericConverter { private final CollectionToObjectConverter helperConverter; - public ArrayToObjectConverter(GenericConversionService conversionService) { + public ArrayToObjectConverter(ConversionService conversionService) { this.helperConverter = new CollectionToObjectConverter(conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToStringConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToStringConverter.java index cad162e2437..550039dbc61 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToStringConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToStringConverter.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Set; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; import org.springframework.util.ObjectUtils; @@ -35,7 +36,7 @@ final class ArrayToStringConverter implements ConditionalGenericConverter { private final CollectionToStringConverter helperConverter; - public ArrayToStringConverter(GenericConversionService conversionService) { + public ArrayToStringConverter(ConversionService conversionService) { this.helperConverter = new CollectionToStringConverter(conversionService); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToArrayConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToArrayConverter.java index d986f447e3b..e4d70903e39 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToArrayConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToArrayConverter.java @@ -19,13 +19,11 @@ package org.springframework.core.convert.support; import java.lang.reflect.Array; import java.util.Collection; import java.util.Collections; -import java.util.Iterator; import java.util.Set; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; /** * Converts a Collection to an array. @@ -40,9 +38,9 @@ import org.springframework.core.convert.converter.GenericConverter; */ final class CollectionToArrayConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public CollectionToArrayConverter(GenericConversionService conversionService) { + public CollectionToArrayConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -56,32 +54,14 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); - } + return null; + } Collection sourceCollection = (Collection) source; - TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); - if (sourceElementType == TypeDescriptor.NULL) { - sourceElementType = ConversionUtils.getElementType(sourceCollection); - } - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - Object array = Array.newInstance(targetElementType.getType(), sourceCollection.size()); + Object array = Array.newInstance(targetType.getElementType(), sourceCollection.size()); int i = 0; - if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetElementType)) { - for (Iterator it = sourceCollection.iterator(); it.hasNext(); i++) { - Array.set(array, i, it.next()); - } - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceElementType, targetElementType); - } - for (Iterator it = sourceCollection.iterator(); it.hasNext(); i++) { - Object sourceElement = it.next(); - Object targetElement = ConversionUtils.invokeConverter( - converter, sourceElement, sourceElementType, targetElementType); - Array.set(array, i, targetElement); - } + for (Object sourceElement : sourceCollection) { + Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor()); + Array.set(array, i++, targetElement); } return array; } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToCollectionConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToCollectionConverter.java index aa7d599448e..72e1bbf7e68 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToCollectionConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToCollectionConverter.java @@ -21,10 +21,9 @@ import java.util.Collections; import java.util.Set; import org.springframework.core.CollectionFactory; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; /** * Converts from a Collection to another Collection. @@ -39,9 +38,9 @@ import org.springframework.core.convert.converter.GenericConverter; */ final class CollectionToCollectionConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public CollectionToCollectionConverter(GenericConversionService conversionService) { + public CollectionToCollectionConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -56,32 +55,13 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert @SuppressWarnings("unchecked") public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } Collection sourceCollection = (Collection) source; - TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); - if (sourceElementType == TypeDescriptor.NULL) { - sourceElementType = ConversionUtils.getElementType(sourceCollection); - } - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - if (sourceElementType == TypeDescriptor.NULL || targetElementType == TypeDescriptor.NULL - || sourceElementType.isAssignableTo(targetElementType)) { - if (sourceType.isAssignableTo(targetType)) { - return sourceCollection; - } - else { - Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size()); - target.addAll(sourceCollection); - return target; - } - } Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size()); - GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceElementType, targetElementType); - } - for (Object element : sourceCollection) { - target.add(ConversionUtils.invokeConverter(converter, element, sourceElementType, targetElementType)); + for (Object sourceElement : sourceCollection) { + Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor(sourceElement)); + target.add(targetElement); } return target; } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java index 59047089f0d..9f1ac3b3ce2 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java @@ -20,10 +20,9 @@ import java.util.Collection; import java.util.Collections; import java.util.Set; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; /** * Converts a Collection to an Object by returning the first collection element after converting it to the desired targetType. @@ -33,9 +32,9 @@ import org.springframework.core.convert.converter.GenericConverter; */ final class CollectionToObjectConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public CollectionToObjectConverter(GenericConversionService conversionService) { + public CollectionToObjectConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -49,29 +48,14 @@ final class CollectionToObjectConverter implements ConditionalGenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } Collection sourceCollection = (Collection) source; if (sourceCollection.size() == 0) { return null; } - else { - Object firstElement = sourceCollection.iterator().next(); - TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); - if (sourceElementType == TypeDescriptor.NULL && firstElement != null) { - sourceElementType = TypeDescriptor.valueOf(firstElement.getClass()); - } - if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) { - return firstElement; - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType); - if (converter == null) { - throw new ConverterNotFoundException(sourceElementType, targetType); - } - return ConversionUtils.invokeConverter(converter, firstElement, sourceElementType, targetType); - } - } + Object firstElement = sourceCollection.iterator().next(); + return this.conversionService.convert(firstElement, sourceType.getElementTypeDescriptor(firstElement), targetType); } -} +} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToStringConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToStringConverter.java index 252fe8226a5..d0e7025b3fd 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToStringConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToStringConverter.java @@ -20,10 +20,9 @@ import java.util.Collection; import java.util.Collections; import java.util.Set; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; /** * Converts a Collection to a comma-delimited String. @@ -35,9 +34,9 @@ final class CollectionToStringConverter implements ConditionalGenericConverter { private static final String DELIMITER = ","; - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public CollectionToStringConverter(GenericConversionService conversionService) { + public CollectionToStringConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -51,48 +50,23 @@ final class CollectionToStringConverter implements ConditionalGenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } Collection sourceCollection = (Collection) source; if (sourceCollection.size() == 0) { return ""; } - else { - TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); - if (sourceElementType == TypeDescriptor.NULL) { - sourceElementType = ConversionUtils.getElementType(sourceCollection); - } - if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) { - StringBuilder string = new StringBuilder(); - int i = 0; - for (Object element : sourceCollection) { - if (i > 0) { - string.append(DELIMITER); - } - string.append(element); - i++; - } - return string.toString(); - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType); - if (converter == null) { - throw new ConverterNotFoundException(sourceElementType, targetType); - } - StringBuilder string = new StringBuilder(); - int i = 0; - for (Object sourceElement : sourceCollection) { - if (i > 0) { - string.append(DELIMITER); - } - Object targetElement = ConversionUtils.invokeConverter( - converter, sourceElement, sourceElementType, targetType); - string.append(targetElement); - i++; - } - return string.toString(); + StringBuilder string = new StringBuilder(); + int i = 0; + for (Object sourceElement : sourceCollection) { + if (i > 0) { + string.append(DELIMITER); } + Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType); + string.append(targetElement); + i++; } + return string.toString(); } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java index 34003b0913d..516caf13320 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java @@ -30,6 +30,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.GenericTypeResolver; +import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConverterNotFoundException; @@ -39,6 +40,7 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterFactory; import org.springframework.core.convert.converter.ConverterRegistry; import org.springframework.core.convert.converter.GenericConverter; +import org.springframework.core.style.StylerUtils; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -113,29 +115,68 @@ public class GenericConversionService implements ConversionService, ConverterReg public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { assertNotNull(sourceType, targetType); + if (logger.isDebugEnabled()) { + logger.debug("Checking if I can convert " + sourceType + " to " + targetType); + } if (sourceType == TypeDescriptor.NULL || targetType == TypeDescriptor.NULL) { + if (logger.isDebugEnabled()) { + logger.debug("Yes, I can convert"); + } return true; } - return getConverter(sourceType, targetType) != null; + GenericConverter converter = getConverter(sourceType, targetType); + if (converter != null) { + if (logger.isDebugEnabled()) { + logger.debug("Yes, I can convert"); + } + return true; + } else { + if (logger.isDebugEnabled()) { + logger.debug("No, I cannot convert"); + } + return false; + } } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { assertNotNull(sourceType, targetType); if (logger.isDebugEnabled()) { - logger.debug("Converting value of " + sourceType + " to " + targetType); + logger.debug("Converting value " + StylerUtils.style(source) + " of " + sourceType + " to " + targetType); } if (sourceType == TypeDescriptor.NULL) { - Assert.isTrue(source == null, "The source must be null if sourceType == TypeDescriptor.NULL"); - return convertNullSource(sourceType, targetType); + Assert.isTrue(source == null, "The value must be null if sourceType == TypeDescriptor.NULL"); + Object result = convertNullSource(sourceType, targetType); + if (logger.isDebugEnabled()) { + logger.debug("Converted to " + StylerUtils.style(result)); + } + return result; } if (targetType == TypeDescriptor.NULL) { + if (logger.isDebugEnabled()) { + logger.debug("Converted to null"); + } return null; } GenericConverter converter = getConverter(sourceType, targetType); if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetType); + ConverterNotFoundException e = new ConverterNotFoundException(sourceType, targetType); + if (logger.isDebugEnabled()) { + logger.debug(e); + } + throw e; + } + try { + Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType); + if (logger.isDebugEnabled()) { + logger.debug("Converted to " + StylerUtils.style(result)); + } + return result; + } catch (ConversionException e) { + if (logger.isDebugEnabled()) { + logger.debug(e); + } + throw e; } - return ConversionUtils.invokeConverter(converter, source, sourceType, targetType); } public String toString() { @@ -197,7 +238,7 @@ public class GenericConversionService implements ConversionService, ConverterReg /** * Return the default converter if no converter is found for the given sourceType/targetType pair. - * Returns a NO_OP Converter if the sourceType is assignalbe to the targetType. + * Returns a NO_OP Converter if the sourceType is assignable to the targetType. * Returns null otherwise, indicating no suitable converter could be found. * Subclasses may override. * @param sourceType the source type to convert from @@ -366,7 +407,6 @@ public class GenericConversionService implements ConversionService, ConverterReg private GenericConverter matchConverter( MatchableConverters matchable, TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) { - return (matchable != null ? matchable.matchConverter(sourceFieldType, targetFieldType) : null); } @@ -453,19 +493,19 @@ public class GenericConversionService implements ConversionService, ConverterReg for (ConditionalGenericConverter conditional : this.conditionalConverters) { if (conditional.matches(sourceType, targetType)) { if (logger.isDebugEnabled()) { - logger.debug("Conditional converter lookup [MATCHED] " + conditional); + logger.debug("[MATCHED] converter " + conditional); } return conditional; } else { if (logger.isDebugEnabled()) { - logger.debug("Conditional converter lookup [DID NOT MATCH] " + conditional); + logger.debug("[DID NOT MATCH] converter " + conditional); } } } } if (this.defaultConverter != null && logger.isDebugEnabled()) { - logger.debug("Default converter lookup [MATCHED] " + this.defaultConverter); + logger.debug("[MATCHED] converter " + this.defaultConverter); } return this.defaultConverter; } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMapConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMapConverter.java index ca86a1628b6..d258e0ed035 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMapConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMapConverter.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Set; import org.springframework.core.CollectionFactory; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; @@ -37,9 +38,9 @@ import org.springframework.core.convert.converter.ConditionalGenericConverter; */ final class MapToMapConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public MapToMapConverter(GenericConversionService conversionService) { + public MapToMapConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -55,57 +56,19 @@ final class MapToMapConverter implements ConditionalGenericConverter { @SuppressWarnings("unchecked") public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } Map sourceMap = (Map) source; - TypeDescriptor targetKeyType = targetType.getMapKeyTypeDescriptor(); - TypeDescriptor targetValueType = targetType.getMapValueTypeDescriptor(); - if (targetKeyType == TypeDescriptor.NULL && targetValueType == TypeDescriptor.NULL) { - return compatibleMapWithoutEntryConversion(sourceMap, targetType); - } - TypeDescriptor sourceKeyType = sourceType.getMapKeyTypeDescriptor(); - TypeDescriptor sourceValueType = sourceType.getMapValueTypeDescriptor(); - if (sourceKeyType == TypeDescriptor.NULL || sourceValueType == TypeDescriptor.NULL) { - TypeDescriptor[] sourceEntryTypes = ConversionUtils.getMapEntryTypes(sourceMap); - sourceKeyType = sourceEntryTypes[0]; - sourceValueType = sourceEntryTypes[1]; - } - if (sourceKeyType == TypeDescriptor.NULL && sourceValueType == TypeDescriptor.NULL) { - return compatibleMapWithoutEntryConversion(sourceMap, targetType); - } - boolean keysCompatible = false; - if (sourceKeyType != TypeDescriptor.NULL && sourceKeyType.isAssignableTo(targetKeyType)) { - keysCompatible = true; - } - boolean valuesCompatible = false; - if (sourceValueType != TypeDescriptor.NULL && sourceValueType.isAssignableTo(targetValueType)) { - valuesCompatible = true; - } - if (keysCompatible && valuesCompatible) { - return compatibleMapWithoutEntryConversion(sourceMap, targetType); - } Map targetMap = CollectionFactory.createMap(targetType.getType(), sourceMap.size()); - MapEntryConverter converter = new MapEntryConverter(sourceKeyType, sourceValueType, targetKeyType, - targetValueType, keysCompatible, valuesCompatible, this.conversionService); for (Object entry : sourceMap.entrySet()) { Map.Entry sourceMapEntry = (Map.Entry) entry; - Object targetKey = converter.convertKey(sourceMapEntry.getKey()); - Object targetValue = converter.convertValue(sourceMapEntry.getValue()); + Object sourceKey = sourceMapEntry.getKey(); + Object sourceValue = sourceMapEntry.getValue(); + Object targetKey = this.conversionService.convert(sourceKey, sourceType.getMapKeyTypeDescriptor(sourceKey), targetType.getMapKeyTypeDescriptor(sourceKey)); + Object targetValue = this.conversionService.convert(sourceValue, sourceType.getMapValueTypeDescriptor(sourceValue), targetType.getMapValueTypeDescriptor(sourceValue)); targetMap.put(targetKey, targetValue); } return targetMap; } - - @SuppressWarnings("unchecked") - private Map compatibleMapWithoutEntryConversion(Map source, TypeDescriptor targetType) { - if (targetType.getType().isInstance(source)) { - return source; - } - else { - Map target = CollectionFactory.createMap(targetType.getType(), source.size()); - target.putAll(source); - return target; - } - } - + } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java index 1bfcefb5b4b..83428f504cb 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java @@ -20,10 +20,9 @@ import java.lang.reflect.Array; import java.util.Collections; import java.util.Set; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; /** * Converts an Object to a single-element Array containing the Object. @@ -34,9 +33,9 @@ import org.springframework.core.convert.converter.GenericConverter; */ final class ObjectToArrayConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public ObjectToArrayConverter(GenericConversionService conversionService) { + public ObjectToArrayConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -50,20 +49,11 @@ final class ObjectToArrayConverter implements ConditionalGenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); - } - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - Object target = Array.newInstance(targetElementType.getType(), 1); - if (sourceType.isAssignableTo(targetElementType)) { - Array.set(target, 0, source); - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - Array.set(target, 0, ConversionUtils.invokeConverter(converter, source, sourceType, targetElementType)); + return null; } + Object target = Array.newInstance(targetType.getElementType(), 1); + Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor()); + Array.set(target, 0, targetElement); return target; } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java index e3ebdee886b..b08b13b2920 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java @@ -21,10 +21,9 @@ import java.util.Collections; import java.util.Set; import org.springframework.core.CollectionFactory; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; /** * Converts an Object to a single-element Collection containing the Object. @@ -35,9 +34,9 @@ import org.springframework.core.convert.converter.GenericConverter; */ final class ObjectToCollectionConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public ObjectToCollectionConverter(GenericConversionService conversionService) { + public ObjectToCollectionConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -52,20 +51,11 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter { @SuppressWarnings("unchecked") public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } Collection target = CollectionFactory.createCollection(targetType.getType(), 1); - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) { - target.add(source); - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - target.add(ConversionUtils.invokeConverter(converter, source, sourceType, targetElementType)); - } + Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor(source)); + target.add(targetElement); return target; } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java index df540db8e65..3a0bfa150a5 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java @@ -52,9 +52,6 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter { } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { - if (sourceType.isAssignableTo(targetType)) { - return source; - } Class sourceClass = sourceType.getObjectType(); Class targetClass = targetType.getObjectType(); Object target; diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToStringConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToStringConverter.java index 34f34b0f97a..bea9463e0c3 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToStringConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToStringConverter.java @@ -43,10 +43,10 @@ final class ObjectToStringConverter implements ConditionalGenericConverter { public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { Class sourceClass = sourceType.getObjectType(); - return Number.class.isAssignableFrom(sourceClass) || Boolean.class.equals(sourceClass) || - Character.class.equals(sourceClass) || CharSequence.class.isAssignableFrom(sourceClass) || - StringWriter.class.isAssignableFrom(sourceClass) || sourceClass.isEnum() || - ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class); + return String.class.equals(sourceClass) || Number.class.isAssignableFrom(sourceClass) || + Boolean.class.equals(sourceClass) || Character.class.equals(sourceClass) || + CharSequence.class.isAssignableFrom(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) || + sourceClass.isEnum() || ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class); } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java index 66ec1141d6f..69009f096e9 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java @@ -75,10 +75,10 @@ public class PropertyTypeDescriptor extends TypeDescriptor { public Annotation[] getAnnotations() { Annotation[] anns = this.cachedAnnotations; if (anns == null) { - Map annMap = new LinkedHashMap(); + Map, Annotation> annMap = new LinkedHashMap, Annotation>(); String name = this.propertyDescriptor.getName(); if (StringUtils.hasLength(name)) { - Class clazz = getMethodParameter().getMethod().getDeclaringClass(); + Class clazz = getMethodParameter().getMethod().getDeclaringClass(); Field field = ReflectionUtils.findField(clazz, name); if (field == null) { // Same lenient fallback checking as in CachedIntrospectionResults... diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArrayConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArrayConverter.java index 2d05f50e600..53a648ea8c2 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArrayConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArrayConverter.java @@ -20,10 +20,9 @@ import java.lang.reflect.Array; import java.util.Collections; import java.util.Set; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; import org.springframework.util.StringUtils; /** @@ -34,9 +33,9 @@ import org.springframework.util.StringUtils; */ final class StringToArrayConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public StringToArrayConverter(GenericConversionService conversionService) { + public StringToArrayConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -50,25 +49,17 @@ final class StringToArrayConverter implements ConditionalGenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } String string = (String) source; String[] fields = StringUtils.commaDelimitedListToStringArray(string); - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - if (sourceType.isAssignableTo(targetElementType)) { - return fields; - } - else { - Object target = Array.newInstance(targetElementType.getType(), fields.length); - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - for (int i = 0; i < fields.length; i++) { - Array.set(target, i, ConversionUtils.invokeConverter(converter, fields[i], sourceType, targetElementType)); - } - return target; + Object target = Array.newInstance(targetType.getElementType(), fields.length); + for (int i = 0; i < fields.length; i++) { + Object sourceElement = fields[i]; + Object targetElement = this.conversionService.convert(sourceElement, sourceType, targetType.getElementTypeDescriptor()); + Array.set(target, i, targetElement); } + return target; } } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java index 8f74d74b2d2..c501c46369c 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java @@ -21,10 +21,9 @@ import java.util.Collections; import java.util.Set; import org.springframework.core.CollectionFactory; -import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; -import org.springframework.core.convert.converter.GenericConverter; import org.springframework.util.StringUtils; /** @@ -35,9 +34,9 @@ import org.springframework.util.StringUtils; */ final class StringToCollectionConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public StringToCollectionConverter(GenericConversionService conversionService) { + public StringToCollectionConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -52,27 +51,14 @@ final class StringToCollectionConverter implements ConditionalGenericConverter { @SuppressWarnings("unchecked") public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } String string = (String) source; String[] fields = StringUtils.commaDelimitedListToStringArray(string); Collection target = CollectionFactory.createCollection(targetType.getType(), fields.length); - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) { - for (String field : fields) { - target.add(field); - } - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - for (String sourceElement : fields) { - Object targetElement = ConversionUtils.invokeConverter( - converter, sourceElement, sourceType, targetElementType); - target.add(targetElement); - } + for (String sourceElement : fields) { + Object targetElement = this.conversionService.convert(sourceElement, sourceType, targetType.getElementTypeDescriptor(sourceElement)); + target.add(targetElement); } return target; } diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java index 5813b95e23a..97e5262d479 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java @@ -56,7 +56,7 @@ public class TypeDescriptorTests { assertTrue(typeDescriptor.isArray()); assertEquals(Integer.TYPE,typeDescriptor.getElementType()); } - + @Test public void complexTypeDescriptors() throws Exception { TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("arrayOfListOfString")); diff --git a/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java b/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java index 18c27c33550..d4b2d6709f5 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java @@ -39,19 +39,20 @@ public class GenericConversionServiceTests { private GenericConversionService conversionService = new GenericConversionService(); @Test - public void executeConversion() { + public void convert() { conversionService.addConverterFactory(new StringToNumberConverterFactory()); assertEquals(new Integer(3), conversionService.convert("3", Integer.class)); } @Test - public void executeConversionNullSource() { + public void convertNullSource() { assertEquals(null, conversionService.convert(null, Integer.class)); } @Test - public void executeCompatibleSource() { + public void convertAssignableSource() { assertEquals(Boolean.FALSE, conversionService.convert(false, boolean.class)); + assertEquals(Boolean.FALSE, conversionService.convert(false, Boolean.class)); } @Test @@ -189,7 +190,7 @@ public class GenericConversionServiceTests { input.put("key", "value"); Object converted = conversionService.convert(input, TypeDescriptor.forObject(input), new TypeDescriptor(getClass().getField("wildcardMap"))); - assertSame(input, converted); + assertEquals(input, converted); } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/TypedValue.java b/org.springframework.expression/src/main/java/org/springframework/expression/TypedValue.java index f5a1b7bfe11..99ed027a5cd 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/TypedValue.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/TypedValue.java @@ -72,7 +72,7 @@ public class TypedValue { @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append("TypedValue: ").append(this.value).append(" of type ").append(this.getTypeDescriptor().asString()); + str.append("TypedValue: ").append(this.value).append(" of ").append(this.getTypeDescriptor()); return str.toString(); } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/HelperTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/HelperTests.java index 03a0e5b1520..19fb78e0394 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/HelperTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/HelperTests.java @@ -29,12 +29,12 @@ import org.springframework.expression.ParseException; import org.springframework.expression.PropertyAccessor; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.ast.FormatHelper; +import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.expression.spel.support.ReflectionHelper; import org.springframework.expression.spel.support.ReflectivePropertyAccessor; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardTypeConverter; import org.springframework.expression.spel.support.ReflectionHelper.ArgsMatchKind; -import org.springframework.expression.spel.standard.SpelExpression; /** * Tests for any helper code. @@ -94,7 +94,7 @@ public class HelperTests extends ExpressionTestCase { public void testTypedValue() { TypedValue tValue = new TypedValue("hello"); Assert.assertEquals(String.class,tValue.getTypeDescriptor().getType()); - Assert.assertEquals("TypedValue: hello of type java.lang.String",tValue.toString()); + Assert.assertEquals("TypedValue: hello of [TypeDescriptor java.lang.String]",tValue.toString()); } @Test