Browse Source

DATACMNS-167 - Improved Iterable handling in TypeDiscoverer.

If a type implemented Iterable<…> it was currently treated as a collection which might cause inappropriate conversion in the mapping sub-system. We now consider types collection like if they're either Iterable directly or assignable to Collection.
1.3.x
Oliver Gierke 14 years ago
parent
commit
aec655a499
  1. 85
      spring-data-commons-core/src/main/java/org/springframework/data/util/TypeDiscoverer.java
  2. 35
      spring-data-commons-core/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java

85
spring-data-commons-core/src/main/java/org/springframework/data/util/TypeDiscoverer.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2011 the original author or authors.
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,6 +27,7 @@ import java.lang.reflect.Type; @@ -27,6 +27,7 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -138,9 +139,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -138,9 +139,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
}
/*
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getParameterTypes(java.lang.reflect.Constructor)
*/
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getParameterTypes(java.lang.reflect.Constructor)
*/
public List<TypeInformation<?>> getParameterTypes(Constructor<?> constructor) {
List<TypeInformation<?>> result = new ArrayList<TypeInformation<?>>();
@ -153,12 +154,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -153,12 +154,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.TypeDiscovererTest.FieldInformation
* #getField(java.lang.String)
*/
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getProperty(java.lang.String)
*/
public TypeInformation<?> getProperty(String fieldname) {
int separatorIndex = fieldname.indexOf('.');
@ -228,17 +226,15 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -228,17 +226,15 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.document.mongodb.TypeDiscovererTest.FieldInformation
* #getType()
*/
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getType()
*/
public Class<S> getType() {
return resolveType(type);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getActualType()
*/
public TypeInformation<?> getActualType() {
@ -251,16 +247,18 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -251,16 +247,18 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
}
}
/* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#isMap()
*/
/*
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#isMap()
*/
public boolean isMap() {
return Map.class.isAssignableFrom(getType());
}
/* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getMapValueType()
*/
/*
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getMapValueType()
*/
public TypeInformation<?> getMapValueType() {
if (!isMap()) {
@ -275,21 +273,30 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -275,21 +273,30 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
return arguments == null ? null : createInfo(arguments[index]);
}
/* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#isCollectionLike()
*/
/*
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#isCollectionLike()
*/
public boolean isCollectionLike() {
Class<?> rawType = getType();
return rawType.isArray() || Iterable.class.isAssignableFrom(rawType);
if (rawType.isArray() || Iterable.class.equals(rawType)) {
return true;
}
return Collection.class.isAssignableFrom(rawType);
}
/* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getComponentType()
*/
/*
* (non-Javadoc)
* @see org.springframework.data.util.TypeInformation#getComponentType()
*/
public TypeInformation<?> getComponentType() {
if (!(isMap() || isCollectionLike())) {
Class<S> rawType = getType();
if (!(isMap() || isCollectionLike() || Iterable.class.isAssignableFrom(rawType))) {
return null;
}
@ -298,8 +305,6 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -298,8 +305,6 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
return createInfo(parameterizedType.getActualTypeArguments()[0]);
}
Class<S> rawType = getType();
if (isMap()) {
return getTypeArgument(rawType, Map.class, 0);
}
@ -326,10 +331,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -326,10 +331,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
@ -353,10 +357,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> { @@ -353,10 +357,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {

35
spring-data-commons-core/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2011 the original author or authors.
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -134,6 +134,39 @@ public class TypeDiscovererUnitTests { @@ -134,6 +134,39 @@ public class TypeDiscovererUnitTests {
assertThat(discoverer.getMapValueType(), is(nullValue()));
}
/**
* @see DATACMNS-167
*/
@Test
@SuppressWarnings("rawtypes")
public void doesNotConsiderTypeImplementingIterableACollection() {
TypeDiscoverer<Person> discoverer = new TypeDiscoverer<Person>(Person.class, null);
TypeInformation reference = ClassTypeInformation.from(Address.class);
TypeInformation<?> addresses = discoverer.getProperty("addresses");
assertThat(addresses.isCollectionLike(), is(false));
assertThat(addresses.getComponentType(), is(reference));
TypeInformation<?> adressIterable = discoverer.getProperty("addressIterable");
assertThat(adressIterable.isCollectionLike(), is(true));
assertThat(adressIterable.getComponentType(), is(reference));
}
class Person {
Addresses addresses;
Iterable<Address> addressIterable;
}
abstract class Addresses implements Iterable<Address> {
}
class Address {
}
class SelfReferencing {
Map<String, SelfReferencingMap> parent;

Loading…
Cancel
Save