Support for MultiValueMap in MapToMapConverter

Refactor TypeDescriptor to use ResolvableType in order to retain full
generic type information, in the process fixing MultiValueMap support
in MapToMapConverter.

Issue: SPR-9499
This commit is contained in:
Phillip Webb
2013-10-17 13:10:03 -07:00
parent f29092db23
commit 57a36f3f56
8 changed files with 322 additions and 721 deletions

View File

@@ -32,14 +32,20 @@ import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* Tests for {@link TypeDescriptor}.
*
* @author Keith Donald
* @author Andy Clement
* @author Phillip Webb
@@ -105,7 +111,7 @@ public class TypeDescriptorTests {
assertEquals(List.class, desc.getType());
assertEquals(List.class, desc.getObjectType());
assertEquals("java.util.List", desc.getName());
assertEquals("java.util.List<java.util.List<java.util.Map<java.lang.Integer, java.lang.Enum>>>", desc.toString());
assertEquals("java.util.List<java.util.List<java.util.Map<java.lang.Integer, java.lang.Enum<?>>>>", desc.toString());
assertTrue(!desc.isPrimitive());
assertEquals(0, desc.getAnnotations().length);
assertTrue(desc.isCollection());
@@ -435,7 +441,7 @@ public class TypeDescriptorTests {
assertTrue(typeDescriptor.isArray());
assertEquals(List.class,typeDescriptor.getElementTypeDescriptor().getType());
assertEquals(String.class, typeDescriptor.getElementTypeDescriptor().getElementTypeDescriptor().getType());
assertEquals("java.util.List[]",typeDescriptor.toString());
assertEquals("java.util.List<java.lang.String>[]",typeDescriptor.toString());
}
@Test
@@ -812,6 +818,31 @@ public class TypeDescriptorTests {
public Map<CharSequence, Number> isAssignableMapKeyValueTypes;
@Test
public void multiValueMap() throws Exception {
TypeDescriptor td = new TypeDescriptor(getClass().getField("multiValueMap"));
assertTrue(td.isMap());
assertEquals(String.class, td.getMapKeyTypeDescriptor().getType());
assertEquals(List.class, td.getMapValueTypeDescriptor().getType());
assertEquals(Integer.class,
td.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
}
public MultiValueMap<String, Integer> multiValueMap = new LinkedMultiValueMap<String, Integer>();
@Test
public void passDownGeneric() throws Exception {
TypeDescriptor td = new TypeDescriptor(getClass().getField("passDownGeneric"));
assertEquals(List.class, td.getElementTypeDescriptor().getType());
assertEquals(Set.class, td.getElementTypeDescriptor().getElementTypeDescriptor().getType());
assertEquals(Integer.class, td.getElementTypeDescriptor().getElementTypeDescriptor().getElementTypeDescriptor().getType());
}
public PassDownGeneric<Integer> passDownGeneric = new PassDownGeneric<Integer>();
public static class PassDownGeneric<T> extends ArrayList<List<Set<T>>> {
}
@Test
public void testUpCast() throws Exception {
Property property = new Property(getClass(), getClass().getMethod("getProperty"),

View File

@@ -25,11 +25,13 @@ import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MapToMapConverterTests {
@@ -217,6 +219,36 @@ public class MapToMapConverterTests {
assertEquals(NoDefaultConstructorMap.class, result.getClass());
}
public MultiValueMap<String, String> multiValueMapTarget;
@Test
@SuppressWarnings("unchecked")
public void multiValueMapToMultiValueMap() throws Exception {
DefaultConversionService.addDefaultConverters(conversionService);
MultiValueMap<String, Integer> source = new LinkedMultiValueMap<String, Integer>();
source.put("a", Arrays.asList(1, 2, 3));
source.put("b", Arrays.asList(4, 5, 6));
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("multiValueMapTarget"));
MultiValueMap<String, String> converted = (MultiValueMap<String, String>) conversionService.convert(source, targetType);
assertThat(converted.size(), equalTo(2));
assertThat(converted.get("a"), equalTo(Arrays.asList("1", "2", "3")));
assertThat(converted.get("b"), equalTo(Arrays.asList("4", "5", "6")));
}
@Test
@SuppressWarnings("unchecked")
public void mapToMultiValueMap() throws Exception {
DefaultConversionService.addDefaultConverters(conversionService);
Map<String, Integer> source = new HashMap<String, Integer>();
source.put("a", 1);
source.put("b", 2);
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("multiValueMapTarget"));
MultiValueMap<String, String> converted = (MultiValueMap<String, String>) conversionService.convert(source, targetType);
assertThat(converted.size(), equalTo(2));
assertThat(converted.get("a"), equalTo(Arrays.asList("1")));
assertThat(converted.get("b"), equalTo(Arrays.asList("2")));
}
@SuppressWarnings("serial")
public static class NoDefaultConstructorMap<K, V> extends HashMap<K, V> {
public NoDefaultConstructorMap(Map<? extends K, ? extends V> m) {