提交 8e800f03 编写于 作者: K Keith Donald

map to map generic converter

上级 ac6e2638
......@@ -38,42 +38,41 @@ class CollectionToCollectionGenericConverter implements GenericConverter {
public Object convert(Object source, TypeDescriptor targetType) {
Collection sourceCollection = (Collection) source;
Object firstNotNullElement = getFirstNotNullElement(sourceCollection);
if (firstNotNullElement == null) {
Class targetElementType = targetType.getElementType();
if (targetElementType == null) {
return compatibleCollectionWithoutElementConversion(sourceCollection, targetType);
}
Class targetElementType = targetType.getElementType();
if (targetElementType == null || targetElementType.isAssignableFrom(firstNotNullElement.getClass())) {
Class sourceElementType = getElementType(sourceCollection);
if (sourceElementType == null || targetElementType.isAssignableFrom(sourceElementType)) {
return compatibleCollectionWithoutElementConversion(sourceCollection, targetType);
}
Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
GenericConverter elementConverter = conversionService.getConverter(firstNotNullElement.getClass(),
TypeDescriptor.valueOf(targetElementType));
TypeDescriptor targetElementTypeDescriptor = TypeDescriptor.valueOf(targetElementType);
GenericConverter elementConverter = conversionService.getConverter(sourceElementType,
targetElementTypeDescriptor);
for (Object element : sourceCollection) {
targetCollection.add(elementConverter.convert(element, TypeDescriptor.valueOf(targetElementType)));
targetCollection.add(elementConverter.convert(element, targetElementTypeDescriptor));
}
return targetCollection;
}
private Class getElementType(Collection collection) {
for (Object element : collection) {
if (element != null) {
return element.getClass();
}
}
return null;
}
private Collection compatibleCollectionWithoutElementConversion(Collection source, TypeDescriptor targetType) {
if (targetType.getType().isAssignableFrom(source.getClass())) {
return source;
} else {
Collection target = CollectionFactory.createCollection(targetType.getType(), source.size());
for (Object element : source) {
target.addAll(source);
}
target.addAll(source);
return target;
}
}
private Object getFirstNotNullElement(Collection collection) {
for (Object element : collection) {
if (element != null) {
return element;
}
}
return null;
}
}
......@@ -58,6 +58,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
public GenericConversionService() {
addGenericConverter(Collection.class, Collection.class, new CollectionToCollectionGenericConverter(this));
addGenericConverter(Map.class, Map.class, new MapToMapGenericConverter(this));
}
/**
......
package org.springframework.core.convert.support;
import java.util.Map;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.TypeDescriptor;
class MapToMapGenericConverter implements GenericConverter {
private GenericConversionService conversionService;
public MapToMapGenericConverter(GenericConversionService conversionService) {
this.conversionService = conversionService;
}
public Object convert(Object source, TypeDescriptor targetType) {
Map sourceMap = (Map) source;
Class targetKeyType = targetType.getMapKeyType();
Class targetValueType = targetType.getMapValueType();
if (targetKeyType == null && targetValueType == null) {
return compatibleMapWithoutEntryConversion(sourceMap, targetType);
}
Class[] sourceEntryTypes = getMapEntryTypes(sourceMap);
Class sourceKeyType = sourceEntryTypes[0];
Class sourceValueType = sourceEntryTypes[1];
if (sourceKeyType == null && sourceValueType == null) {
return compatibleMapWithoutEntryConversion(sourceMap, targetType);
}
boolean keysCompatible = false;
if (targetKeyType != null && sourceKeyType != null && targetKeyType.isAssignableFrom(sourceKeyType)) {
keysCompatible = true;
}
boolean valuesCompatible = false;
if (targetValueType != null && sourceValueType != null && targetValueType.isAssignableFrom(sourceValueType)) {
valuesCompatible = true;
}
if (keysCompatible && valuesCompatible) {
return compatibleMapWithoutEntryConversion(sourceMap, targetType);
}
Map targetMap = CollectionFactory.createMap(targetType.getType(), sourceMap.size());
MapEntryConverter converter = new MapEntryConverter(sourceKeyType, sourceValueType, targetKeyType, targetValueType, keysCompatible, valuesCompatible, conversionService);
for (Object entry : sourceMap.entrySet()) {
Map.Entry sourceMapEntry = (Map.Entry) entry;
targetMap.put(converter.convertKey(sourceMapEntry.getKey()), converter.convertValue(sourceMapEntry.getValue()));
}
return targetMap;
}
private Class[] getMapEntryTypes(Map sourceMap) {
Class keyType = null;
Class valueType = null;
for (Object entry : sourceMap.entrySet()) {
Map.Entry mapEntry = (Map.Entry) entry;
Object key = mapEntry.getKey();
if (keyType == null && key != null) {
keyType = key.getClass();
}
Object value = mapEntry.getValue();
if (valueType == null && value != null) {
valueType = value.getClass();
}
if (mapEntry.getKey() != null && mapEntry.getValue() != null) {
break;
}
}
return new Class[] { keyType, valueType };
}
private Map compatibleMapWithoutEntryConversion(Map source, TypeDescriptor targetType) {
if (targetType.getType().isAssignableFrom(source.getClass())) {
return source;
} else {
Map target = CollectionFactory.createMap(targetType.getType(), source.size());
target.putAll(source);
return target;
}
}
private static class MapEntryConverter {
private GenericConverter keyConverter;
private GenericConverter valueConverter;
private TypeDescriptor targetKeyTypeDescriptor;
private TypeDescriptor targetValueTypeDescriptor;
public MapEntryConverter(Class sourceKeyType, Class sourceValueType, Class targetKeyType,
Class targetValueType, boolean keysCompatible, boolean valuesCompatible,
GenericConversionService conversionService) {
if (sourceKeyType != null && targetKeyType != null && !keysCompatible) {
this.targetKeyTypeDescriptor = TypeDescriptor.valueOf(targetKeyType);
this.keyConverter = conversionService.getConverter(sourceKeyType, targetKeyTypeDescriptor);
}
if (sourceValueType != null && targetValueType != null && !valuesCompatible) {
this.targetValueTypeDescriptor = TypeDescriptor.valueOf(targetValueType);
this.valueConverter = conversionService.getConverter(sourceValueType, targetValueTypeDescriptor);
}
}
public Object convertKey(Object sourceKey) {
if (sourceKey != null && this.keyConverter != null) {
return this.keyConverter.convert(sourceKey, targetKeyTypeDescriptor);
} else {
return sourceKey;
}
}
public Object convertValue(Object sourceValue) {
if (sourceValue != null && this.valueConverter != null) {
return this.valueConverter.convert(sourceValue, targetValueTypeDescriptor);
} else {
return sourceValue;
}
}
}
}
......@@ -230,7 +230,6 @@ public class GenericConversionServiceTests {
public Map<Integer, FooEnum> genericMap = new HashMap<Integer, FooEnum>();
@Test
@Ignore
public void convertMapToMap() throws Exception {
Map<String, String> foo = new HashMap<String, String>();
foo.put("1", "BAR");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册