conversion utils helper for common code

This commit is contained in:
Keith Donald 2009-09-22 15:37:26 +00:00
parent 871fc14fbb
commit ed611be838
12 changed files with 91 additions and 80 deletions

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
@ -40,7 +42,9 @@ final class ArrayToArrayGenericConverter implements GenericConverter {
throw new ConverterNotFoundException(sourceElementType, targetElementType); throw new ConverterNotFoundException(sourceElementType, targetElementType);
} }
for (int i = 0; i < Array.getLength(target); i++) { for (int i = 0; i < Array.getLength(target); i++) {
Array.set(target, i, converter.convert(Array.get(source, i), sourceElementType, targetElementType)); Object sourceElement = Array.get(source, i);
Object targetElement = invokeConverter(converter, sourceElement, sourceElementType, targetElementType);
Array.set(target, i, targetElement);
} }
return target; return target;
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.Collection; import java.util.Collection;
@ -45,7 +47,9 @@ final class ArrayToCollectionGenericConverter implements GenericConverter {
throw new ConverterNotFoundException(sourceElementType, targetElementType); throw new ConverterNotFoundException(sourceElementType, targetElementType);
} }
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
collection.add(converter.convert(Array.get(source, i), sourceElementType, targetElementType)); Object sourceElement = Array.get(source, i);
Object targetElement = invokeConverter(converter, sourceElement, sourceElementType, targetElementType);
collection.add(targetElement);
} }
} }
return collection; return collection;

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
@ -41,7 +43,7 @@ final class ArrayToObjectGenericConverter implements GenericConverter {
if (converter == null) { if (converter == null) {
throw new ConverterNotFoundException(sourceElementType, targetType); throw new ConverterNotFoundException(sourceElementType, targetType);
} }
return converter.convert(Array.get(source, 0), sourceElementType, targetType); return invokeConverter(converter, Array.get(source, 0), sourceElementType, targetType);
} }
} }
} }

View File

@ -15,6 +15,9 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getElementType;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
@ -49,19 +52,12 @@ final class CollectionToArrayGenericConverter implements GenericConverter {
throw new ConverterNotFoundException(sourceElementType, targetElementType); throw new ConverterNotFoundException(sourceElementType, targetElementType);
} }
for (Iterator it = sourceCollection.iterator(); it.hasNext(); i++) { for (Iterator it = sourceCollection.iterator(); it.hasNext(); i++) {
Array.set(array, i, converter.convert(it.next(), sourceElementType, targetElementType)); Object sourceElement = it.next();
Object targetElement = invokeConverter(converter, sourceElement, sourceElementType, targetElementType);
Array.set(array, i, targetElement);
} }
} }
return array; return array;
} }
private TypeDescriptor getElementType(Collection collection) {
for (Object element : collection) {
if (element != null) {
return TypeDescriptor.valueOf(element.getClass());
}
}
return TypeDescriptor.NULL;
}
} }

View File

@ -15,6 +15,9 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getElementType;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.util.Collection; import java.util.Collection;
import org.springframework.core.CollectionFactory; import org.springframework.core.CollectionFactory;
@ -40,30 +43,20 @@ final class CollectionToCollectionGenericConverter implements GenericConverter {
if (sourceType.isAssignableTo(targetType)) { if (sourceType.isAssignableTo(targetType)) {
return sourceCollection; return sourceCollection;
} else { } else {
Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
.size()); target.addAll(sourceCollection);
targetCollection.addAll(sourceCollection); return target;
return targetCollection;
} }
} }
Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size()); Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType); GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType);
if (converter == null) { if (converter == null) {
throw new ConverterNotFoundException(sourceElementType, targetElementType); throw new ConverterNotFoundException(sourceElementType, targetElementType);
} }
for (Object element : sourceCollection) { for (Object element : sourceCollection) {
targetCollection.add(converter.convert(element, sourceElementType, targetElementType)); target.add(invokeConverter(converter, element, sourceElementType, targetElementType));
} }
return targetCollection; return target;
}
private TypeDescriptor getElementType(Collection collection) {
for (Object element : collection) {
if (element != null) {
return TypeDescriptor.valueOf(element.getClass());
}
}
return TypeDescriptor.NULL;
} }
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.util.Collection; import java.util.Collection;
import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
@ -45,7 +47,7 @@ final class CollectionToObjectGenericConverter implements GenericConverter {
if (converter == null) { if (converter == null) {
throw new ConverterNotFoundException(sourceElementType, targetType); throw new ConverterNotFoundException(sourceElementType, targetType);
} }
return converter.convert(firstElement, sourceElementType, targetType); return invokeConverter(converter, firstElement, sourceElementType, targetType);
} }
} }
} }

View File

@ -0,0 +1,27 @@
package org.springframework.core.convert.support;
import java.util.Collection;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.TypeDescriptor;
final class ConversionUtils {
public static Object invokeConverter(GenericConverter converter, Object source, TypeDescriptor sourceType,
TypeDescriptor targetType) {
try {
return converter.convert(source, sourceType, targetType);
}
catch (Exception ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
}
public static TypeDescriptor getElementType(Collection collection) {
for (Object element : collection) {
if (element != null) {
return TypeDescriptor.valueOf(element.getClass());
}
}
return TypeDescriptor.NULL;
}
}

View File

@ -16,6 +16,8 @@
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -30,7 +32,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
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.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.TypeDescriptor;
@ -58,7 +59,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
} }
}; };
private final Map<Class, Map<Class, GenericConverter>> sourceTypeConverters = new HashMap<Class, Map<Class, GenericConverter>>(); private final Map<Class, Map<Class, GenericConverter>> sourceTypeConverters = new HashMap<Class, Map<Class, GenericConverter>>();
private ConversionService parent; private ConversionService parent;
@ -69,12 +69,10 @@ public class GenericConversionService implements ConversionService, ConverterReg
} }
}; };
public GenericConversionService() { public GenericConversionService() {
initGenericConverters(); initGenericConverters();
} }
/** /**
* Registers the converters in the set provided. * Registers the converters in the set provided.
* JavaBean-friendly alternative to calling {@link #addConverter(Converter)}. * JavaBean-friendly alternative to calling {@link #addConverter(Converter)}.
@ -111,7 +109,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
return this.parent; return this.parent;
} }
// implementing ConverterRegistry // implementing ConverterRegistry
public void addConverter(Converter converter) { public void addConverter(Converter converter) {
@ -140,7 +137,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
getSourceMap(sourceType).remove(targetType); getSourceMap(sourceType).remove(targetType);
} }
// implementing ConversionService // implementing ConversionService
public boolean canConvert(Class<?> sourceType, Class<?> targetType) { public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
@ -177,15 +173,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
if (converter == null) { if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType); throw new ConverterNotFoundException(sourceType, targetType);
} }
try { return invokeConverter(converter, source, sourceType, targetType);
return converter.convert(source, sourceType, targetType);
}
catch (ConversionFailedException ex) {
throw ex;
}
catch (Exception ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
} }
// subclassing hooks // subclassing hooks
@ -203,6 +191,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
addGenericConverter(Map.class, Map.class, new MapToMapGenericConverter(this)); addGenericConverter(Map.class, Map.class, new MapToMapGenericConverter(this));
addGenericConverter(Object.class, Object[].class, new ObjectToArrayGenericConverter(this)); addGenericConverter(Object.class, Object[].class, new ObjectToArrayGenericConverter(this));
addGenericConverter(Object.class, Collection.class, new ObjectToCollectionGenericConverter(this)); addGenericConverter(Object.class, Collection.class, new ObjectToCollectionGenericConverter(this));
addGenericConverter(String.class, Object[].class, new StringToArrayGenericConverter(this));
} }
/** /**
@ -242,21 +231,17 @@ public class GenericConversionService implements ConversionService, ConverterReg
GenericConverter converter = findConverterByClassPair(sourceType.getObjectType(), targetType.getObjectType()); GenericConverter converter = findConverterByClassPair(sourceType.getObjectType(), targetType.getObjectType());
if (converter != null) { if (converter != null) {
return converter; return converter;
} } else if (this.parent != null && this.parent.canConvert(sourceType, targetType)) {
else if (this.parent != null && this.parent.canConvert(sourceType, targetType)) {
return this.parentConverterAdapter; return this.parentConverterAdapter;
} } else {
else {
if (sourceType.isAssignableTo(targetType)) { if (sourceType.isAssignableTo(targetType)) {
return NO_OP_CONVERTER; return NO_OP_CONVERTER;
} } else {
else {
return null; return null;
} }
} }
} }
// internal helpers // internal helpers
private List<Class> getRequiredTypeInfo(Object converter) { private List<Class> getRequiredTypeInfo(Object converter) {
@ -298,12 +283,10 @@ public class GenericConversionService implements ConversionService, ConverterReg
if (typeInfo.size() == 2) { if (typeInfo.size() == 2) {
return typeInfo; return typeInfo;
} }
} } else if (Converter.class.isAssignableFrom((Class) rawType)) {
else if (Converter.class.isAssignableFrom((Class) rawType)) {
return getConverterTypeInfo((Class) rawType); return getConverterTypeInfo((Class) rawType);
} }
} } else if (Converter.class.isAssignableFrom((Class) ifc)) {
else if (Converter.class.isAssignableFrom((Class) ifc)) {
return getConverterTypeInfo((Class) ifc); return getConverterTypeInfo((Class) ifc);
} }
} }
@ -330,8 +313,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
} }
Map<Class, GenericConverter> objectConverters = getConvertersForSource(Object.class); Map<Class, GenericConverter> objectConverters = getConvertersForSource(Object.class);
return getConverter(objectConverters, targetType); return getConverter(objectConverters, targetType);
} } else {
else {
LinkedList<Class> classQueue = new LinkedList<Class>(); LinkedList<Class> classQueue = new LinkedList<Class>();
classQueue.addFirst(sourceType); classQueue.addFirst(sourceType);
while (!classQueue.isEmpty()) { while (!classQueue.isEmpty()) {
@ -393,8 +375,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
} }
} }
return converters.get(Object.class); return converters.get(Object.class);
} } else {
else {
LinkedList<Class> classQueue = new LinkedList<Class>(); LinkedList<Class> classQueue = new LinkedList<Class>();
classQueue.addFirst(targetType); classQueue.addFirst(targetType);
while (!classQueue.isEmpty()) { while (!classQueue.isEmpty()) {
@ -408,8 +389,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
if (componentType.getSuperclass() != null) { if (componentType.getSuperclass() != null) {
classQueue.addFirst(Array.newInstance(componentType.getSuperclass(), 0).getClass()); classQueue.addFirst(Array.newInstance(componentType.getSuperclass(), 0).getClass());
} }
} } else {
else {
if (currentClass.getSuperclass() != null) { if (currentClass.getSuperclass() != null) {
classQueue.addFirst(currentClass.getSuperclass()); classQueue.addFirst(currentClass.getSuperclass());
} }
@ -423,7 +403,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
} }
} }
private static class ConverterAdapter implements GenericConverter { private static class ConverterAdapter implements GenericConverter {
private Converter converter; private Converter converter;
@ -438,7 +417,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
} }
} }
private static class ConverterFactoryAdapter implements GenericConverter { private static class ConverterFactoryAdapter implements GenericConverter {
private ConverterFactory converterFactory; private ConverterFactory converterFactory;

View File

@ -1,5 +1,7 @@
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.util.Map; import java.util.Map;
import org.springframework.core.CollectionFactory; import org.springframework.core.CollectionFactory;
@ -114,7 +116,7 @@ final class MapToMapGenericConverter implements GenericConverter {
public Object convertKey(Object sourceKey) { public Object convertKey(Object sourceKey) {
if (sourceKey != null && this.keyConverter != null) { if (sourceKey != null && this.keyConverter != null) {
return this.keyConverter.convert(sourceKey, this.sourceKeyType, this.targetKeyType); return invokeConverter(this.keyConverter, sourceKey, this.sourceKeyType, this.targetKeyType);
} else { } else {
return sourceKey; return sourceKey;
} }
@ -122,7 +124,7 @@ final class MapToMapGenericConverter implements GenericConverter {
public Object convertValue(Object sourceValue) { public Object convertValue(Object sourceValue) {
if (sourceValue != null && this.valueConverter != null) { if (sourceValue != null && this.valueConverter != null) {
return this.valueConverter.convert(sourceValue, this.sourceValueType, this.targetValueType); return invokeConverter(this.valueConverter, sourceValue, this.sourceValueType, this.targetValueType);
} else { } else {
return sourceValue; return sourceValue;
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
@ -38,7 +40,7 @@ final class ObjectToArrayGenericConverter implements GenericConverter {
if (converter == null) { if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetElementType); throw new ConverterNotFoundException(sourceType, targetElementType);
} }
Array.set(target, 0, converter.convert(source, sourceType, targetElementType)); Array.set(target, 0, invokeConverter(converter, source, sourceType, targetElementType));
} }
return target; return target;
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.core.convert.support; package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.util.Collection; import java.util.Collection;
import org.springframework.core.CollectionFactory; import org.springframework.core.CollectionFactory;
@ -39,7 +41,7 @@ final class ObjectToCollectionGenericConverter implements GenericConverter {
if (converter == null) { if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetElementType); throw new ConverterNotFoundException(sourceType, targetElementType);
} }
target.add(converter.convert(source, sourceType, targetElementType)); target.add(invokeConverter(converter, source, sourceType, targetElementType));
} }
return target; return target;
} }

View File

@ -96,7 +96,7 @@ public class GenericConversionServiceTests {
} }
@Test @Test
public void convertNullConversionPointType() { public void convertNullTypeDescriptor() {
assertEquals(null, converter.convert(3, TypeDescriptor.valueOf(String.class), TypeDescriptor.NULL)); assertEquals(null, converter.convert(3, TypeDescriptor.valueOf(String.class), TypeDescriptor.NULL));
} }
@ -304,7 +304,6 @@ public class GenericConversionServiceTests {
} }
@Test @Test
@Ignore
public void convertStringToArrayWithElementConversion() { public void convertStringToArrayWithElementConversion() {
converter.addConverterFactory(new StringToNumberConverterFactory()); converter.addConverterFactory(new StringToNumberConverterFactory());
Integer[] result = converter.convert("1,2,3", Integer[].class); Integer[] result = converter.convert("1,2,3", Integer[].class);