DATACMNS-782 - ProxyProjectionFactory now converts primitive attribute values.
The ProjectingMethodInterceptor now uses a default ConversionService instance to try to convert a potentially not matching result of the target invocation into the type the projection requires before the attempt to create nested projection.
This commit is contained in:
@@ -26,6 +26,8 @@ import java.util.Map.Entry;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -43,6 +45,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
|
||||
|
||||
private final ProjectionFactory factory;
|
||||
private final MethodInterceptor delegate;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ProjectingMethodInterceptor} using the given {@link ProjectionFactory} and delegate
|
||||
@@ -59,6 +62,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
|
||||
|
||||
this.factory = factory;
|
||||
this.delegate = delegate;
|
||||
this.conversionService = new DefaultConversionService();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -75,13 +79,16 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
|
||||
}
|
||||
|
||||
TypeInformation<?> type = ClassTypeInformation.fromReturnTypeOf(invocation.getMethod());
|
||||
Class<?> rawType = type.getType();
|
||||
|
||||
if (type.isCollectionLike() && !ClassUtils.isPrimitiveArray(type.getType())) {
|
||||
if (type.isCollectionLike() && !ClassUtils.isPrimitiveArray(rawType)) {
|
||||
return projectCollectionElements(asCollection(result), type);
|
||||
} else if (type.isMap()) {
|
||||
return projectMapValues((Map<?, ?>) result, type);
|
||||
} else if (conversionRequiredAndPossible(result, rawType)) {
|
||||
return conversionService.convert(result, rawType);
|
||||
} else {
|
||||
return getProjection(result, type.getType());
|
||||
return getProjection(result, rawType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +141,23 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
|
||||
: factory.createProjection(returnType, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the source object needs to be converted to the given target type and whether we can convert it at
|
||||
* all.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @param targetType must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private boolean conversionRequiredAndPossible(Object source, Class<?> targetType) {
|
||||
|
||||
if (source == null || targetType.isInstance(source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return conversionService.canConvert(source.getClass(), targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the given value into a {@link Collection}. Will turn an array into a collection an wrap all other values into
|
||||
* a single-element collection.
|
||||
|
||||
@@ -157,7 +157,7 @@ public class ProxyProjectionFactoryUnitTests {
|
||||
|
||||
List<String> result = factory.getInputProperties(CustomerExcerpt.class);
|
||||
|
||||
assertThat(result, hasSize(4));
|
||||
assertThat(result, hasSize(5));
|
||||
assertThat(result, hasItems("firstname", "address", "shippingAddresses", "picture"));
|
||||
}
|
||||
|
||||
@@ -220,8 +220,23 @@ public class ProxyProjectionFactoryUnitTests {
|
||||
assertThat(excerpt.getShippingAddresses(), is(arrayWithSize(1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-782
|
||||
*/
|
||||
@Test
|
||||
public void convertsPrimitiveValues() {
|
||||
|
||||
Customer customer = new Customer();
|
||||
customer.id = 1L;
|
||||
|
||||
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
|
||||
|
||||
assertThat(excerpt.getId(), is(customer.id.toString()));
|
||||
}
|
||||
|
||||
static class Customer {
|
||||
|
||||
public Long id;
|
||||
public String firstname, lastname;
|
||||
public Address address;
|
||||
public byte[] picture;
|
||||
@@ -235,6 +250,8 @@ public class ProxyProjectionFactoryUnitTests {
|
||||
|
||||
interface CustomerExcerpt {
|
||||
|
||||
String getId();
|
||||
|
||||
String getFirstname();
|
||||
|
||||
AddressExcerpt getAddress();
|
||||
|
||||
Reference in New Issue
Block a user