DATACMNS-1555 - Support for extracting properties during a PersistentPropertyPath traversal.

PersistentPropertyAccessor now has an overloaded method to pass in a TraversalContext that can be prepared to property handlers for PersistentProperties. During the traversal, the handler is called with the value for the property so that it can e.g. extract list elements, map values etc.
This commit is contained in:
Oliver Drotbohm
2019-07-19 07:56:42 +02:00
parent a0bcc5e20e
commit e0f2d65d73
3 changed files with 239 additions and 1 deletions

View File

@@ -19,10 +19,20 @@ import static org.assertj.core.api.Assertions.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Value;
import lombok.experimental.Wither;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.Test;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.mapping.context.SampleMappingContext;
@@ -133,6 +143,53 @@ public class PersistentPropertyAccessorUnitTests {
assertThat(convertingAccessor.getBean().getCustomer().getFirstname()).isEqualTo("2");
}
@Test // DATACMNS-1555
public void usesTraversalContextToTraverseCollections() {
WithContext withContext = WithContext.builder() //
.collection(Collections.singleton("value")) //
.list(Collections.singletonList("value")) //
.set(Collections.singleton("value")) //
.map(Collections.singletonMap("key", "value")) //
.string(" value ") //
.build();
Spec collectionHelper = Spec.of("collection",
(context, property) -> context.registerCollectionHandler(property, it -> it.iterator().next()));
Spec listHelper = Spec.of("list", (context, property) -> context.registerListHandler(property, it -> it.get(0)));
Spec setHelper = Spec.of("set",
(context, property) -> context.registerSetHandler(property, it -> it.iterator().next()));
Spec mapHelper = Spec.of("map", (context, property) -> context.registerMapHandler(property, it -> it.get("key")));
Spec stringHelper = Spec.of("string",
(context, property) -> context.registerHandler(property, String.class, it -> it.trim()));
Stream.of(collectionHelper, listHelper, setHelper, mapHelper, stringHelper).forEach(it -> {
PersistentEntity<Object, SamplePersistentProperty> entity = context.getPersistentEntity(WithContext.class);
PersistentProperty<?> property = entity.getRequiredPersistentProperty(it.name);
PersistentPropertyAccessor<WithContext> accessor = entity.getPropertyAccessor(withContext);
TraversalContext traversalContext = it.registrar.apply(new TraversalContext(), property);
PersistentPropertyPath<SamplePersistentProperty> propertyPath = context.getPersistentPropertyPath(it.name,
WithContext.class);
assertThat(accessor.getProperty(propertyPath, traversalContext)).isEqualTo("value");
});
}
@Test // DATACMNS-1555
public void traversalContextRejectsInvalidPropertyHandler() {
PersistentEntity<Object, SamplePersistentProperty> entity = context.getPersistentEntity(WithContext.class);
PersistentProperty<?> property = entity.getRequiredPersistentProperty("collection");
TraversalContext traversal = new TraversalContext();
assertThatExceptionOfType(IllegalArgumentException.class) //
.isThrownBy(() -> traversal.registerHandler(property, Map.class, Function.identity()));
}
@Value
static class Order {
Customer customer;
@@ -157,4 +214,23 @@ public class PersistentPropertyAccessorUnitTests {
static class Outer {
NestedImmutable immutable;
}
// DATACMNS-1555
@Builder
static class WithContext {
Collection<String> collection;
List<String> list;
Set<String> set;
Map<String, String> map;
String string;
}
@Value(staticConstructor = "of")
static class Spec {
String name;
BiFunction<TraversalContext, PersistentProperty<?>, TraversalContext> registrar;
}
}