Skip to content

Commit d832052

Browse files
nexx512odrotbohm
nexx512
authored andcommitted
Fixed resolving generic types for Vavr maps.
Issue #2517.
1 parent f933b45 commit d832052

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

src/main/java/org/springframework/data/util/ParameterizedTypeInformation.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* @author Oliver Gierke
4040
* @author Mark Paluch
4141
* @author Christoph Strobl
42+
* @author Jürgen Diez
4243
*/
4344
class ParameterizedTypeInformation<T> extends ParentTypeAwareTypeInformation<T> {
4445

@@ -67,7 +68,7 @@ public ParameterizedTypeInformation(ParameterizedType type, TypeDiscoverer<?> pa
6768
@Nullable
6869
protected TypeInformation<?> doGetMapValueType() {
6970

70-
if (Map.class.isAssignableFrom(getType())) {
71+
if (isMap()) {
7172

7273
Type[] arguments = type.getActualTypeArguments();
7374

@@ -157,13 +158,13 @@ public boolean isAssignableFrom(TypeInformation<?> target) {
157158
@Nullable
158159
protected TypeInformation<?> doGetComponentType() {
159160

160-
boolean isCustomMapImplementation = isMap() && !getType().equals(Map.class);
161+
boolean isCustomMapImplementation = isMap() && !isMapBaseType();
161162

162163
if (isCustomMapImplementation) {
163-
return getRequiredSuperTypeInformation(Map.class).getComponentType();
164+
return getRequiredSuperTypeInformation(getMapBaseType()).getComponentType();
164165
}
165166

166-
return createInfo(type.getActualTypeArguments()[0]);
167+
return createInfo(this.type.getActualTypeArguments()[0]);
167168
}
168169

169170
/*

src/main/java/org/springframework/data/util/TypeDiscoverer.java

+24-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
*/
4848
class TypeDiscoverer<S> implements TypeInformation<S> {
4949

50-
private static final Class<?>[] MAP_TYPES;
50+
protected static final Class<?>[] MAP_TYPES;
5151
private static final Class<?>[] COLLECTION_TYPES;
5252

5353
static {
@@ -361,7 +361,7 @@ public TypeInformation<?> getMapValueType() {
361361

362362
@Nullable
363363
protected TypeInformation<?> doGetMapValueType() {
364-
return isMap() ? getTypeArgument(getBaseType(MAP_TYPES), 1)
364+
return isMap() ? getTypeArgument(getMapBaseType(), 1)
365365
: getTypeArguments().stream().skip(1).findFirst().orElse(null);
366366
}
367367

@@ -398,7 +398,7 @@ protected TypeInformation<?> doGetComponentType() {
398398
}
399399

400400
if (isMap()) {
401-
return getTypeArgument(getBaseType(MAP_TYPES), 0);
401+
return getTypeArgument(getMapBaseType(), 0);
402402
}
403403

404404
if (Iterable.class.isAssignableFrom(rawType)) {
@@ -533,6 +533,27 @@ private TypeInformation<?> getTypeArgument(Class<?> bound, int index) {
533533
: null;
534534
}
535535

536+
protected boolean isMapBaseType() {
537+
return isBaseType(MAP_TYPES);
538+
}
539+
540+
private boolean isBaseType(Class<?>[] candidates) {
541+
542+
Class<S> type = getType();
543+
544+
for (Class<?> candidate: candidates) {
545+
if (candidate.equals(type)) {
546+
return true;
547+
}
548+
}
549+
550+
return false;
551+
}
552+
553+
protected Class<?> getMapBaseType() {
554+
return getBaseType(MAP_TYPES);
555+
}
556+
536557
private Class<?> getBaseType(Class<?>[] candidates) {
537558

538559
Class<S> type = getType();

src/test/java/org/springframework/data/util/ParameterizedTypeInformationUnitTests.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*
4141
* @author Oliver Gierke
4242
* @author Mark Paluch
43+
* @author Jürgen Diez
4344
*/
4445
@ExtendWith(MockitoExtension.class)
4546
@MockitoSettings(strictness = Strictness.LENIENT)
@@ -76,22 +77,39 @@ void considersTypeInformationsWithSameParentsNotEqual() {
7677
}
7778

7879
@Test // DATACMNS-88
79-
void resolvesMapValueTypeCorrectly() {
80+
void resolvesMapTypesCorrectly() {
8081

8182
TypeInformation<Foo> type = ClassTypeInformation.from(Foo.class);
8283
TypeInformation<?> propertyType = type.getProperty("param");
8384
TypeInformation<?> value = propertyType.getProperty("value");
8485

86+
assertThat(propertyType.getComponentType().getType()).isEqualTo(Locale.class);
8587
assertThat(value.getType()).isEqualTo(String.class);
8688
assertThat(propertyType.getMapValueType().getType()).isEqualTo(String.class);
8789

8890
propertyType = type.getProperty("param2");
8991
value = propertyType.getProperty("value");
9092

93+
assertThat(propertyType.getComponentType().getType()).isEqualTo(String.class);
9194
assertThat(value.getType()).isEqualTo(String.class);
9295
assertThat(propertyType.getMapValueType().getType()).isEqualTo(Locale.class);
9396
}
9497

98+
@Test
99+
void resolvesVavrMapTypesCorrectly() {
100+
101+
TypeInformation<VavrFoo> type = ClassTypeInformation.from(VavrFoo.class);
102+
TypeInformation<?> propertyType = type.getProperty("param");
103+
104+
assertThat(propertyType.getComponentType().getType()).isEqualTo(Locale.class);
105+
assertThat(propertyType.getMapValueType().getType()).isEqualTo(String.class);
106+
107+
propertyType = type.getProperty("param2");
108+
109+
assertThat(propertyType.getComponentType().getType()).isEqualTo(String.class);
110+
assertThat(propertyType.getMapValueType().getType()).isEqualTo(Locale.class);
111+
}
112+
95113
@Test // DATACMNS-446
96114
void createsToStringRepresentation() {
97115

@@ -170,6 +188,11 @@ class Foo {
170188
Localized2<String> param2;
171189
}
172190

191+
class VavrFoo {
192+
io.vavr.collection.HashMap<Locale, String> param;
193+
io.vavr.collection.HashMap<String, Locale> param2;
194+
}
195+
173196
class Bar {
174197
List<String> param;
175198
}

src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java

+11
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,15 @@ void considerVavrMapToBeAMap() {
188188
assertThat(type.isMap()).isTrue();
189189
}
190190

191+
@Test // #2517
192+
void returnsComponentAndValueTypesForVavrMapExtensions() {
193+
194+
TypeInformation<?> discoverer = new TypeDiscoverer<>(CustomVavrMap.class, EMPTY_MAP);
195+
196+
assertThat(discoverer.getMapValueType().getType()).isEqualTo(Locale.class);
197+
assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class);
198+
}
199+
191200
@Test
192201
void considerVavrSetToBeCollectionLike() {
193202

@@ -261,4 +270,6 @@ public Iterator<String> iterator() {
261270
return Collections.emptyIterator();
262271
}
263272
}
273+
274+
interface CustomVavrMap extends io.vavr.collection.Map<String, Locale> {}
264275
}

0 commit comments

Comments
 (0)