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 7e0dfb2e6..ab74e06d7 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 @@ -246,12 +246,16 @@ class TypeDiscoverer implements TypeInformation { */ public TypeInformation getMapValueType() { - if (!Map.class.isAssignableFrom(getType())) { + if (!isMap()) { return null; } - - ParameterizedType parameterizedType = (ParameterizedType) type; - return createInfo(parameterizedType.getActualTypeArguments()[1]); + + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + return createInfo(parameterizedType.getActualTypeArguments()[1]); + } + + return createInfo(GenericTypeResolver.resolveTypeArguments(getType(), Map.class)[1]); } /* (non-Javadoc) @@ -268,12 +272,30 @@ class TypeDiscoverer implements TypeInformation { */ public TypeInformation getComponentType() { - if (!(Map.class.isAssignableFrom(getType()) || isCollectionLike())) { + if (!(isMap() || isCollectionLike())) { return null; } - ParameterizedType parameterizedType = (ParameterizedType) type; - return createInfo(parameterizedType.getActualTypeArguments()[0]); + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + return createInfo(parameterizedType.getActualTypeArguments()[0]); + } + + Class rawType = getType(); + + if (isMap()) { + return createInfo(GenericTypeResolver.resolveTypeArguments(rawType, Map.class)[0]); + } + + if (Iterable.class.isAssignableFrom(rawType)) { + return createInfo(GenericTypeResolver.resolveTypeArguments(rawType, Iterable.class)[0]); + } + + if (rawType.isArray()) { + return createInfo(rawType.getComponentType()); + } + + return null; } /* diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java index 23e628985..859f97c75 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java @@ -15,11 +15,15 @@ */ package org.springframework.data.util; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.Collection; +import java.util.Locale; import java.util.Map; +import java.util.Properties; import org.junit.Test; import org.junit.runner.RunWith; @@ -84,6 +88,25 @@ public class TypeDiscovererUnitTests { TypeInformation mapValueType = information.getProperty("map").getMapValueType(); assertEquals(mapValueType, information); } + + @Test + public void returnsComponentAndValueTypesForMapExtensions() { + TypeDiscoverer discoverer = new TypeDiscoverer(CustomMap.class, null); + assertEquals(Locale.class, discoverer.getMapValueType().getType()); + assertEquals(String.class, discoverer.getComponentType().getType()); + } + + @Test + public void returnsComponentTypeForCollectionExtension() { + TypeDiscoverer discoverer = new TypeDiscoverer(CustomCollection.class, null); + assertEquals(String.class, discoverer.getComponentType().getType()); + } + + @Test + public void returnsComponentTypeForArrays() { + TypeDiscoverer discoverer = new TypeDiscoverer(String[].class, null); + assertEquals(String.class, discoverer.getComponentType().getType()); + } class SelfReferencing { @@ -93,4 +116,12 @@ public class TypeDiscovererUnitTests { class SelfReferencingMap { Map map; } + + interface CustomMap extends Map { + + } + + interface CustomCollection extends Collection { + + } }