string to collection and array converters now are conditional and apply target element type match
This commit is contained in:
parent
38041acc87
commit
a1a7c32052
|
|
@ -27,7 +27,12 @@ public interface ConversionService {
|
|||
|
||||
/**
|
||||
* Returns true if objects of sourceType can be converted to targetType.
|
||||
* @param sourceType the source type to convert from (required)
|
||||
* If this method returns true, it means {@link #convert(Object, Class)} is capable of converting an instance of sourceType to targetType.
|
||||
* Special note on collections, arrays, and maps types:
|
||||
* For conversion between collection, array, and map types, this method will return 'true'
|
||||
* even though a convert invocation may still generate a {@link ConversionException} if the underlying elements are not convertible.
|
||||
* Callers are expected to handle this exceptional case when working with collections and maps.
|
||||
* @param sourceType the source type to convert from (may be null if source is null)
|
||||
* @param targetType the target type to convert to (required)
|
||||
* @return true if a conversion can be performed, false if not
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
|
|
@ -36,12 +41,16 @@ public interface ConversionService {
|
|||
|
||||
/**
|
||||
* Returns true if objects of sourceType can be converted to the targetType.
|
||||
* The TypeDescriptors provide additional context about the source and target locations where conversion would occur, often object property locations.
|
||||
* @param sourceType context about the source type to convert from (required)
|
||||
* The TypeDescriptors provide additional context about the source and target locations where conversion would occur, often object fields or property locations.
|
||||
* If this method returns true, it means {@link #convert(Object, TypeDescriptor, TypeDescriptor)} is capable of converting an instance of sourceType to targetType.
|
||||
* Special note on collections, arrays, and maps types:
|
||||
* For conversion between collection, array, and map types, this method will return 'true'
|
||||
* even though a convert invocation may still generate a {@link ConversionException} if the underlying elements are not convertible.
|
||||
* Callers are expected to handle this exceptional case when working with collections and maps.
|
||||
* @param sourceType context about the source type to convert from (may be null if source is null)
|
||||
* @param targetType context about the target type to convert to (required)
|
||||
* @return true if a conversion can be performed between the source and target types, false if not
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
* @see TypeDescriptor#forObject(Object)
|
||||
*/
|
||||
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
|
||||
|
|
@ -57,7 +66,7 @@ public interface ConversionService {
|
|||
|
||||
/**
|
||||
* Convert the source to targetType.
|
||||
* The TypeDescriptors provide additional context about the source and target locations where conversion will occur, often object property locations.
|
||||
* The TypeDescriptors provide additional context about the source and target locations where conversion will occur, often object fields or property locations.
|
||||
* @param source the source object to convert (may be null)
|
||||
* @param sourceType context about the source type converting from (may be null if source is null)
|
||||
* @param targetType context about the target type to convert to (required)
|
||||
|
|
@ -65,7 +74,6 @@ public interface ConversionService {
|
|||
* @throws ConversionException if a conversion exception occurred
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
* @throws IllegalArgumentException if sourceType is null but source is not null
|
||||
* @see TypeDescriptor#forObject(Object)
|
||||
*/
|
||||
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,16 +22,17 @@ 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.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Converts a comma-delimited String to an Array.
|
||||
*
|
||||
* Only matches if String.class can be converted to the target array element type.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
final class StringToArrayConverter implements GenericConverter {
|
||||
final class StringToArrayConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final ConversionService conversionService;
|
||||
|
||||
|
|
@ -43,6 +44,10 @@ final class StringToArrayConverter implements GenericConverter {
|
|||
return Collections.singleton(new ConvertiblePair(String.class, Object[].class));
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.conversionService.canConvert(sourceType, targetType.getElementType());
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
|
|||
|
||||
/**
|
||||
* Converts a comma-delimited String to a Collection.
|
||||
* If the target collection element type is declared, only matches if String.class can be converted to it.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
|
|
@ -45,10 +46,11 @@ final class StringToCollectionConverter implements ConditionalGenericConverter {
|
|||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType.getElementType() == null) {
|
||||
if (targetType.getElementType() != null) {
|
||||
return this.conversionService.canConvert(sourceType, targetType.getElementType());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return this.conversionService.canConvert(sourceType, targetType.getElementType());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
|||
|
|
@ -759,4 +759,5 @@ public class DefaultConversionTests {
|
|||
return new TestEntity(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,16 +16,17 @@
|
|||
|
||||
package org.springframework.core.convert.support;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
|
|
@ -528,4 +529,25 @@ public class GenericConversionServiceTests {
|
|||
|
||||
public static Map<String, ?> wildcardMap;
|
||||
|
||||
@Test
|
||||
public void stringToArrayCanConvert() {
|
||||
conversionService.addConverter(new StringToArrayConverter(conversionService));
|
||||
assertFalse(conversionService.canConvert(String.class, Integer[].class));
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
assertTrue(conversionService.canConvert(String.class, Integer[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringToCollectionCanConvert() throws Exception {
|
||||
conversionService.addConverter(new StringToCollectionConverter(conversionService));
|
||||
assertTrue(conversionService.canConvert(String.class, Collection.class));
|
||||
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("stringToCollection"));
|
||||
assertFalse(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
assertTrue(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
|
||||
}
|
||||
|
||||
public Collection<Integer> stringToCollection;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue