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.
This commit is contained in:
@@ -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;
|
||||
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 {
|
||||
|
||||
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 {
|
||||
* @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 {
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
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 {
|
||||
String getFirstname();
|
||||
|
||||
AddressExcerpt getAddress();
|
||||
|
||||
AddressExcerpt[] getShippingAddresses();
|
||||
|
||||
byte[] getPicture();
|
||||
}
|
||||
|
||||
interface AddressExcerpt {
|
||||
|
||||
Reference in New Issue
Block a user