DATACMNS-1450 - Introduced type-safe Sort API.
We now expose a TypedSort that can use method handles to define properties to sort by. Sort.sort(Person.class).by(Person::getName).ascending(); Related tickets: DATACMNS-1449.
This commit is contained in:
@@ -23,8 +23,11 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.util.MethodInvocationRecorder;
|
||||
import org.springframework.data.util.MethodInvocationRecorder.Recorded;
|
||||
import org.springframework.data.util.Streamable;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -169,6 +172,17 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TypedSort} for the given type.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.2
|
||||
*/
|
||||
public static <T> TypedSort<T> sort(Class<T> type) {
|
||||
return new TypedSort<>(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Sort} instances representing no sorting setup at all.
|
||||
*
|
||||
@@ -692,4 +706,83 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension of Sort to use method handles to define properties to sort by.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 2.2
|
||||
* @soundtrack The Intersphere - Linger (The Grand Delusion)
|
||||
*/
|
||||
public static class TypedSort<T> extends Sort {
|
||||
|
||||
private static final long serialVersionUID = -3550403511206745880L;
|
||||
|
||||
private final Recorded<T> recorded;
|
||||
|
||||
private TypedSort(Class<T> type) {
|
||||
this(MethodInvocationRecorder.forProxyOf(type));
|
||||
}
|
||||
|
||||
private TypedSort(Recorded<T> recorded) {
|
||||
|
||||
super(new Order[0]);
|
||||
this.recorded = recorded;
|
||||
}
|
||||
|
||||
public <S> TypedSort<S> by(Function<T, S> property) {
|
||||
return new TypedSort<>(recorded.record(property));
|
||||
}
|
||||
|
||||
public <S> TypedSort<S> by(Recorded.ToCollectionConverter<T, S> collectionProperty) {
|
||||
return new TypedSort<>(recorded.record(collectionProperty));
|
||||
}
|
||||
|
||||
public <S> TypedSort<S> by(Recorded.ToMapConverter<T, S> mapProperty) {
|
||||
return new TypedSort<>(recorded.record(mapProperty));
|
||||
}
|
||||
|
||||
public Sort ascending() {
|
||||
return withDirection(Sort::ascending);
|
||||
}
|
||||
|
||||
public Sort descending() {
|
||||
return withDirection(Sort::descending);
|
||||
}
|
||||
|
||||
private Sort withDirection(Function<Sort, Sort> direction) {
|
||||
|
||||
return recorded.getPropertyPath() //
|
||||
.map(Sort::by) //
|
||||
.map(direction) //
|
||||
.orElseGet(Sort::unsorted);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.Sort#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Order> iterator() {
|
||||
|
||||
return recorded.getPropertyPath() //
|
||||
.map(Order::by) //
|
||||
.map(Collections::singleton) //
|
||||
.orElseGet(Collections::emptySet).iterator();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.Sort#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return recorded.getPropertyPath() //
|
||||
.map(Sort::by) //
|
||||
.orElseGet(Sort::unsorted) //
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ package org.springframework.data.domain;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.domain.Sort.NullHandling.*;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
@@ -172,4 +176,28 @@ public class SortUnitTests {
|
||||
.isThrownBy(() -> Sort.by((Direction) null, "foo"))//
|
||||
.withMessageContaining("Direction");
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1450
|
||||
public void translatesTypedSortCorrectly() {
|
||||
|
||||
assertThat(Sort.sort(Sample.class).by(Sample::getNested).by(Nested::getFirstname)) //
|
||||
.containsExactly(Order.by("nested.firstname"));
|
||||
|
||||
assertThat(Sort.sort(Sample.class).by((Sample it) -> it.getNested().getFirstname())) //
|
||||
.containsExactly(Order.by("nested.firstname"));
|
||||
|
||||
assertThat(Sort.sort(Sample.class).by(Sample::getNesteds).by(Nested::getFirstname)) //
|
||||
.containsExactly(Order.by("nesteds.firstname"));
|
||||
}
|
||||
|
||||
@Getter
|
||||
static class Sample {
|
||||
Nested nested;
|
||||
Collection<Nested> nesteds;
|
||||
}
|
||||
|
||||
@Getter
|
||||
static class Nested {
|
||||
String firstname;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user