Default conversion support for EnumSet / EnumMap

Issue: SPR-12483
This commit is contained in:
Juergen Hoeller
2014-11-28 20:30:46 +01:00
parent 717b2af50f
commit fef4cd0ed6
9 changed files with 316 additions and 198 deletions

View File

@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
@@ -199,7 +200,7 @@ public class CollectionToCollectionConverterTests {
public void listToCollectionNoCopyRequired() throws NoSuchFieldException {
List<?> input = new ArrayList<String>(Arrays.asList("foo", "bar"));
assertSame(input, conversionService.convert(input, TypeDescriptor.forObject(input),
new TypeDescriptor(getClass().getField("wildCardCollection"))));
new TypeDescriptor(getClass().getField("wildcardCollection"))));
}
@Test
@@ -232,7 +233,7 @@ public class CollectionToCollectionConverterTests {
assertSame(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
}
@Test(expected=ConverterNotFoundException.class)
@Test(expected = ConverterNotFoundException.class)
public void elementTypesNotConvertible() throws Exception {
List<String> resources = new ArrayList<String>();
resources.add(null);
@@ -241,7 +242,7 @@ public class CollectionToCollectionConverterTests {
assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
}
@Test(expected=ConversionFailedException.class)
@Test(expected = ConversionFailedException.class)
public void nothingInCommon() throws Exception {
List<Object> resources = new ArrayList<Object>();
resources.add(new ClassPathResource("test"));
@@ -250,22 +251,15 @@ public class CollectionToCollectionConverterTests {
assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
}
public ArrayList<Integer> scalarListTarget;
public List<Integer> emptyListTarget;
public LinkedList<Integer> emptyListDifferentTarget;
public List<List<List<Integer>>> objectToCollection;
public List<String> strings;
public List list = Collections.emptyList();
public Collection<?> wildCardCollection = Collections.emptyList();
public List<Resource> resources;
@Test
public void testStringToEnumSet() throws Exception {
conversionService.addConverterFactory(new StringToEnumConverterFactory());
List<String> list = new ArrayList<String>();
list.add("A");
list.add("C");
assertEquals(EnumSet.of(MyEnum.A, MyEnum.C),
conversionService.convert(list, TypeDescriptor.forObject(list), new TypeDescriptor(getClass().getField("enumSet"))));
}
public static abstract class BaseResource implements Resource {
@@ -335,4 +329,26 @@ public class CollectionToCollectionConverterTests {
public static class TestResource extends BaseResource {
}
public static enum MyEnum {A, B, C}
public ArrayList<Integer> scalarListTarget;
public List<Integer> emptyListTarget;
public LinkedList<Integer> emptyListDifferentTarget;
public List<List<List<Integer>>> objectToCollection;
public List<String> strings;
public List list = Collections.emptyList();
public Collection<?> wildcardCollection = Collections.emptyList();
public List<Resource> resources;
public EnumSet<MyEnum> enumSet;
}

View File

@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -445,8 +446,6 @@ public class GenericConversionServiceTests {
System.out.println(watch.prettyPrint());
}
public static List<Integer> list;
@Test
public void testPerformance3() throws Exception {
Assume.group(TestGroup.PERFORMANCE);
@@ -473,8 +472,6 @@ public class GenericConversionServiceTests {
System.out.println(watch.prettyPrint());
}
public static Map<String, Integer> map;
@Test
public void emptyListToArray() {
conversionService.addConverter(new CollectionToArrayConverter(conversionService));
@@ -483,7 +480,7 @@ public class GenericConversionServiceTests {
TypeDescriptor sourceType = TypeDescriptor.forObject(list);
TypeDescriptor targetType = TypeDescriptor.valueOf(String[].class);
assertTrue(conversionService.canConvert(sourceType, targetType));
assertEquals(0, ((String[])conversionService.convert(list, sourceType, targetType)).length);
assertEquals(0, ((String[]) conversionService.convert(list, sourceType, targetType)).length);
}
@Test
@@ -497,82 +494,6 @@ public class GenericConversionServiceTests {
assertNull(conversionService.convert(list, sourceType, targetType));
}
private interface MyBaseInterface {
}
private interface MyInterface extends MyBaseInterface {
}
private static class MyInterfaceImplementer implements MyInterface {
}
private static class MyBaseInterfaceConverter implements Converter<MyBaseInterface, String> {
@Override
public String convert(MyBaseInterface source) {
return "RESULT";
}
}
private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> {
@Override
public Resource[] convert(String[] source) {
Resource[] result = new Resource[source.length];
for (int i = 0; i < source.length; i++) {
result[i] = new DescriptiveResource(source[i].substring(1));
}
return result;
}
}
private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> {
@Override
public Integer[] convert(String[] source) {
Integer[] result = new Integer[source.length];
for (int i = 0; i < source.length; i++) {
result[i] = Integer.parseInt(source[i].substring(1));
}
return result;
}
}
private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> {
@Override
public Integer[] convert(String source) {
String[] srcArray = StringUtils.commaDelimitedListToStringArray(source);
Integer[] result = new Integer[srcArray.length];
for (int i = 0; i < srcArray.length; i++) {
result[i] = Integer.parseInt(srcArray[i].substring(1));
}
return result;
}
}
public static class WithCopyConstructor {
public WithCopyConstructor() {
}
public WithCopyConstructor(WithCopyConstructor value) {
}
}
public static Map<String, ?> wildcardMap;
@Test
public void stringToArrayCanConvert() {
conversionService.addConverter(new StringToArrayConverter(conversionService));
@@ -585,14 +506,12 @@ public class GenericConversionServiceTests {
public void stringToCollectionCanConvert() throws Exception {
conversionService.addConverter(new StringToCollectionConverter(conversionService));
assertTrue(conversionService.canConvert(String.class, Collection.class));
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("stringToCollection"));
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("integerCollection"));
assertFalse(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
conversionService.addConverterFactory(new StringToNumberConverterFactory());
assertTrue(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
}
public Collection<Integer> stringToCollection;
@Test
public void testConvertiblePairsInSet() {
Set<GenericConverter.ConvertiblePair> set = new HashSet<GenericConverter.ConvertiblePair>();
@@ -781,6 +700,13 @@ public class GenericConversionServiceTests {
assertEquals(MyEnum.A, conversionService.convert("base1", MyEnum.class));
}
@Test
public void testStringToEnumSet() throws Exception {
DefaultConversionService.addDefaultConverters(conversionService);
assertEquals(EnumSet.of(MyEnum.A),
conversionService.convert("A", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("enumSet"))));
}
@Test
public void convertNullAnnotatedStringToString() throws Exception {
DefaultConversionService.addDefaultConverters(conversionService);
@@ -870,15 +796,80 @@ public class GenericConversionServiceTests {
}
@ExampleAnnotation
public String annotatedString;
@Retention(RetentionPolicy.RUNTIME)
public static @interface ExampleAnnotation {
}
private interface MyBaseInterface {
}
private interface MyInterface extends MyBaseInterface {
}
private static class MyInterfaceImplementer implements MyInterface {
}
private static class MyBaseInterfaceConverter implements Converter<MyBaseInterface, String> {
@Override
public String convert(MyBaseInterface source) {
return "RESULT";
}
}
private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> {
@Override
public Resource[] convert(String[] source) {
Resource[] result = new Resource[source.length];
for (int i = 0; i < source.length; i++) {
result[i] = new DescriptiveResource(source[i].substring(1));
}
return result;
}
}
private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> {
@Override
public Integer[] convert(String[] source) {
Integer[] result = new Integer[source.length];
for (int i = 0; i < source.length; i++) {
result[i] = Integer.parseInt(source[i].substring(1));
}
return result;
}
}
private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> {
@Override
public Integer[] convert(String source) {
String[] srcArray = StringUtils.commaDelimitedListToStringArray(source);
Integer[] result = new Integer[srcArray.length];
for (int i = 0; i < srcArray.length; i++) {
result[i] = Integer.parseInt(srcArray[i].substring(1));
}
return result;
}
}
public static class WithCopyConstructor {
public WithCopyConstructor() {
}
public WithCopyConstructor(WithCopyConstructor value) {
}
}
private static class MyConditionalConverter implements Converter<String, Color>, ConditionalConverter {
private int matchAttempts = 0;
@@ -1062,6 +1053,7 @@ public class GenericConversionServiceTests {
}
private static class StringToMyEnumBaseInterfaceConverter<T extends Enum<?> & MyEnumBaseInterface> implements Converter<String, T> {
private final Class<T> enumType;
public StringToMyEnumBaseInterfaceConverter(Class<T> enumType) {
@@ -1098,6 +1090,17 @@ public class GenericConversionServiceTests {
}
@ExampleAnnotation
public String annotatedString;
public List<Integer> list;
public Map<String, Integer> map;
public Map<String, ?> wildcardMap;
public EnumSet<MyEnum> enumSet;
public Collection rawCollection;
public Collection<?> genericCollection;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -39,11 +40,13 @@ public class MapToMapConverterTests {
private GenericConversionService conversionService = new GenericConversionService();
@Before
public void setUp() {
conversionService.addConverter(new MapToMapConverter(conversionService));
}
@Test
public void scalarMap() throws Exception {
Map<String, String> map = new HashMap<String, String>();
@@ -66,8 +69,6 @@ public class MapToMapConverterTests {
assertEquals((Integer) 37, result.get(2));
}
public Map<Integer, Integer> scalarMapTarget;
@Test
public void scalarMapNotGenericTarget() throws Exception {
Map<String, String> map = new HashMap<String, String>();
@@ -99,8 +100,6 @@ public class MapToMapConverterTests {
assertEquals((Integer) 37, result.get(2));
}
public Map notGenericMapSource;
@Test
public void collectionMap() throws Exception {
Map<String, List<String>> map = new HashMap<String, List<String>>();
@@ -124,8 +123,6 @@ public class MapToMapConverterTests {
assertEquals(Arrays.asList(37, 23), result.get(2));
}
public Map<Integer, List<Integer>> collectionMapTarget;
@Test
public void collectionMapSourceTarget() throws Exception {
Map<String, List<String>> map = new HashMap<String, List<String>>();
@@ -137,8 +134,9 @@ public class MapToMapConverterTests {
try {
conversionService.convert(map, sourceType, targetType);
fail("Should have failed");
} catch (ConverterNotFoundException e) {
}
catch (ConverterNotFoundException ex) {
// expected
}
conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
conversionService.addConverterFactory(new StringToNumberConverterFactory());
@@ -150,8 +148,6 @@ public class MapToMapConverterTests {
assertEquals(Arrays.asList(37, 23), result.get(2));
}
public Map<String, List<String>> sourceCollectionMapTarget;
@Test
public void collectionMapNotGenericTarget() throws Exception {
Map<String, List<String>> map = new HashMap<String, List<String>>();
@@ -181,8 +177,6 @@ public class MapToMapConverterTests {
assertSame(map, conversionService.convert(map, sourceType, targetType));
}
public Map<String, String> emptyMapTarget;
@Test
public void emptyMapNoTargetGenericInfo() throws Exception {
Map<String, String> map = new HashMap<String, String>();
@@ -202,8 +196,6 @@ public class MapToMapConverterTests {
assertEquals(LinkedHashMap.class, result.getClass());
}
public LinkedHashMap<String, String> emptyMapDifferentTarget;
@Test
public void noDefaultConstructorCopyNotRequired() throws Exception {
// SPR-9284
@@ -220,8 +212,6 @@ public class MapToMapConverterTests {
assertEquals(NoDefaultConstructorMap.class, result.getClass());
}
public MultiValueMap<String, String> multiValueMapTarget;
@Test
@SuppressWarnings("unchecked")
public void multiValueMapToMultiValueMap() throws Exception {
@@ -250,11 +240,46 @@ public class MapToMapConverterTests {
assertThat(converted.get("b"), equalTo(Arrays.asList("2")));
}
@Test
public void testStringToEnumMap() throws Exception {
conversionService.addConverterFactory(new StringToEnumConverterFactory());
Map<String, Integer> source = new HashMap<String, Integer>();
source.put("A", 1);
source.put("C", 2);
EnumMap<MyEnum, Integer> result = new EnumMap<MyEnum, Integer>(MyEnum.class);
result.put(MyEnum.A, 1);
result.put(MyEnum.C, 2);
assertEquals(result,
conversionService.convert(source, TypeDescriptor.forObject(source), new TypeDescriptor(getClass().getField("enumMap"))));
}
@SuppressWarnings("serial")
public static class NoDefaultConstructorMap<K, V> extends HashMap<K, V> {
public NoDefaultConstructorMap(Map<? extends K, ? extends V> m) {
super(m);
public NoDefaultConstructorMap(Map<? extends K, ? extends V> map) {
super(map);
}
}
public static enum MyEnum {A, B, C}
public Map<Integer, Integer> scalarMapTarget;
public Map<Integer, List<Integer>> collectionMapTarget;
public Map<String, List<String>> sourceCollectionMapTarget;
public Map<String, String> emptyMapTarget;
public LinkedHashMap<String, String> emptyMapDifferentTarget;
public MultiValueMap<String, String> multiValueMapTarget;
public Map notGenericMapSource;
public EnumMap<MyEnum, Integer> enumMap;
}