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:
Oliver Drotbohm
2018-12-13 16:47:21 +01:00
parent 34d95fb7e4
commit 34507ec000
2 changed files with 121 additions and 0 deletions

View File

@@ -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();
}
}
}