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
This commit is contained in:
parent
efc8a513d1
commit
eca3e5d0b8
|
|
@ -17,12 +17,14 @@
|
||||||
package org.springframework.format.support;
|
package org.springframework.format.support;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
|
|
@ -66,6 +68,9 @@ public class FormattingConversionService extends GenericConversionService implem
|
||||||
}
|
}
|
||||||
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
|
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
|
||||||
|
|
||||||
|
final Map<FieldFormatterKey, GenericConverter> cachedPrinters = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||||
|
final Map<FieldFormatterKey, GenericConverter> cachedParsers = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||||
|
|
||||||
for (final Class<?> fieldType : fieldTypes) {
|
for (final Class<?> fieldType : fieldTypes) {
|
||||||
addConverter(new ConditionalGenericConverter() {
|
addConverter(new ConditionalGenericConverter() {
|
||||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||||
|
|
@ -75,8 +80,14 @@ public class FormattingConversionService extends GenericConversionService implem
|
||||||
return (sourceType.getAnnotation(annotationType) != null);
|
return (sourceType.getAnnotation(annotationType) != null);
|
||||||
}
|
}
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
Printer<?> printer = annotationFormatterFactory.getPrinter(sourceType.getAnnotation(annotationType), sourceType.getType());
|
FieldFormatterKey key = new FieldFormatterKey(sourceType.getAnnotation(annotationType), fieldType);
|
||||||
return new PrinterConverter(fieldType, printer, FormattingConversionService.this).convert(source, sourceType, targetType);
|
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() {
|
public String toString() {
|
||||||
return "@" + annotationType.getName() + " " + fieldType.getName() + " -> " +
|
return "@" + annotationType.getName() + " " + fieldType.getName() + " -> " +
|
||||||
|
|
@ -91,8 +102,14 @@ public class FormattingConversionService extends GenericConversionService implem
|
||||||
return (targetType.getAnnotation(annotationType) != null);
|
return (targetType.getAnnotation(annotationType) != null);
|
||||||
}
|
}
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
Parser<?> parser = annotationFormatterFactory.getParser(targetType.getAnnotation(annotationType), targetType.getType());
|
FieldFormatterKey key = new FieldFormatterKey(targetType.getAnnotation(annotationType), fieldType);
|
||||||
return new ParserConverter(fieldType, parser, FormattingConversionService.this).convert(source, sourceType, targetType);
|
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() {
|
public String toString() {
|
||||||
return String.class.getName() + " -> @" + annotationType.getName() + " " +
|
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 {
|
private static class PrinterConverter implements GenericConverter {
|
||||||
|
|
||||||
|
|
@ -142,7 +191,6 @@ public class FormattingConversionService extends GenericConversionService implem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class ParserConverter implements GenericConverter {
|
private static class ParserConverter implements GenericConverter {
|
||||||
|
|
||||||
private Class<?> fieldType;
|
private Class<?> fieldType;
|
||||||
|
|
@ -166,17 +214,17 @@ public class FormattingConversionService extends GenericConversionService implem
|
||||||
if (text == null || text.length() == 0) {
|
if (text == null || text.length() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Object result;
|
||||||
try {
|
try {
|
||||||
Object result = this.parser.parse(text, LocaleContextHolder.getLocale());
|
result = this.parser.parse(text, LocaleContextHolder.getLocale());
|
||||||
TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass());
|
} catch (ParseException e) {
|
||||||
if (!resultType.isAssignableTo(targetType)) {
|
throw new IllegalArgumentException("Unable to parse '" + text + "'", e);
|
||||||
result = this.conversionService.convert(result, resultType, targetType);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass());
|
||||||
throw new ConversionFailedException(sourceType, targetType, source, ex);
|
if (!resultType.isAssignableTo(targetType)) {
|
||||||
|
result = this.conversionService.convert(result, resultType, targetType);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ public class TypeDescriptor {
|
||||||
* Is this type a {@link Collection} type?
|
* Is this type a {@link Collection} type?
|
||||||
*/
|
*/
|
||||||
public boolean isCollection() {
|
public boolean isCollection() {
|
||||||
return isTypeAssignableTo(Collection.class);
|
return Collection.class.isAssignableFrom(getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -257,6 +257,15 @@ public class TypeDescriptor {
|
||||||
return TypeDescriptor.valueOf(getElementType());
|
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
|
* Create a copy of this type descriptor, preserving the context information
|
||||||
* but exposing the specified element type (e.g. an array/collection element).
|
* 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?
|
* Is this type a {@link Map} type?
|
||||||
*/
|
*/
|
||||||
public boolean isMap() {
|
public boolean isMap() {
|
||||||
return isTypeAssignableTo(Map.class);
|
return Map.class.isAssignableFrom(getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -355,6 +364,15 @@ public class TypeDescriptor {
|
||||||
return TypeDescriptor.valueOf(getMapKeyType());
|
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.
|
* Returns map value type as a type descriptor.
|
||||||
*/
|
*/
|
||||||
|
|
@ -362,6 +380,15 @@ public class TypeDescriptor {
|
||||||
return TypeDescriptor.valueOf(getMapValueType());
|
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.
|
* Obtain the annotations associated with the wrapped parameter/field, if any.
|
||||||
*/
|
*/
|
||||||
|
|
@ -374,8 +401,6 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
else if (this.methodParameter != null) {
|
else if (this.methodParameter != null) {
|
||||||
if (this.methodParameter.getParameterIndex() < 0) {
|
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();
|
return this.methodParameter.getMethodAnnotations();
|
||||||
}
|
}
|
||||||
else {
|
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
|
* @param targetType the target type
|
||||||
* @return true if this type is assignable to the target
|
* @return true if this type is assignable to the target
|
||||||
*/
|
*/
|
||||||
public boolean isAssignableTo(TypeDescriptor targetType) {
|
public boolean isAssignableTo(TypeDescriptor targetType) {
|
||||||
Class targetClass = targetType.getType();
|
if (this == TypeDescriptor.NULL || targetType == TypeDescriptor.NULL) {
|
||||||
if (!isTypeAssignableTo(targetClass)) {
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (targetClass != null) {
|
return targetType.getObjectType().isAssignableFrom(getObjectType());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A textual representation of the type descriptor (eg. Map<String,Foo>) for use in messages
|
* A textual representation of the type descriptor (eg. Map<String,Foo>) for use in messages
|
||||||
*/
|
*/
|
||||||
public String asString() {
|
public String asString() {
|
||||||
StringBuffer stringValue = new StringBuffer();
|
return toString();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
@ -484,6 +455,14 @@ public class TypeDescriptor {
|
||||||
builder.append("@").append(ann.annotationType().getName()).append(' ');
|
builder.append("@").append(ann.annotationType().getName()).append(' ');
|
||||||
}
|
}
|
||||||
builder.append(ClassUtils.getQualifiedName(getType()));
|
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("]");
|
builder.append("]");
|
||||||
return builder.toString();
|
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
|
// static factory methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -551,7 +524,7 @@ public class TypeDescriptor {
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (object instanceof Collection || object instanceof Map) {
|
else if (object instanceof Collection<?> || object instanceof Map<?, ?>) {
|
||||||
return new TypeDescriptor(object);
|
return new TypeDescriptor(object);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
import org.springframework.core.convert.converter.GenericConverter;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
@ -35,7 +36,7 @@ final class ArrayToArrayConverter implements GenericConverter {
|
||||||
|
|
||||||
private final CollectionToArrayConverter helperConverter;
|
private final CollectionToArrayConverter helperConverter;
|
||||||
|
|
||||||
public ArrayToArrayConverter(GenericConversionService conversionService) {
|
public ArrayToArrayConverter(ConversionService conversionService) {
|
||||||
this.helperConverter = new CollectionToArrayConverter(conversionService);
|
this.helperConverter = new CollectionToArrayConverter(conversionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,27 +22,25 @@ import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an Array to a Collection.
|
* Converts an Array to a Collection.
|
||||||
*
|
*
|
||||||
* <p>First, creates a new Collection of the requested targetType.
|
* <p>First, creates a new Collection of the requested targetType.
|
||||||
* Then adds each array element to the target collection.
|
* Then adds each array element to the target collection.
|
||||||
* Will perform an element conversion from the source component type
|
* Will perform an element conversion from the source component type to the collection's parameterized type if necessary.
|
||||||
* to the collection's parameterized type if necessary.
|
|
||||||
*
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public ArrayToCollectionConverter(GenericConversionService conversionService) {
|
public ArrayToCollectionConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,30 +55,16 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
int length = Array.getLength(source);
|
int length = Array.getLength(source);
|
||||||
Collection collection = CollectionFactory.createCollection(targetType.getType(), length);
|
Collection target = CollectionFactory.createCollection(targetType.getType(), length);
|
||||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
for (int i = 0; i < length; i++) {
|
||||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
Object sourceElement = Array.get(source, i);
|
||||||
if (targetElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetElementType)) {
|
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(sourceElement));
|
||||||
for (int i = 0; i < length; i++) {
|
target.add(targetElement);
|
||||||
collection.add(Array.get(source, i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
return target;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
@ -35,7 +36,7 @@ final class ArrayToObjectConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final CollectionToObjectConverter helperConverter;
|
private final CollectionToObjectConverter helperConverter;
|
||||||
|
|
||||||
public ArrayToObjectConverter(GenericConversionService conversionService) {
|
public ArrayToObjectConverter(ConversionService conversionService) {
|
||||||
this.helperConverter = new CollectionToObjectConverter(conversionService);
|
this.helperConverter = new CollectionToObjectConverter(conversionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
@ -35,7 +36,7 @@ final class ArrayToStringConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final CollectionToStringConverter helperConverter;
|
private final CollectionToStringConverter helperConverter;
|
||||||
|
|
||||||
public ArrayToStringConverter(GenericConversionService conversionService) {
|
public ArrayToStringConverter(ConversionService conversionService) {
|
||||||
this.helperConverter = new CollectionToStringConverter(conversionService);
|
this.helperConverter = new CollectionToStringConverter(conversionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,11 @@ package org.springframework.core.convert.support;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Collection to an array.
|
* Converts a Collection to an array.
|
||||||
|
|
@ -40,9 +38,9 @@ import org.springframework.core.convert.converter.GenericConverter;
|
||||||
*/
|
*/
|
||||||
final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public CollectionToArrayConverter(GenericConversionService conversionService) {
|
public CollectionToArrayConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,32 +54,14 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
Collection<?> sourceCollection = (Collection<?>) source;
|
Collection<?> sourceCollection = (Collection<?>) source;
|
||||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
Object array = Array.newInstance(targetType.getElementType(), sourceCollection.size());
|
||||||
if (sourceElementType == TypeDescriptor.NULL) {
|
|
||||||
sourceElementType = ConversionUtils.getElementType(sourceCollection);
|
|
||||||
}
|
|
||||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
|
||||||
Object array = Array.newInstance(targetElementType.getType(), sourceCollection.size());
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetElementType)) {
|
for (Object sourceElement : sourceCollection) {
|
||||||
for (Iterator<?> it = sourceCollection.iterator(); it.hasNext(); i++) {
|
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||||
Array.set(array, i, it.next());
|
Array.set(array, i++, targetElement);
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,9 @@ import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts from a Collection to another Collection.
|
* Converts from a Collection to another Collection.
|
||||||
|
|
@ -39,9 +38,9 @@ import org.springframework.core.convert.converter.GenericConverter;
|
||||||
*/
|
*/
|
||||||
final class CollectionToCollectionConverter implements ConditionalGenericConverter {
|
final class CollectionToCollectionConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public CollectionToCollectionConverter(GenericConversionService conversionService) {
|
public CollectionToCollectionConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,32 +55,13 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
Collection<?> sourceCollection = (Collection<?>) source;
|
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());
|
Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||||
GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType);
|
for (Object sourceElement : sourceCollection) {
|
||||||
if (converter == null) {
|
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor(sourceElement));
|
||||||
throw new ConverterNotFoundException(sourceElementType, targetElementType);
|
target.add(targetElement);
|
||||||
}
|
|
||||||
for (Object element : sourceCollection) {
|
|
||||||
target.add(ConversionUtils.invokeConverter(converter, element, sourceElementType, targetElementType));
|
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,9 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
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.
|
* 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 {
|
final class CollectionToObjectConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public CollectionToObjectConverter(GenericConversionService conversionService) {
|
public CollectionToObjectConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,29 +48,14 @@ final class CollectionToObjectConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
Collection<?> sourceCollection = (Collection<?>) source;
|
Collection<?> sourceCollection = (Collection<?>) source;
|
||||||
if (sourceCollection.size() == 0) {
|
if (sourceCollection.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
Object firstElement = sourceCollection.iterator().next();
|
||||||
Object firstElement = sourceCollection.iterator().next();
|
return this.conversionService.convert(firstElement, sourceType.getElementTypeDescriptor(firstElement), targetType);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -20,10 +20,9 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Collection to a comma-delimited String.
|
* Converts a Collection to a comma-delimited String.
|
||||||
|
|
@ -35,9 +34,9 @@ final class CollectionToStringConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private static final String DELIMITER = ",";
|
private static final String DELIMITER = ",";
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public CollectionToStringConverter(GenericConversionService conversionService) {
|
public CollectionToStringConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,48 +50,23 @@ final class CollectionToStringConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
Collection<?> sourceCollection = (Collection<?>) source;
|
Collection<?> sourceCollection = (Collection<?>) source;
|
||||||
if (sourceCollection.size() == 0) {
|
if (sourceCollection.size() == 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
else {
|
StringBuilder string = new StringBuilder();
|
||||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
int i = 0;
|
||||||
if (sourceElementType == TypeDescriptor.NULL) {
|
for (Object sourceElement : sourceCollection) {
|
||||||
sourceElementType = ConversionUtils.getElementType(sourceCollection);
|
if (i > 0) {
|
||||||
}
|
string.append(DELIMITER);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType);
|
||||||
|
string.append(targetElement);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
return string.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
|
import org.springframework.core.convert.ConversionException;
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.ConverterNotFoundException;
|
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.ConverterFactory;
|
||||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
import org.springframework.core.convert.converter.GenericConverter;
|
||||||
|
import org.springframework.core.style.StylerUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
|
@ -113,29 +115,68 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
|
|
||||||
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
assertNotNull(sourceType, 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 (sourceType == TypeDescriptor.NULL || targetType == TypeDescriptor.NULL) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Yes, I can convert");
|
||||||
|
}
|
||||||
return true;
|
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) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
assertNotNull(sourceType, targetType);
|
assertNotNull(sourceType, targetType);
|
||||||
if (logger.isDebugEnabled()) {
|
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) {
|
if (sourceType == TypeDescriptor.NULL) {
|
||||||
Assert.isTrue(source == null, "The source must be null if sourceType == TypeDescriptor.NULL");
|
Assert.isTrue(source == null, "The value must be null if sourceType == TypeDescriptor.NULL");
|
||||||
return convertNullSource(sourceType, targetType);
|
Object result = convertNullSource(sourceType, targetType);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Converted to " + StylerUtils.style(result));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (targetType == TypeDescriptor.NULL) {
|
if (targetType == TypeDescriptor.NULL) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Converted to null");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
GenericConverter converter = getConverter(sourceType, targetType);
|
GenericConverter converter = getConverter(sourceType, targetType);
|
||||||
if (converter == null) {
|
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() {
|
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.
|
* 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 <code>null</code> otherwise, indicating no suitable converter could be found.
|
* Returns <code>null</code> otherwise, indicating no suitable converter could be found.
|
||||||
* Subclasses may override.
|
* Subclasses may override.
|
||||||
* @param sourceType the source type to convert from
|
* @param sourceType the source type to convert from
|
||||||
|
|
@ -366,7 +407,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
|
|
||||||
private GenericConverter matchConverter(
|
private GenericConverter matchConverter(
|
||||||
MatchableConverters matchable, TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) {
|
MatchableConverters matchable, TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) {
|
||||||
|
|
||||||
return (matchable != null ? matchable.matchConverter(sourceFieldType, targetFieldType) : null);
|
return (matchable != null ? matchable.matchConverter(sourceFieldType, targetFieldType) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,19 +493,19 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
for (ConditionalGenericConverter conditional : this.conditionalConverters) {
|
for (ConditionalGenericConverter conditional : this.conditionalConverters) {
|
||||||
if (conditional.matches(sourceType, targetType)) {
|
if (conditional.matches(sourceType, targetType)) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Conditional converter lookup [MATCHED] " + conditional);
|
logger.debug("[MATCHED] converter " + conditional);
|
||||||
}
|
}
|
||||||
return conditional;
|
return conditional;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (logger.isDebugEnabled()) {
|
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()) {
|
if (this.defaultConverter != null && logger.isDebugEnabled()) {
|
||||||
logger.debug("Default converter lookup [MATCHED] " + this.defaultConverter);
|
logger.debug("[MATCHED] converter " + this.defaultConverter);
|
||||||
}
|
}
|
||||||
return this.defaultConverter;
|
return this.defaultConverter;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
import org.springframework.core.CollectionFactory;
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
|
|
||||||
|
|
@ -37,9 +38,9 @@ import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
*/
|
*/
|
||||||
final class MapToMapConverter implements 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;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,57 +56,19 @@ final class MapToMapConverter implements ConditionalGenericConverter {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
Map<?, ?> sourceMap = (Map<?, ?>) source;
|
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());
|
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()) {
|
for (Object entry : sourceMap.entrySet()) {
|
||||||
Map.Entry sourceMapEntry = (Map.Entry) entry;
|
Map.Entry sourceMapEntry = (Map.Entry) entry;
|
||||||
Object targetKey = converter.convertKey(sourceMapEntry.getKey());
|
Object sourceKey = sourceMapEntry.getKey();
|
||||||
Object targetValue = converter.convertValue(sourceMapEntry.getValue());
|
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);
|
targetMap.put(targetKey, targetValue);
|
||||||
}
|
}
|
||||||
return targetMap;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,9 @@ import java.lang.reflect.Array;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
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.
|
* 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 {
|
final class ObjectToArrayConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public ObjectToArrayConverter(GenericConversionService conversionService) {
|
public ObjectToArrayConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,20 +49,11 @@ final class ObjectToArrayConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
Object target = Array.newInstance(targetType.getElementType(), 1);
|
||||||
|
Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor());
|
||||||
|
Array.set(target, 0, targetElement);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,9 @@ import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
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.
|
* 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 {
|
final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public ObjectToCollectionConverter(GenericConversionService conversionService) {
|
public ObjectToCollectionConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,20 +51,11 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
Collection target = CollectionFactory.createCollection(targetType.getType(), 1);
|
Collection target = CollectionFactory.createCollection(targetType.getType(), 1);
|
||||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor(source));
|
||||||
if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) {
|
target.add(targetElement);
|
||||||
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));
|
|
||||||
}
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,6 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (sourceType.isAssignableTo(targetType)) {
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
Class<?> sourceClass = sourceType.getObjectType();
|
Class<?> sourceClass = sourceType.getObjectType();
|
||||||
Class<?> targetClass = targetType.getObjectType();
|
Class<?> targetClass = targetType.getObjectType();
|
||||||
Object target;
|
Object target;
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ final class ObjectToStringConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
Class<?> sourceClass = sourceType.getObjectType();
|
Class<?> sourceClass = sourceType.getObjectType();
|
||||||
return Number.class.isAssignableFrom(sourceClass) || Boolean.class.equals(sourceClass) ||
|
return String.class.equals(sourceClass) || Number.class.isAssignableFrom(sourceClass) ||
|
||||||
Character.class.equals(sourceClass) || CharSequence.class.isAssignableFrom(sourceClass) ||
|
Boolean.class.equals(sourceClass) || Character.class.equals(sourceClass) ||
|
||||||
StringWriter.class.isAssignableFrom(sourceClass) || sourceClass.isEnum() ||
|
CharSequence.class.isAssignableFrom(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) ||
|
||||||
ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
|
sourceClass.isEnum() || ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
|
|
|
||||||
|
|
@ -75,10 +75,10 @@ public class PropertyTypeDescriptor extends TypeDescriptor {
|
||||||
public Annotation[] getAnnotations() {
|
public Annotation[] getAnnotations() {
|
||||||
Annotation[] anns = this.cachedAnnotations;
|
Annotation[] anns = this.cachedAnnotations;
|
||||||
if (anns == null) {
|
if (anns == null) {
|
||||||
Map<Class, Annotation> annMap = new LinkedHashMap<Class, Annotation>();
|
Map<Class<?>, Annotation> annMap = new LinkedHashMap<Class<?>, Annotation>();
|
||||||
String name = this.propertyDescriptor.getName();
|
String name = this.propertyDescriptor.getName();
|
||||||
if (StringUtils.hasLength(name)) {
|
if (StringUtils.hasLength(name)) {
|
||||||
Class clazz = getMethodParameter().getMethod().getDeclaringClass();
|
Class<?> clazz = getMethodParameter().getMethod().getDeclaringClass();
|
||||||
Field field = ReflectionUtils.findField(clazz, name);
|
Field field = ReflectionUtils.findField(clazz, name);
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
// Same lenient fallback checking as in CachedIntrospectionResults...
|
// Same lenient fallback checking as in CachedIntrospectionResults...
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,9 @@ import java.lang.reflect.Array;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -34,9 +33,9 @@ import org.springframework.util.StringUtils;
|
||||||
*/
|
*/
|
||||||
final class StringToArrayConverter implements ConditionalGenericConverter {
|
final class StringToArrayConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public StringToArrayConverter(GenericConversionService conversionService) {
|
public StringToArrayConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,25 +49,17 @@ final class StringToArrayConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
String string = (String) source;
|
String string = (String) source;
|
||||||
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
||||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
Object target = Array.newInstance(targetType.getElementType(), fields.length);
|
||||||
if (sourceType.isAssignableTo(targetElementType)) {
|
for (int i = 0; i < fields.length; i++) {
|
||||||
return fields;
|
Object sourceElement = fields[i];
|
||||||
}
|
Object targetElement = this.conversionService.convert(sourceElement, sourceType, targetType.getElementTypeDescriptor());
|
||||||
else {
|
Array.set(target, i, targetElement);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -21,10 +21,9 @@ import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
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.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -35,9 +34,9 @@ import org.springframework.util.StringUtils;
|
||||||
*/
|
*/
|
||||||
final class StringToCollectionConverter implements ConditionalGenericConverter {
|
final class StringToCollectionConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
public StringToCollectionConverter(GenericConversionService conversionService) {
|
public StringToCollectionConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,27 +51,14 @@ final class StringToCollectionConverter implements ConditionalGenericConverter {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
String string = (String) source;
|
String string = (String) source;
|
||||||
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
||||||
Collection target = CollectionFactory.createCollection(targetType.getType(), fields.length);
|
Collection target = CollectionFactory.createCollection(targetType.getType(), fields.length);
|
||||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
for (String sourceElement : fields) {
|
||||||
if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) {
|
Object targetElement = this.conversionService.convert(sourceElement, sourceType, targetType.getElementTypeDescriptor(sourceElement));
|
||||||
for (String field : fields) {
|
target.add(targetElement);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,19 +39,20 @@ public class GenericConversionServiceTests {
|
||||||
private GenericConversionService conversionService = new GenericConversionService();
|
private GenericConversionService conversionService = new GenericConversionService();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void executeConversion() {
|
public void convert() {
|
||||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||||
assertEquals(new Integer(3), conversionService.convert("3", Integer.class));
|
assertEquals(new Integer(3), conversionService.convert("3", Integer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void executeConversionNullSource() {
|
public void convertNullSource() {
|
||||||
assertEquals(null, conversionService.convert(null, Integer.class));
|
assertEquals(null, conversionService.convert(null, Integer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void executeCompatibleSource() {
|
public void convertAssignableSource() {
|
||||||
assertEquals(Boolean.FALSE, conversionService.convert(false, boolean.class));
|
assertEquals(Boolean.FALSE, conversionService.convert(false, boolean.class));
|
||||||
|
assertEquals(Boolean.FALSE, conversionService.convert(false, Boolean.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -189,7 +190,7 @@ public class GenericConversionServiceTests {
|
||||||
input.put("key", "value");
|
input.put("key", "value");
|
||||||
Object converted = conversionService.convert(input, TypeDescriptor.forObject(input),
|
Object converted = conversionService.convert(input, TypeDescriptor.forObject(input),
|
||||||
new TypeDescriptor(getClass().getField("wildcardMap")));
|
new TypeDescriptor(getClass().getField("wildcardMap")));
|
||||||
assertSame(input, converted);
|
assertEquals(input, converted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ public class TypedValue {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder str = new StringBuilder();
|
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();
|
return str.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ import org.springframework.expression.ParseException;
|
||||||
import org.springframework.expression.PropertyAccessor;
|
import org.springframework.expression.PropertyAccessor;
|
||||||
import org.springframework.expression.TypedValue;
|
import org.springframework.expression.TypedValue;
|
||||||
import org.springframework.expression.spel.ast.FormatHelper;
|
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.ReflectionHelper;
|
||||||
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||||
import org.springframework.expression.spel.support.ReflectionHelper.ArgsMatchKind;
|
import org.springframework.expression.spel.support.ReflectionHelper.ArgsMatchKind;
|
||||||
import org.springframework.expression.spel.standard.SpelExpression;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for any helper code.
|
* Tests for any helper code.
|
||||||
|
|
@ -94,7 +94,7 @@ public class HelperTests extends ExpressionTestCase {
|
||||||
public void testTypedValue() {
|
public void testTypedValue() {
|
||||||
TypedValue tValue = new TypedValue("hello");
|
TypedValue tValue = new TypedValue("hello");
|
||||||
Assert.assertEquals(String.class,tValue.getTypeDescriptor().getType());
|
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
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue