Browse Source

DATACMNS-722 - ProxyProjectionFactory now deals with arrays.

We now handle primitive and non-primitive arrays in ProxyProjectionFactory. WE basically skip element projections for the former and correctly implement exactly that for the latter.
1.10.x
Oliver Gierke 11 years ago
parent
commit
d641f978bf
  1. 21
      src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java
  2. 42
      src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java

21
src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java

@ -15,9 +15,11 @@ @@ -15,9 +15,11 @@
*/
package org.springframework.data.projection;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -28,6 +30,7 @@ import org.springframework.data.util.ClassTypeInformation; @@ -28,6 +30,7 @@ import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
/**
* {@link MethodInterceptor} to delegate the invocation to a different {@link MethodInterceptor} but creating a
@ -73,7 +76,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -73,7 +76,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
TypeInformation<?> type = ClassTypeInformation.fromReturnTypeOf(invocation.getMethod());
if (type.isCollectionLike()) {
if (type.isCollectionLike() && !ClassUtils.isPrimitiveArray(type.getType())) {
return projectCollectionElements(asCollection(result), type);
} else if (type.isMap()) {
return projectMapValues((Map<?, ?>) result, type);
@ -90,14 +93,20 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -90,14 +93,20 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
* @param type must not be {@literal null}.
* @return
*/
private Collection<Object> projectCollectionElements(Collection<?> sources, TypeInformation<?> type) {
private Object projectCollectionElements(Collection<?> sources, TypeInformation<?> type) {
Collection<Object> result = CollectionFactory.createCollection(type.getType(), sources.size());
Class<?> rawType = type.getType();
Collection<Object> result = CollectionFactory.createCollection(rawType.isArray() ? List.class : rawType,
sources.size());
for (Object source : sources) {
result.add(getProjection(source, type.getComponentType().getType()));
}
if (rawType.isArray()) {
return result.toArray((Object[]) Array.newInstance(type.getComponentType().getType(), result.size()));
}
return result;
}
@ -121,8 +130,8 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -121,8 +130,8 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
}
private Object getProjection(Object result, Class<?> returnType) {
return ClassUtils.isAssignable(returnType, result.getClass()) ? result : factory.createProjection(returnType,
result);
return ClassUtils.isAssignable(returnType, result.getClass()) ? result
: factory.createProjection(returnType, result);
}
/**
@ -139,7 +148,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -139,7 +148,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
if (source instanceof Collection) {
return (Collection<?>) source;
} else if (source.getClass().isArray()) {
return Arrays.asList((Object[]) source);
return Arrays.asList(ObjectUtils.toObjectArray(source));
} else {
return Collections.singleton(source);
}

42
src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java

@ -157,8 +157,8 @@ public class ProxyProjectionFactoryUnitTests { @@ -157,8 +157,8 @@ public class ProxyProjectionFactoryUnitTests {
List<String> result = factory.getInputProperties(CustomerExcerpt.class);
assertThat(result, hasSize(2));
assertThat(result, hasItems("firstname", "address"));
assertThat(result, hasSize(4));
assertThat(result, hasItems("firstname", "address", "shippingAddresses", "picture"));
}
/**
@ -176,10 +176,44 @@ public class ProxyProjectionFactoryUnitTests { @@ -176,10 +176,44 @@ public class ProxyProjectionFactoryUnitTests {
assertThat(advisors[0].getAdvice(), is(instanceOf(DefaultMethodInvokingMethodInterceptor.class)));
}
/**
* @see DATACMNS-722
*/
@Test
public void doesNotProjectPrimitiveArray() {
Customer customer = new Customer();
customer.picture = "binarydata".getBytes();
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
assertThat(excerpt.getPicture(), is(customer.picture));
}
/**
* @see DATACMNS-722
*/
@Test
public void projectsNonPrimitiveArray() {
Address address = new Address();
address.city = "New York";
address.zipCode = "ZIP";
Customer customer = new Customer();
customer.shippingAddresses = new Address[] { address };
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
assertThat(excerpt.getShippingAddresses(), is(arrayWithSize(1)));
}
static class Customer {
public String firstname, lastname;
public Address address;
public byte[] picture;
public Address[] shippingAddresses;
}
static class Address {
@ -192,6 +226,10 @@ public class ProxyProjectionFactoryUnitTests { @@ -192,6 +226,10 @@ public class ProxyProjectionFactoryUnitTests {
String getFirstname();
AddressExcerpt getAddress();
AddressExcerpt[] getShippingAddresses();
byte[] getPicture();
}
interface AddressExcerpt {

Loading…
Cancel
Save