DATACMNS-940 - Support for Javaslang collections as repository return types.
Javaslang's collection and map types can now be used on repository query methods and get adapted similarly to nullable wrapper types (like JDK's Optional). Also made TypeInformation infrastructure aware of the map type so that a value type lookup gets handle correctly.
This commit is contained in:
@@ -35,13 +35,16 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -51,6 +54,22 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
|
||||
private static final Iterable<Class<?>> MAP_TYPES;
|
||||
|
||||
static {
|
||||
|
||||
ClassLoader classLoader = TypeDiscoverer.class.getClassLoader();
|
||||
|
||||
Set<Class<?>> mapTypes = new HashSet<Class<?>>();
|
||||
mapTypes.add(Map.class);
|
||||
|
||||
try {
|
||||
mapTypes.add(ClassUtils.forName("javaslang.collection.Map", classLoader));
|
||||
} catch (ClassNotFoundException o_O) {}
|
||||
|
||||
MAP_TYPES = Collections.unmodifiableSet(mapTypes);
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
private final Map<TypeVariable<?>, Type> typeVariableMap;
|
||||
private final Map<String, ValueHolder> fieldTypes = new ConcurrentHashMap<String, ValueHolder>();
|
||||
@@ -329,7 +348,14 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
* @see org.springframework.data.util.TypeInformation#isMap()
|
||||
*/
|
||||
public boolean isMap() {
|
||||
return Map.class.isAssignableFrom(getType());
|
||||
|
||||
for (Class<?> mapType : MAP_TYPES) {
|
||||
if (mapType.isAssignableFrom(getType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -349,7 +375,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
protected TypeInformation<?> doGetMapValueType() {
|
||||
|
||||
if (isMap()) {
|
||||
return getTypeArgument(Map.class, 1);
|
||||
return getTypeArgument(getBaseType(MAP_TYPES), 1);
|
||||
}
|
||||
|
||||
List<TypeInformation<?>> arguments = getTypeArguments();
|
||||
@@ -399,7 +425,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
}
|
||||
|
||||
if (isMap()) {
|
||||
return getTypeArgument(Map.class, 0);
|
||||
return getTypeArgument(getBaseType(MAP_TYPES), 0);
|
||||
}
|
||||
|
||||
if (Iterable.class.isAssignableFrom(rawType)) {
|
||||
@@ -525,6 +551,17 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
return createInfo(arguments[index]);
|
||||
}
|
||||
|
||||
private Class<?> getBaseType(Iterable<Class<?>> candidates) {
|
||||
|
||||
for (Class<?> candidate : candidates) {
|
||||
if (candidate.isAssignableFrom(getType())) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Type %s not contained in candidates %s!", getType(), candidates));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
|
||||
Reference in New Issue
Block a user