Fixed addConverterFactory assertion

This commit is contained in:
Juergen Hoeller 2015-03-25 00:42:51 +01:00
parent 4e28da439d
commit 22670b7fad
2 changed files with 54 additions and 52 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -92,7 +92,7 @@ public class GenericConversionService implements ConfigurableConversionService {
new ConcurrentHashMap<ConverterCacheKey, GenericConverter>(64);
// implementing ConverterRegistry
// ConverterRegistry implementation
@Override
public void addConverter(Converter<?, ?> converter) {
@ -104,7 +104,8 @@ public class GenericConversionService implements ConfigurableConversionService {
@Override
public void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter) {
addConverter(new ConverterAdapter(converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
addConverter(new ConverterAdapter(
converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
}
@Override
@ -116,7 +117,7 @@ public class GenericConversionService implements ConfigurableConversionService {
@Override
public void addConverterFactory(ConverterFactory<?, ?> converterFactory) {
ResolvableType[] typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class);
Assert.notNull("Unable to the determine sourceType <S> and targetRangeType R which your " +
Assert.notNull(typeInfo, "Unable to the determine source type <S> and target range type R which your " +
"ConverterFactory<S, R> converts between; declare these generic types.");
addConverter(new ConverterFactoryAdapter(converterFactory,
new ConvertiblePair(typeInfo[0].resolve(), typeInfo[1].resolve())));
@ -128,7 +129,8 @@ public class GenericConversionService implements ConfigurableConversionService {
invalidateCache();
}
// implementing ConversionService
// ConversionService implementation
@Override
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
@ -148,17 +150,18 @@ public class GenericConversionService implements ConfigurableConversionService {
}
/**
* Returns true if conversion between the sourceType and targetType can be bypassed.
* More precisely this method will return true if objects of sourceType can be
* Return whether conversion between the sourceType and targetType can be bypassed.
* <p>More precisely, this method will return true if objects of sourceType can be
* converted to the targetType by returning the source object unchanged.
* @param sourceType context about the source type to convert from (may be null if source is null)
* @param sourceType context about the source type to convert from
* (may be {@code null} if source is {@code null})
* @param targetType context about the target type to convert to (required)
* @return true if conversion can be bypassed
* @throws IllegalArgumentException if targetType is null
* @return {@code true} if conversion can be bypassed; {@code false} otherwise
* @throws IllegalArgumentException if targetType is {@code null}
* @since 3.2
*/
public boolean canBypassConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
Assert.notNull(targetType, "The targetType to convert to cannot be null");
Assert.notNull(targetType, "targetType to convert to cannot be null");
if (sourceType == null) {
return true;
}
@ -169,19 +172,19 @@ public class GenericConversionService implements ConfigurableConversionService {
@Override
@SuppressWarnings("unchecked")
public <T> T convert(Object source, Class<T> targetType) {
Assert.notNull(targetType,"The targetType to convert to cannot be null");
Assert.notNull(targetType, "targetType to convert to cannot be null");
return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
Assert.notNull(targetType,"The targetType to convert to cannot be null");
Assert.notNull(targetType, "targetType to convert to cannot be null");
if (sourceType == null) {
Assert.isTrue(source == null, "The source must be [null] if sourceType == [null]");
return handleResult(sourceType, targetType, convertNullSource(sourceType, targetType));
Assert.isTrue(source == null, "source must be [null] if sourceType == [null]");
return handleResult(null, targetType, convertNullSource(null, targetType));
}
if (source != null && !sourceType.getObjectType().isInstance(source)) {
throw new IllegalArgumentException("The source to convert from must be an instance of " +
throw new IllegalArgumentException("source to convert from must be an instance of " +
sourceType + "; instead it was a " + source.getClass().getName());
}
GenericConverter converter = getConverter(sourceType, targetType);
@ -202,8 +205,8 @@ public class GenericConversionService implements ConfigurableConversionService {
* @param targetType the target type
* @return the converted value
* @throws ConversionException if a conversion exception occurred
* @throws IllegalArgumentException if targetType is null,
* or sourceType is null but source is not null
* @throws IllegalArgumentException if targetType is {@code null},
* or sourceType is {@code null} but source is not {@code null}
*/
public Object convert(Object source, TypeDescriptor targetType) {
return convert(source, TypeDescriptor.forObject(source), targetType);
@ -218,11 +221,11 @@ public class GenericConversionService implements ConfigurableConversionService {
// Protected template methods
/**
* Template method to convert a null source.
* <p>Default implementation returns {@code null} or the Java 8
* Template method to convert a {@code null} source.
* <p>The default implementation returns {@code null} or the Java 8
* {@link java.util.Optional#empty()} instance if the target type is
* {@code java.uti.Optional}.
* Subclasses may override to return custom null objects for specific target types.
* {@code java.util.Optional}. Subclasses may override this to return
* custom {@code null} objects for specific target types.
* @param sourceType the sourceType to convert from
* @param targetType the targetType to convert to
* @return the converted null object
@ -239,11 +242,10 @@ public class GenericConversionService implements ConfigurableConversionService {
* First queries this ConversionService's converter cache.
* On a cache miss, then performs an exhaustive search for a matching converter.
* If no converter matches, returns the default converter.
* Subclasses may override.
* @param sourceType the source type to convert from
* @param targetType the target type to convert to
* @return the generic converter that will perform the conversion, or {@code null} if
* no suitable converter was found
* @return the generic converter that will perform the conversion,
* or {@code null} if no suitable converter was found
* @see #getDefaultConverter(TypeDescriptor, TypeDescriptor)
*/
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
@ -269,9 +271,8 @@ public class GenericConversionService implements ConfigurableConversionService {
/**
* Return the default converter if no converter is found for the given sourceType/targetType pair.
* Returns a NO_OP Converter if the sourceType is assignable to the targetType.
* <p>Returns a NO_OP Converter if the sourceType is assignable to the targetType.
* Returns {@code null} otherwise, indicating no suitable converter could be found.
* Subclasses may override.
* @param sourceType the source type to convert from
* @param targetType the target type to convert to
* @return the default generic converter that will perform the conversion
@ -280,7 +281,8 @@ public class GenericConversionService implements ConfigurableConversionService {
return (sourceType.isAssignableTo(targetType) ? NO_OP_CONVERTER : null);
}
// internal helpers
// Internal helpers
private ResolvableType[] getRequiredTypeInfo(Object converter, Class<?> genericIfc) {
ResolvableType resolvableType = ResolvableType.forClass(converter.getClass()).as(genericIfc);
@ -303,7 +305,7 @@ public class GenericConversionService implements ConfigurableConversionService {
private Object handleConverterNotFound(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
assertNotPrimitiveTargetType(sourceType, targetType);
return source;
return null;
}
if (sourceType.isAssignableTo(targetType) && targetType.getObjectType().isInstance(source)) {
return source;
@ -375,7 +377,7 @@ public class GenericConversionService implements ConfigurableConversionService {
@Override
public String toString() {
return this.typeInfo + " : " + this.converter;
return (this.typeInfo + " : " + this.converter);
}
}
@ -425,7 +427,7 @@ public class GenericConversionService implements ConfigurableConversionService {
@Override
public String toString() {
return this.typeInfo + " : " + this.converterFactory;
return (this.typeInfo + " : " + this.converterFactory);
}
}
@ -453,20 +455,20 @@ public class GenericConversionService implements ConfigurableConversionService {
return false;
}
ConverterCacheKey otherKey = (ConverterCacheKey) other;
return ObjectUtils.nullSafeEquals(this.sourceType, otherKey.sourceType) &&
ObjectUtils.nullSafeEquals(this.targetType, otherKey.targetType);
return (ObjectUtils.nullSafeEquals(this.sourceType, otherKey.sourceType) &&
ObjectUtils.nullSafeEquals(this.targetType, otherKey.targetType));
}
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.sourceType) * 29 +
ObjectUtils.nullSafeHashCode(this.targetType);
return (ObjectUtils.nullSafeHashCode(this.sourceType) * 29 +
ObjectUtils.nullSafeHashCode(this.targetType));
}
@Override
public String toString() {
return "ConverterCacheKey [sourceType = " + this.sourceType +
", targetType = " + this.targetType + "]";
return ("ConverterCacheKey [sourceType = " + this.sourceType +
", targetType = " + this.targetType + "]");
}
}
@ -544,9 +546,9 @@ public class GenericConversionService implements ConfigurableConversionService {
return converter;
}
}
// Check ConditionalGenericConverter that match all types
// Check ConditionalConverters for a dynamic match
for (GenericConverter globalConverter : this.globalConverters) {
if (((ConditionalConverter)globalConverter).matches(sourceType, targetType)) {
if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) {
return globalConverter;
}
}
@ -563,6 +565,7 @@ public class GenericConversionService implements ConfigurableConversionService {
Set<Class<?>> visited = new HashSet<Class<?>>(20);
addToClassHierarchy(0, ClassUtils.resolvePrimitiveIfNecessary(type), false, hierarchy, visited);
boolean array = type.isArray();
int i = 0;
while (i < hierarchy.size()) {
Class<?> candidate = hierarchy.get(i);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -113,17 +113,17 @@ public class GenericConversionServiceTests {
assertEquals(null, conversionService.convert(null, Integer.class));
}
@Test(expected=ConversionFailedException.class)
@Test(expected = ConversionFailedException.class)
public void convertNullSourcePrimitiveTarget() {
assertEquals(null, conversionService.convert(null, int.class));
}
@Test(expected=ConversionFailedException.class)
@Test(expected = ConversionFailedException.class)
public void convertNullSourcePrimitiveTargetTypeDescriptor() {
conversionService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(int.class));
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void convertNotNullSourceNullSourceTypeDescriptor() {
conversionService.convert("3", null, TypeDescriptor.valueOf(int.class));
}
@ -177,18 +177,18 @@ public class GenericConversionServiceTests {
assertNull(conversionService.convert(null, Integer.class));
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void convertNullTargetClass() {
assertNull(conversionService.convert("3", (Class<?>) null));
assertNull(conversionService.convert("3", TypeDescriptor.valueOf(String.class), null));
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void convertNullTypeDescriptor() {
assertNull(conversionService.convert("3", TypeDescriptor.valueOf(String.class), null));
}
@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void convertWrongSourceTypeDescriptor() {
conversionService.convert("3", TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(Long.class));
}
@ -218,8 +218,7 @@ public class GenericConversionServiceTests {
}
// SPR-8718
@Test(expected=ConverterNotFoundException.class)
@Test(expected = ConverterNotFoundException.class)
public void convertSuperTarget() {
conversionService.addConverter(new ColorConverter());
conversionService.convert("#000000", SystemColor.class);
@ -295,7 +294,7 @@ public class GenericConversionServiceTests {
@Test
public void testInterfaceToString() {
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(new MyBaseInterfaceConverter());
conversionService.addConverter(new MyBaseInterfaceToStringConverter());
conversionService.addConverter(new ObjectToStringConverter());
Object converted = conversionService.convert(new MyInterfaceImplementer(), String.class);
assertEquals("RESULT", converted);
@ -304,7 +303,7 @@ public class GenericConversionServiceTests {
@Test
public void testInterfaceArrayToStringArray() {
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(new MyBaseInterfaceConverter());
conversionService.addConverter(new MyBaseInterfaceToStringConverter());
conversionService.addConverter(new ArrayToArrayConverter(conversionService));
String[] converted = conversionService.convert(new MyInterface[] {new MyInterfaceImplementer()}, String[].class);
assertEquals("RESULT", converted[0]);
@ -313,7 +312,7 @@ public class GenericConversionServiceTests {
@Test
public void testObjectArrayToStringArray() {
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(new MyBaseInterfaceConverter());
conversionService.addConverter(new MyBaseInterfaceToStringConverter());
conversionService.addConverter(new ArrayToArrayConverter(conversionService));
String[] converted = conversionService.convert(new MyInterfaceImplementer[] {new MyInterfaceImplementer()}, String[].class);
assertEquals("RESULT", converted[0]);
@ -813,7 +812,7 @@ public class GenericConversionServiceTests {
}
private static class MyBaseInterfaceConverter implements Converter<MyBaseInterface, String> {
private static class MyBaseInterfaceToStringConverter implements Converter<MyBaseInterface, String> {
@Override
public String convert(MyBaseInterface source) {