Skip to content

Commit

Permalink
Fixed resolving generic types for Vavr maps.
Browse files Browse the repository at this point in the history
Issue #2517.
  • Loading branch information
nexx512 authored and odrotbohm committed Feb 14, 2022
1 parent 8ebe52d commit 8d2a346
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* @author Oliver Gierke
* @author Mark Paluch
* @author Christoph Strobl
* @author Jürgen Diez
*/
class ParameterizedTypeInformation<T> extends ParentTypeAwareTypeInformation<T> {

Expand All @@ -63,7 +64,7 @@ public ParameterizedTypeInformation(ParameterizedType type, TypeDiscoverer<?> pa
@Nullable
protected TypeInformation<?> doGetMapValueType() {

if (Map.class.isAssignableFrom(getType())) {
if (isMap()) {

var arguments = type.getActualTypeArguments();

Expand Down Expand Up @@ -141,13 +142,13 @@ public boolean isAssignableFrom(TypeInformation<?> target) {
@Nullable
protected TypeInformation<?> doGetComponentType() {

var isCustomMapImplementation = isMap() && !getType().equals(Map.class);
var isCustomMapImplementation = isMap() && !isMapBaseType();

if (isCustomMapImplementation) {
return getRequiredSuperTypeInformation(Map.class).getComponentType();
return getRequiredSuperTypeInformation(getMapBaseType()).getComponentType();
}

return createInfo(type.getActualTypeArguments()[0]);
return createInfo(this.type.getActualTypeArguments()[0]);
}

@Override
Expand Down
27 changes: 24 additions & 3 deletions src/main/java/org/springframework/data/util/TypeDiscoverer.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
*/
class TypeDiscoverer<S> implements TypeInformation<S> {

private static final Class<?>[] MAP_TYPES;
protected static final Class<?>[] MAP_TYPES;
private static final Class<?>[] COLLECTION_TYPES;

static {
Expand Down Expand Up @@ -328,7 +328,7 @@ public TypeInformation<?> getMapValueType() {

@Nullable
protected TypeInformation<?> doGetMapValueType() {
return isMap() ? getTypeArgument(getBaseType(MAP_TYPES), 1)
return isMap() ? getTypeArgument(getMapBaseType(), 1)
: getTypeArguments().stream().skip(1).findFirst().orElse(null);
}

Expand Down Expand Up @@ -357,7 +357,7 @@ protected TypeInformation<?> doGetComponentType() {
}

if (isMap()) {
return getTypeArgument(getBaseType(MAP_TYPES), 0);
return getTypeArgument(getMapBaseType(), 0);
}

if (Iterable.class.isAssignableFrom(rawType)) {
Expand Down Expand Up @@ -469,6 +469,27 @@ private TypeInformation<?> getTypeArgument(Class<?> bound, int index) {
: null;
}

protected boolean isMapBaseType() {
return isBaseType(MAP_TYPES);
}

private boolean isBaseType(Class<?>[] candidates) {

Class<S> type = getType();

for (Class<?> candidate: candidates) {
if (candidate.equals(type)) {
return true;
}
}

return false;
}

protected Class<?> getMapBaseType() {
return getBaseType(MAP_TYPES);
}

private Class<?> getBaseType(Class<?>[] candidates) {

var type = getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
*
* @author Oliver Gierke
* @author Mark Paluch
* @author Jürgen Diez
*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
Expand Down Expand Up @@ -76,22 +77,39 @@ void considersTypeInformationsWithSameParentsNotEqual() {
}

@Test // DATACMNS-88
void resolvesMapValueTypeCorrectly() {
void resolvesMapTypesCorrectly() {

TypeInformation<Foo> type = ClassTypeInformation.from(Foo.class);
var propertyType = type.getProperty("param");
var value = propertyType.getProperty("value");

assertThat(propertyType.getComponentType().getType()).isEqualTo(Locale.class);
assertThat(value.getType()).isEqualTo(String.class);
assertThat(propertyType.getMapValueType().getType()).isEqualTo(String.class);

propertyType = type.getProperty("param2");
value = propertyType.getProperty("value");

assertThat(propertyType.getComponentType().getType()).isEqualTo(String.class);
assertThat(value.getType()).isEqualTo(String.class);
assertThat(propertyType.getMapValueType().getType()).isEqualTo(Locale.class);
}

@Test
void resolvesVavrMapTypesCorrectly() {

TypeInformation<VavrFoo> type = ClassTypeInformation.from(VavrFoo.class);
TypeInformation<?> propertyType = type.getProperty("param");

assertThat(propertyType.getComponentType().getType()).isEqualTo(Locale.class);
assertThat(propertyType.getMapValueType().getType()).isEqualTo(String.class);

propertyType = type.getProperty("param2");

assertThat(propertyType.getComponentType().getType()).isEqualTo(String.class);
assertThat(propertyType.getMapValueType().getType()).isEqualTo(Locale.class);
}

@Test // DATACMNS-446
void createsToStringRepresentation() {

Expand Down Expand Up @@ -170,6 +188,11 @@ class Foo {
Localized2<String> param2;
}

class VavrFoo {
io.vavr.collection.HashMap<Locale, String> param;
io.vavr.collection.HashMap<String, Locale> param2;
}

class Bar {
List<String> param;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ void considerVavrMapToBeAMap() {
assertThat(type.isMap()).isTrue();
}

@Test // #2517
void returnsComponentAndValueTypesForVavrMapExtensions() {

var discoverer = new TypeDiscoverer<>(CustomVavrMap.class, EMPTY_MAP);

assertThat(discoverer.getMapValueType().getType()).isEqualTo(Locale.class);
assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class);
}

@Test // #2511
void considerVavrSetToBeCollectionLike() {

Expand Down Expand Up @@ -260,4 +269,6 @@ public Iterator<String> iterator() {
return Collections.emptyIterator();
}
}

interface CustomVavrMap extends io.vavr.collection.Map<String, Locale> {}
}

0 comments on commit 8d2a346

Please sign in to comment.