map to map generic converter
This commit is contained in:
parent
ac6e26388f
commit
8e800f0322
|
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue