implemented collection/map converter conditional matching checks; updated SpEL to reflect this behavior
This commit is contained in:
@@ -45,7 +45,7 @@ final class ArrayToArrayConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
return this.helperConverter.matches(sourceType, targetType);
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
@@ -49,7 +49,23 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
// yes
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getElementTypeDescriptor().getType().isAssignableFrom(targetType.getElementTypeDescriptor().getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -45,7 +45,7 @@ final class ArrayToObjectConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
return this.helperConverter.matches(sourceType, targetType);
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
@@ -45,7 +45,7 @@ final class ArrayToStringConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
return this.helperConverter.matches(sourceType, targetType);
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
@@ -49,7 +49,23 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
if (sourceType.getElementTypeDescriptor() == null) {
|
||||
// maybe
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getElementTypeDescriptor().getType().isAssignableFrom(targetType.getElementTypeDescriptor().getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
@@ -66,4 +82,4 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,27 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
// yes
|
||||
return true;
|
||||
}
|
||||
if (sourceType.getElementTypeDescriptor() == null) {
|
||||
// maybe
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getElementTypeDescriptor().getType().isAssignableFrom(targetType.getElementTypeDescriptor().getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -72,4 +92,4 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,23 @@ final class CollectionToObjectConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
if (sourceType.getElementTypeDescriptor() == null) {
|
||||
// maybe
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType);
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getElementTypeDescriptor().getType().isAssignableFrom(targetType.getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
@@ -45,7 +45,23 @@ final class CollectionToStringConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
if (sourceType.getElementTypeDescriptor() == null) {
|
||||
// maybe
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType);
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getElementTypeDescriptor().getType().isAssignableFrom(targetType.getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
@@ -69,4 +85,4 @@ final class CollectionToStringConverter implements ConditionalGenericConverter {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ final class MapToMapConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
return canConvertKey(sourceType, targetType) && canConvertValue(sourceType, targetType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -70,6 +70,54 @@ final class MapToMapConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private boolean canConvertKey(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType.getMapKeyTypeDescriptor() == null) {
|
||||
// yes
|
||||
return true;
|
||||
}
|
||||
if (sourceType.getMapKeyTypeDescriptor() == null) {
|
||||
// maybe
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType.getMapKeyTypeDescriptor(), targetType.getMapKeyTypeDescriptor());
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getMapKeyTypeDescriptor().getType().isAssignableFrom(targetType.getMapKeyTypeDescriptor().getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canConvertValue(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType.getMapValueTypeDescriptor() == null) {
|
||||
// yes
|
||||
return true;
|
||||
}
|
||||
if (sourceType.getMapValueTypeDescriptor() == null) {
|
||||
// maybe
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType.getMapValueTypeDescriptor(), targetType.getMapValueTypeDescriptor());
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getMapValueTypeDescriptor().getType().isAssignableFrom(targetType.getMapValueTypeDescriptor().getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object convertKey(Object sourceKey, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType == null) {
|
||||
|
||||
@@ -44,7 +44,19 @@ final class ObjectToArrayConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
boolean canConvert = conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor());
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getType().isAssignableFrom(targetType.getElementTypeDescriptor().getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
@@ -46,7 +46,23 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return true;
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
// yes
|
||||
return true;
|
||||
}
|
||||
boolean canConvert = conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor());
|
||||
if (canConvert) {
|
||||
// yes
|
||||
return true;
|
||||
} else {
|
||||
if (sourceType.getType().isAssignableFrom(targetType.getElementTypeDescriptor().getType())) {
|
||||
// maybe;
|
||||
return true;
|
||||
} else {
|
||||
// no;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -64,4 +80,4 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -175,16 +175,16 @@ public class CollectionToCollectionConverterTests {
|
||||
assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allNullsNotConvertible() throws Exception {
|
||||
@Test(expected=ConverterNotFoundException.class)
|
||||
public void elementTypesNotConvertible() throws Exception {
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
resources.add(null);
|
||||
resources.add(null);
|
||||
TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("allNullsNotConvertible"));
|
||||
TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("strings"));
|
||||
assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
|
||||
}
|
||||
|
||||
public List<String> allNullsNotConvertible;
|
||||
public List<String> strings;
|
||||
|
||||
@Test(expected=ConversionFailedException.class)
|
||||
public void nothingInCommon() throws Exception {
|
||||
|
||||
@@ -225,11 +225,11 @@ public class GenericConversionServiceTests {
|
||||
@Test
|
||||
public void genericConverterDelegatingBackToConversionServiceConverterNotFound() {
|
||||
conversionService.addConverter(new ObjectToArrayConverter(conversionService));
|
||||
assertTrue(conversionService.canConvert(String.class, Integer[].class));
|
||||
assertFalse(conversionService.canConvert(String.class, Integer[].class));
|
||||
try {
|
||||
conversionService.convert("3,4,5", Integer[].class);
|
||||
} catch (ConversionFailedException e) {
|
||||
assertTrue(e.getCause() instanceof ConverterNotFoundException);
|
||||
fail("should have failed");
|
||||
} catch (ConverterNotFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.core.convert.support;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -114,12 +115,13 @@ public class MapToMapConverterTests {
|
||||
map.put("2", Arrays.asList("37", "23"));
|
||||
TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("sourceCollectionMapTarget"));
|
||||
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("collectionMapTarget"));
|
||||
assertTrue(conversionService.canConvert(sourceType, targetType));
|
||||
assertFalse(conversionService.canConvert(sourceType, targetType));
|
||||
try {
|
||||
conversionService.convert(map, sourceType, targetType);
|
||||
} catch (ConversionFailedException e) {
|
||||
assertTrue(e.getCause() instanceof ConverterNotFoundException);
|
||||
}
|
||||
fail("Should have failed");
|
||||
} catch (ConverterNotFoundException e) {
|
||||
|
||||
}
|
||||
conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
assertTrue(conversionService.canConvert(sourceType, targetType));
|
||||
|
||||
Reference in New Issue
Block a user