Skip to content

Commit

Permalink
DATACMNS-167 - Improved Iterable handling in TypeDiscoverer.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
odrotbohm committed May 2, 2012
1 parent 5b0cb1a commit aec655a
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 42 deletions.
@@ -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.
Expand Down Expand Up @@ -27,6 +27,7 @@
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;
Expand Down Expand Up @@ -138,9 +139,9 @@ protected Class<S> resolveType(Type type) {
}

/*
* (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<?>>();
Expand All @@ -153,12 +154,9 @@ public List<TypeInformation<?>> getParameterTypes(Constructor<?> constructor) {
}

/*
* (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('.');
Expand Down Expand Up @@ -228,17 +226,15 @@ private static Type getGenericType(PropertyDescriptor descriptor) {
}

/*
* (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() {
Expand All @@ -251,16 +247,18 @@ public TypeInformation<?> getActualType() {
}
}

/* (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()) {
Expand All @@ -275,21 +273,30 @@ private TypeInformation<?> getTypeArgument(Class<?> type, Class<?> bound, int in
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;
}

Expand All @@ -298,8 +305,6 @@ public TypeInformation<?> getComponentType() {
return createInfo(parameterizedType.getActualTypeArguments()[0]);
}

Class<S> rawType = getType();

if (isMap()) {
return getTypeArgument(rawType, Map.class, 0);
}
Expand All @@ -326,10 +331,9 @@ public TypeInformation<?> getReturnType(Method method) {
}

/*
* (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) {
Expand All @@ -353,10 +357,9 @@ public boolean equals(Object obj) {
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {

Expand Down
@@ -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.
Expand Down Expand Up @@ -134,6 +134,39 @@ public void returnsNullForComponentAndValueTypesForRawMaps() {
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;
Expand Down

0 comments on commit aec655a

Please sign in to comment.