1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.core.convert.support;
18
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.EnumMap;
22 import java.util.HashMap;
23 import java.util.LinkedHashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.junit.Before;
28 import org.junit.Test;
29
30 import org.springframework.core.convert.ConversionFailedException;
31 import org.springframework.core.convert.ConverterNotFoundException;
32 import org.springframework.core.convert.TypeDescriptor;
33 import org.springframework.util.LinkedMultiValueMap;
34 import org.springframework.util.MultiValueMap;
35
36 import static org.hamcrest.Matchers.*;
37 import static org.junit.Assert.*;
38
39 public class MapToMapConverterTests {
40
41 private GenericConversionService conversionService = new GenericConversionService();
42
43
44 @Before
45 public void setUp() {
46 conversionService.addConverter(new MapToMapConverter(conversionService));
47 }
48
49
50 @Test
51 public void scalarMap() throws Exception {
52 Map<String, String> map = new HashMap<String, String>();
53 map.put("1", "9");
54 map.put("2", "37");
55 TypeDescriptor sourceType = TypeDescriptor.forObject(map);
56 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("scalarMapTarget"));
57 assertTrue(conversionService.canConvert(sourceType, targetType));
58 try {
59 conversionService.convert(map, sourceType, targetType);
60 } catch (ConversionFailedException e) {
61 assertTrue(e.getCause() instanceof ConverterNotFoundException);
62 }
63 conversionService.addConverterFactory(new StringToNumberConverterFactory());
64 assertTrue(conversionService.canConvert(sourceType, targetType));
65 @SuppressWarnings("unchecked")
66 Map<Integer, Integer> result = (Map<Integer, Integer>) conversionService.convert(map, sourceType, targetType);
67 assertFalse(map.equals(result));
68 assertEquals((Integer) 9, result.get(1));
69 assertEquals((Integer) 37, result.get(2));
70 }
71
72 @Test
73 public void scalarMapNotGenericTarget() throws Exception {
74 Map<String, String> map = new HashMap<String, String>();
75 map.put("1", "9");
76 map.put("2", "37");
77 assertTrue(conversionService.canConvert(Map.class, Map.class));
78 assertSame(map, conversionService.convert(map, Map.class));
79 }
80
81 @Test
82 public void scalarMapNotGenericSourceField() throws Exception {
83 Map<String, String> map = new HashMap<String, String>();
84 map.put("1", "9");
85 map.put("2", "37");
86 TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("notGenericMapSource"));
87 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("scalarMapTarget"));
88 assertTrue(conversionService.canConvert(sourceType, targetType));
89 try {
90 conversionService.convert(map, sourceType, targetType);
91 } catch (ConversionFailedException e) {
92 assertTrue(e.getCause() instanceof ConverterNotFoundException);
93 }
94 conversionService.addConverterFactory(new StringToNumberConverterFactory());
95 assertTrue(conversionService.canConvert(sourceType, targetType));
96 @SuppressWarnings("unchecked")
97 Map<Integer, Integer> result = (Map<Integer, Integer>) conversionService.convert(map, sourceType, targetType);
98 assertFalse(map.equals(result));
99 assertEquals((Integer) 9, result.get(1));
100 assertEquals((Integer) 37, result.get(2));
101 }
102
103 @Test
104 public void collectionMap() throws Exception {
105 Map<String, List<String>> map = new HashMap<String, List<String>>();
106 map.put("1", Arrays.asList("9", "12"));
107 map.put("2", Arrays.asList("37", "23"));
108 TypeDescriptor sourceType = TypeDescriptor.forObject(map);
109 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("collectionMapTarget"));
110 assertTrue(conversionService.canConvert(sourceType, targetType));
111 try {
112 conversionService.convert(map, sourceType, targetType);
113 } catch (ConversionFailedException e) {
114 assertTrue(e.getCause() instanceof ConverterNotFoundException);
115 }
116 conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
117 conversionService.addConverterFactory(new StringToNumberConverterFactory());
118 assertTrue(conversionService.canConvert(sourceType, targetType));
119 @SuppressWarnings("unchecked")
120 Map<Integer, List<Integer>> result = (Map<Integer, List<Integer>>) conversionService.convert(map, sourceType, targetType);
121 assertFalse(map.equals(result));
122 assertEquals(Arrays.asList(9, 12), result.get(1));
123 assertEquals(Arrays.asList(37, 23), result.get(2));
124 }
125
126 @Test
127 public void collectionMapSourceTarget() throws Exception {
128 Map<String, List<String>> map = new HashMap<String, List<String>>();
129 map.put("1", Arrays.asList("9", "12"));
130 map.put("2", Arrays.asList("37", "23"));
131 TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("sourceCollectionMapTarget"));
132 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("collectionMapTarget"));
133 assertFalse(conversionService.canConvert(sourceType, targetType));
134 try {
135 conversionService.convert(map, sourceType, targetType);
136 fail("Should have failed");
137 }
138 catch (ConverterNotFoundException ex) {
139
140 }
141 conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
142 conversionService.addConverterFactory(new StringToNumberConverterFactory());
143 assertTrue(conversionService.canConvert(sourceType, targetType));
144 @SuppressWarnings("unchecked")
145 Map<Integer, List<Integer>> result = (Map<Integer, List<Integer>>) conversionService.convert(map, sourceType, targetType);
146 assertFalse(map.equals(result));
147 assertEquals(Arrays.asList(9, 12), result.get(1));
148 assertEquals(Arrays.asList(37, 23), result.get(2));
149 }
150
151 @Test
152 public void collectionMapNotGenericTarget() throws Exception {
153 Map<String, List<String>> map = new HashMap<String, List<String>>();
154 map.put("1", Arrays.asList("9", "12"));
155 map.put("2", Arrays.asList("37", "23"));
156 assertTrue(conversionService.canConvert(Map.class, Map.class));
157 assertSame(map, conversionService.convert(map, Map.class));
158 }
159
160 @Test
161 public void collectionMapNotGenericTargetCollectionToObjectInteraction() throws Exception {
162 Map<String, List<String>> map = new HashMap<String, List<String>>();
163 map.put("1", Arrays.asList("9", "12"));
164 map.put("2", Arrays.asList("37", "23"));
165 conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
166 conversionService.addConverter(new CollectionToObjectConverter(conversionService));
167 assertTrue(conversionService.canConvert(Map.class, Map.class));
168 assertSame(map, conversionService.convert(map, Map.class));
169 }
170
171 @Test
172 public void emptyMap() throws Exception {
173 Map<String, String> map = new HashMap<String, String>();
174 TypeDescriptor sourceType = TypeDescriptor.forObject(map);
175 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("emptyMapTarget"));
176 assertTrue(conversionService.canConvert(sourceType, targetType));
177 assertSame(map, conversionService.convert(map, sourceType, targetType));
178 }
179
180 @Test
181 public void emptyMapNoTargetGenericInfo() throws Exception {
182 Map<String, String> map = new HashMap<String, String>();
183 assertTrue(conversionService.canConvert(Map.class, Map.class));
184 assertSame(map, conversionService.convert(map, Map.class));
185 }
186
187 @Test
188 public void emptyMapDifferentTargetImplType() throws Exception {
189 Map<String, String> map = new HashMap<String, String>();
190 TypeDescriptor sourceType = TypeDescriptor.forObject(map);
191 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("emptyMapDifferentTarget"));
192 assertTrue(conversionService.canConvert(sourceType, targetType));
193 @SuppressWarnings("unchecked")
194 LinkedHashMap<String, String> result = (LinkedHashMap<String, String>) conversionService.convert(map, sourceType, targetType);
195 assertEquals(map, result);
196 assertEquals(LinkedHashMap.class, result.getClass());
197 }
198
199 @Test
200 public void noDefaultConstructorCopyNotRequired() throws Exception {
201
202 NoDefaultConstructorMap<String, Integer> map = new NoDefaultConstructorMap<String,Integer>(
203 Collections.<String, Integer> singletonMap("1", 1));
204 TypeDescriptor sourceType = TypeDescriptor.map(NoDefaultConstructorMap.class,
205 TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
206 TypeDescriptor targetType = TypeDescriptor.map(NoDefaultConstructorMap.class,
207 TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
208 assertTrue(conversionService.canConvert(sourceType, targetType));
209 @SuppressWarnings("unchecked")
210 Map<String, Integer> result = (Map<String, Integer>) conversionService.convert(map, sourceType, targetType);
211 assertEquals(map, result);
212 assertEquals(NoDefaultConstructorMap.class, result.getClass());
213 }
214
215 @Test
216 @SuppressWarnings("unchecked")
217 public void multiValueMapToMultiValueMap() throws Exception {
218 DefaultConversionService.addDefaultConverters(conversionService);
219 MultiValueMap<String, Integer> source = new LinkedMultiValueMap<String, Integer>();
220 source.put("a", Arrays.asList(1, 2, 3));
221 source.put("b", Arrays.asList(4, 5, 6));
222 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("multiValueMapTarget"));
223 MultiValueMap<String, String> converted = (MultiValueMap<String, String>) conversionService.convert(source, targetType);
224 assertThat(converted.size(), equalTo(2));
225 assertThat(converted.get("a"), equalTo(Arrays.asList("1", "2", "3")));
226 assertThat(converted.get("b"), equalTo(Arrays.asList("4", "5", "6")));
227 }
228
229 @Test
230 @SuppressWarnings("unchecked")
231 public void mapToMultiValueMap() throws Exception {
232 DefaultConversionService.addDefaultConverters(conversionService);
233 Map<String, Integer> source = new HashMap<String, Integer>();
234 source.put("a", 1);
235 source.put("b", 2);
236 TypeDescriptor targetType = new TypeDescriptor(getClass().getField("multiValueMapTarget"));
237 MultiValueMap<String, String> converted = (MultiValueMap<String, String>) conversionService.convert(source, targetType);
238 assertThat(converted.size(), equalTo(2));
239 assertThat(converted.get("a"), equalTo(Arrays.asList("1")));
240 assertThat(converted.get("b"), equalTo(Arrays.asList("2")));
241 }
242
243 @Test
244 public void testStringToEnumMap() throws Exception {
245 conversionService.addConverterFactory(new StringToEnumConverterFactory());
246 Map<String, Integer> source = new HashMap<String, Integer>();
247 source.put("A", 1);
248 source.put("C", 2);
249 EnumMap<MyEnum, Integer> result = new EnumMap<MyEnum, Integer>(MyEnum.class);
250 result.put(MyEnum.A, 1);
251 result.put(MyEnum.C, 2);
252 assertEquals(result,
253 conversionService.convert(source, TypeDescriptor.forObject(source), new TypeDescriptor(getClass().getField("enumMap"))));
254 }
255
256
257 @SuppressWarnings("serial")
258 public static class NoDefaultConstructorMap<K, V> extends HashMap<K, V> {
259
260 public NoDefaultConstructorMap(Map<? extends K, ? extends V> map) {
261 super(map);
262 }
263 }
264
265
266 public static enum MyEnum {A, B, C}
267
268
269 public Map<Integer, Integer> scalarMapTarget;
270
271 public Map<Integer, List<Integer>> collectionMapTarget;
272
273 public Map<String, List<String>> sourceCollectionMapTarget;
274
275 public Map<String, String> emptyMapTarget;
276
277 public LinkedHashMap<String, String> emptyMapDifferentTarget;
278
279 public MultiValueMap<String, String> multiValueMapTarget;
280
281 public Map notGenericMapSource;
282
283 public EnumMap<MyEnum, Integer> enumMap;
284
285 }