Skip to content

Commit 9fddd40

Browse files
committed
DATACMNS-1828 - Fix Map component type lookup for custom Map implementations.
Instead of using the first generic type parameter of a parameterized type as Map component type, we now explicitly lookup the super type's Map-specific generics configuration and use its first generic type parameter. The same for collection like types falling back to the parameter type bound to Iterable.
1 parent 98d61d6 commit 9fddd40

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,17 @@ public boolean isAssignableFrom(TypeInformation<?> target) {
156156
@Override
157157
@Nullable
158158
protected TypeInformation<?> doGetComponentType() {
159+
160+
boolean isCustomMapImplementation = isMap() && !getType().equals(Map.class);
161+
162+
if (isCustomMapImplementation) {
163+
return getRequiredSuperTypeInformation(Map.class).getComponentType();
164+
}
165+
166+
if (isCollectionLike() && !getType().getPackage().getName().startsWith("java.")) {
167+
return getRequiredSuperTypeInformation(Iterable.class).getComponentType();
168+
}
169+
159170
return createInfo(type.getActualTypeArguments()[0]);
160171
}
161172

src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ void unwrapsPages() throws Exception {
264264
Method method = Sample.class.getMethod("pages");
265265
TypeInformation<Object> returnType = ClassTypeInformation.fromReturnTypeOf(method);
266266

267-
assertThat(QueryExecutionConverters.unwrapWrapperTypes(returnType))
268-
.isEqualTo(ClassTypeInformation.from(String.class));
267+
assertThat(QueryExecutionConverters.unwrapWrapperTypes(returnType).getType())
268+
.isEqualTo(String.class);
269269
}
270270

271271
@Test // DATACMNS-983

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,32 @@ public void mergesGenericsFromContextAndProvidedDefaultOnSpecialization() {
443443
assertThat(specialized.getProperty("root").getType()).isEqualTo(Aggregate.class);
444444
}
445445

446+
@Test // DATACMNS-1828
447+
void discoversMapKeyAndValueTypeFromTypedMap() {
448+
449+
TypeInformation<TypeWithTypedMap> information = from(TypeWithTypedMap.class);
450+
451+
TypeInformation<?> typedMap = information.getProperty("typedMap");
452+
453+
assertThat(typedMap.getType()).isEqualTo(StringKeyMap.class);
454+
assertThat(typedMap.isMap()).isTrue();
455+
assertThat(typedMap.getRequiredComponentType().getType()).isEqualTo(String.class);
456+
assertThat(typedMap.getMapValueType().getType()).isEqualTo(Long.class);
457+
458+
TypeInformation<?> longMultiValueMap = information.getProperty("longMultiValueMap");
459+
460+
assertThat(longMultiValueMap.getType()).isEqualTo(MultiValueMap.class);
461+
assertThat(longMultiValueMap.getRequiredComponentType().getType()).isEqualTo(String.class);
462+
assertThat(longMultiValueMap.getMapValueType().getType()).isEqualTo(List.class);
463+
assertThat(longMultiValueMap.getMapValueType().getRequiredActualType().getType()).isEqualTo(Long.class);
464+
465+
TypeInformation<?> justMap = information.getProperty("justMap");
466+
467+
assertThat(justMap.getType()).isEqualTo(Map.class);
468+
assertThat(justMap.getRequiredComponentType().getType()).isEqualTo(String.class);
469+
assertThat(justMap.getMapValueType().getType()).isEqualTo(Long.class);
470+
}
471+
446472
static class StringMapContainer extends MapContainer<String> {
447473

448474
}
@@ -681,4 +707,15 @@ static class OfferCreated extends DomainEvent<OfferDetails, Long> {}
681707

682708
// A domain type partially binding generics
683709
static class GenericEvent<T extends Aggregate> extends DomainEvent<T, Long> {}
710+
711+
// DATACMNS-1828
712+
interface StringKeyMap<T> extends Map<String, T> {}
713+
714+
interface MultiValueMap<T> extends Map<String, List<T>> {}
715+
716+
static class TypeWithTypedMap {
717+
StringKeyMap<Long> typedMap;
718+
MultiValueMap<Long> longMultiValueMap;
719+
Map<String, Long> justMap;
720+
}
684721
}

0 commit comments

Comments
 (0)