diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/util/TypeDiscoverer.java b/spring-data-commons-core/src/main/java/org/springframework/data/util/TypeDiscoverer.java index dd0573aa8..e8b4d0ac4 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/util/TypeDiscoverer.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/util/TypeDiscoverer.java @@ -25,6 +25,7 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -101,6 +102,22 @@ class TypeDiscoverer implements TypeInformation { if (fieldType instanceof GenericArrayType) { return new GenericArrayTypeInformation((GenericArrayType) fieldType, this); } + + if (fieldType instanceof WildcardType) { + + WildcardType wildcardType = (WildcardType) fieldType; + Type[] bounds = wildcardType.getLowerBounds(); + + if (bounds.length > 0) { + return createInfo(bounds[0]); + } + + bounds = wildcardType.getUpperBounds(); + + if (bounds.length > 0) { + return createInfo(bounds[0]); + } + } throw new IllegalArgumentException(); } diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java index 20348515c..b57415412 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java @@ -157,7 +157,27 @@ public class ClassTypeInformationUnitTests { TypeInformation info = ClassTypeInformation.from(PropertyGetter.class); assertThat(ClassTypeInformation.from(PropertyGetter.class), is(sameInstance(info))); } - + + /** + * @see DATACMNS-39 + */ + @Test + public void resolvesWildCardTypeCorrectly() { + + TypeInformation information = ClassTypeInformation.from(ClassWithWildCardBound.class); + + TypeInformation property = information.getProperty("wildcard"); + assertThat(property.isCollectionLike(), is(true)); + assertThat(property.getComponentType().getType(), is(typeCompatibleWith(String.class))); + + property = information.getProperty("complexWildcard"); + assertThat(property.isCollectionLike(), is(true)); + + TypeInformation component = property.getComponentType(); + assertThat(component.isCollectionLike(), is(true)); + assertThat(component.getComponentType().getType(), is(typeCompatibleWith(String.class))); + } + static class StringMapContainer extends MapContainer { } @@ -231,4 +251,9 @@ public class ClassTypeInformationUnitTests { return _name.getBytes(); } } + + static class ClassWithWildCardBound { + List wildcard; + List> complexWildcard; + } }