Skip to content

Commit af6fc2c

Browse files
odrotbohmThomas Darimont
authored andcommitted
DATACMNS-451 - Added custom CollectionFactory.
Added a Spring Data specific CollectionFactory that augments Spring's CollectionFactory with support for special collection types like EnumSet and EnumMap. For all other types we delegate to the wrapped class.
1 parent b41e337 commit af6fc2c

File tree

2 files changed

+212
-0
lines changed

2 files changed

+212
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.convert;
17+
18+
import java.util.Collection;
19+
import java.util.EnumMap;
20+
import java.util.EnumSet;
21+
import java.util.Map;
22+
23+
import org.springframework.util.Assert;
24+
25+
/**
26+
* Wrapper around Spring's {@link org.springframework.core.CollectionFactory} to add support for additional, sepcial
27+
* collection types.
28+
*
29+
* @author Oliver Gierke
30+
*/
31+
public class CollectionFactory {
32+
33+
/**
34+
* Creates a new collection instance for the given collection type. Might also inspect the element type in case
35+
* special collections are requested (e.g. {@link EnumSet}).
36+
*
37+
* @param collectionType must not be {@literal null}.
38+
* @param elementType can be {@literal null}.
39+
* @param size the initial size of the collection to be created.
40+
* @return
41+
*/
42+
@SuppressWarnings("unchecked")
43+
public static Collection<Object> createCollection(Class<?> collectionType, Class<?> elementType, int size) {
44+
45+
Assert.notNull(collectionType, "Collection type must not be null!");
46+
47+
if (EnumSet.class.equals(collectionType)) {
48+
return EnumSet.noneOf(asEnumType(elementType));
49+
}
50+
51+
return org.springframework.core.CollectionFactory.createCollection(collectionType, size);
52+
}
53+
54+
/**
55+
* Creates a new map instance for the given map type. Might also inspect the key type in case special maps are
56+
* requested (e.g. {@link EnumMap}).
57+
*
58+
* @param mapType must not be {@literal null}.
59+
* @param keyType can be {@literal null}.
60+
* @param size the initial size of the collection to be created.
61+
* @return
62+
*/
63+
@SuppressWarnings({ "unchecked", "rawtypes" })
64+
public static Map<Object, Object> createMap(Class<?> mapType, Class<?> keyType, int size) {
65+
66+
Assert.notNull(mapType, "Map type must not be null!");
67+
68+
if (EnumMap.class.isAssignableFrom(mapType)) {
69+
return new EnumMap(asEnumType(keyType));
70+
}
71+
72+
return org.springframework.core.CollectionFactory.createMap(mapType, size);
73+
}
74+
75+
/**
76+
* Returns the given type as subtype of {@link Enum}.
77+
*
78+
* @param enumType must not be {@literal null}.
79+
* @return
80+
* @throws IllegalArgumentException in case the given type is not a subtype of {@link Enum}.
81+
*/
82+
@SuppressWarnings("rawtypes")
83+
private static Class<? extends Enum> asEnumType(Class<?> enumType) {
84+
85+
Assert.notNull(enumType, "EnumType must not be null!");
86+
87+
if (!Enum.class.isAssignableFrom(enumType)) {
88+
throw new IllegalArgumentException(String.format("Given type %s is not an enum type!", enumType.getName()));
89+
}
90+
91+
return enumType.asSubclass(Enum.class);
92+
}
93+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.convert;
17+
18+
import static org.hamcrest.CoreMatchers.*;
19+
import static org.junit.Assert.*;
20+
import static org.springframework.data.convert.CollectionFactory.*;
21+
22+
import java.util.ArrayList;
23+
import java.util.EnumMap;
24+
import java.util.EnumSet;
25+
import java.util.HashSet;
26+
import java.util.List;
27+
import java.util.Set;
28+
import java.util.SortedSet;
29+
import java.util.TreeSet;
30+
31+
import org.junit.Test;
32+
import org.springframework.core.CollectionFactory;
33+
34+
/**
35+
* Unit tests for {@link CollectionFactory}.
36+
*
37+
* @author Oliver Gierke
38+
*/
39+
public class CollectionFactoryUnitTests {
40+
41+
/**
42+
* @see DATACMNS-451
43+
*/
44+
@Test
45+
public void createsSimpleCollectionsCorrectly() {
46+
47+
assertThat(createCollection(List.class, Object.class, 0), is(instanceOf(ArrayList.class)));
48+
assertThat(createCollection(Set.class, Object.class, 0), is(instanceOf(HashSet.class)));
49+
assertThat(createCollection(SortedSet.class, Object.class, 0), is(instanceOf(TreeSet.class)));
50+
}
51+
52+
/**
53+
* @see DATACMNS-451
54+
*/
55+
@Test
56+
public void createsEnumSet() {
57+
assertThat(createCollection(EnumSet.class, Color.class, 0), is(instanceOf(EnumSet.class)));
58+
}
59+
60+
/**
61+
* @see DATACMNS-451
62+
*/
63+
@Test(expected = IllegalArgumentException.class)
64+
public void rejectsInvalidElementTypeForEnumSet() {
65+
createCollection(EnumSet.class, Object.class, 0);
66+
}
67+
68+
/**
69+
* @see DATACMNS-451
70+
*/
71+
@Test(expected = IllegalArgumentException.class)
72+
public void rejectsNullElementTypeForEnumSet() {
73+
createCollection(EnumSet.class, null, 0);
74+
}
75+
76+
/**
77+
* @see DATACMNS-451
78+
*/
79+
@Test(expected = IllegalArgumentException.class)
80+
public void rejectsNullCollectionType() {
81+
createCollection(null, Object.class, 0);
82+
}
83+
84+
/**
85+
* @see DATACMNS-451
86+
*/
87+
@Test
88+
public void createsEnumMap() {
89+
assertThat(createMap(EnumMap.class, Color.class, 0), is(instanceOf(EnumMap.class)));
90+
}
91+
92+
/**
93+
* @see DATACMNS-451
94+
*/
95+
@Test(expected = IllegalArgumentException.class)
96+
public void rejectsInvalidKeyTypeForEnumMap() {
97+
createMap(EnumMap.class, Object.class, 0);
98+
}
99+
100+
/**
101+
* @see DATACMNS-451
102+
*/
103+
@Test(expected = IllegalArgumentException.class)
104+
public void rejectsNullKeyTypeForEnumMap() {
105+
createMap(EnumMap.class, null, 0);
106+
}
107+
108+
/**
109+
* @see DATACMNS-451
110+
*/
111+
@Test(expected = IllegalArgumentException.class)
112+
public void rejectsNullMapType() {
113+
createMap(null, Object.class, 0);
114+
}
115+
116+
enum Color {
117+
RED, BLUE;
118+
}
119+
}

0 commit comments

Comments
 (0)