DATAJPA-702 - Added simplified JpaSort.and(…).

Added new ….and(…) methods to JpaSort to take a Direction and Paths or Attributes to allow more concise definition of additional orders.

Slightly changed the method signature for methods on Path taking a Plural attribute to satisfy the compiler.
This commit is contained in:
Oliver Gierke
2015-04-11 13:49:10 +02:00
parent 6f4e7f3703
commit 428a3c2fcb
2 changed files with 122 additions and 48 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ public class JpaSort extends Sort {
* @param attributes must not be {@literal null} or empty.
*/
public JpaSort(Direction direction, Attribute<?, ?>... attributes) {
this(direction, paths(Arrays.asList(attributes)));
this(direction, paths(attributes));
}
/**
@@ -71,12 +71,50 @@ public class JpaSort extends Sort {
* @param direction the sorting direction.
* @param paths must not be {@literal null} or empty.
*/
public JpaSort(Direction direction, JpaSort.Path<?, ?>... paths) {
public JpaSort(Direction direction, Path<?, ?>... paths) {
this(direction, Arrays.asList(paths));
}
private JpaSort(Direction direction, List<JpaSort.Path<?, ?>> paths) {
super(direction, toString(paths));
private JpaSort(Direction direction, List<Path<?, ?>> paths) {
this(Collections.<Order> emptyList(), direction, paths);
}
private JpaSort(List<Order> orders, Direction direction, List<Path<?, ?>> paths) {
super(combine(orders, direction, paths));
}
/**
* Returns a new {@link JpaSort} with the given sorting criteria added to the current one.
*
* @param direction can be {@literal null}.
* @param attributes must not be {@literal null}.
* @return
*/
public JpaSort and(Direction direction, Attribute<?, ?>... attributes) {
Assert.notNull(attributes, "Attributes must not be null!");
return and(direction, paths(attributes));
}
/**
* Returns a new {@link JpaSort} with the given sorting criteria added to the current one.
*
* @param direction can be {@literal null}.
* @param paths must not be {@literal null}.
* @return
*/
public JpaSort and(Direction direction, Path<?, ?>... paths) {
Assert.notNull(paths, "Paths must not be null!");
List<Order> existing = new ArrayList<Order>();
for (Order order : this) {
existing.add(order);
}
return new JpaSort(existing, direction, Arrays.asList(paths));
}
/**
@@ -85,35 +123,29 @@ public class JpaSort extends Sort {
* @param attributes must not be {@literal null} or empty.
* @return
*/
private static List<Path<?, ?>> paths(List<? extends Attribute<?, ?>> attributes) {
private static Path<?, ?>[] paths(Attribute<?, ?>[] attributes) {
Assert.notNull(attributes, "Attributes must not be null!");
Assert.isTrue(!attributes.isEmpty(), "Attributes must not be empty");
Assert.isTrue(attributes.length > 0, "Attributes must not be empty");
List<Path<?, ?>> paths = new ArrayList<Path<?, ?>>(attributes.size());
Path<?, ?>[] paths = new Path[attributes.length];
for (Attribute<?, ?> attribute : attributes) {
paths.add(path(attribute));
for (int i = 0; i < attributes.length; i++) {
paths[i] = path(attributes[i]);
}
return paths;
}
/**
* Renders the given {@link Path}s into a {@link String} array.
*
* @param paths must not be {@literal null} or empty.
* @return
*/
private static String[] toString(List<Path<?, ?>> paths) {
private static List<Order> combine(List<Order> orders, Direction direction, List<Path<?, ?>> paths) {
List<String> strings = new ArrayList<String>(paths.size());
List<Order> result = new ArrayList<Sort.Order>(orders);
for (Path<?, ?> path : paths) {
strings.add(path.toString());
result.add(new Order(direction, path.toString()));
}
return strings.toArray(new String[strings.size()]);
return result;
}
/**
@@ -123,12 +155,10 @@ public class JpaSort extends Sort {
* @return
*/
@SuppressWarnings("unchecked")
public static <T, S> Path<T, S> path(Attribute<T, S> attribute) {
public static <A extends Attribute<T, S>, T, S> Path<T, S> path(A attribute) {
Assert.notNull(attribute, "Attribute must not be null!");
List<? extends Attribute<?, ?>> attributes = Arrays.asList(attribute);
return new Path<T, S>(attributes);
return new Path<T, S>(Arrays.asList(attribute));
}
/**
@@ -138,12 +168,10 @@ public class JpaSort extends Sort {
* @return
*/
@SuppressWarnings("unchecked")
public static <T, S> Path<T, S> path(PluralAttribute<T, ?, S> attribute) {
public static <P extends PluralAttribute<T, ?, S>, T, S> Path<T, S> path(P attribute) {
Assert.notNull(attribute, "Attribute must not be null!");
List<? extends Attribute<?, ?>> attributes = Arrays.asList(attribute);
return new Path<T, S>(attributes);
return new Path<T, S>(Arrays.asList(attribute));
}
/**
@@ -165,17 +193,17 @@ public class JpaSort extends Sort {
* @param attribute must not be {@literal null}.
* @return
*/
public <U> Path<S, U> dot(Attribute<S, U> attribute) {
public <A extends Attribute<S, U>, U> Path<S, U> dot(A attribute) {
return new Path<S, U>(add(attribute));
}
/**
* Collects the given {@link Attribute} and returning a new {@link Path} pointing to the attribute type.
* Collects the given {@link PluralAttribute} and returning a new {@link Path} pointing to the attribute type.
*
* @param attribute must not be {@literal null}.
* @return
*/
public <U> Path<S, U> dot(PluralAttribute<S, ?, U> attribute) {
public <P extends PluralAttribute<S, ?, U>, U> Path<S, U> dot(P attribute) {
return new Path<S, U>(add(attribute));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,9 @@
*/
package org.springframework.data.jpa.domain;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.domain.Sort.Direction.*;
import static org.springframework.data.jpa.domain.JpaSort.*;
import javax.persistence.EntityManagerFactory;
@@ -27,9 +28,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.JpaSort.Path;
import org.springframework.data.jpa.domain.sample.Address_;
import org.springframework.data.jpa.domain.sample.MailMessage_;
import org.springframework.data.jpa.domain.sample.MailSender_;
import org.springframework.data.jpa.domain.sample.Role_;
import org.springframework.data.jpa.domain.sample.User_;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -81,50 +85,92 @@ public class JpaSortTests {
@Test
public void sortByMultiplePropertiesWithDefaultSortDirection() {
assertThat(new JpaSort(User_.firstname, User_.lastname),
hasItems(new Sort.Order("firstname"), new Sort.Order("lastname")));
assertThat(new JpaSort(User_.firstname, User_.lastname), hasItems(new Order("firstname"), new Order("lastname")));
}
@Test
public void sortByMultiplePropertiesWithDescSortDirection() {
assertThat(new JpaSort(Direction.DESC, User_.firstname, User_.lastname),
hasItems(new Sort.Order(Direction.DESC, "firstname"), new Sort.Order(Direction.DESC, "lastname")));
assertThat(new JpaSort(DESC, User_.firstname, User_.lastname),
hasItems(new Order(DESC, "firstname"), new Order(Direction.DESC, "lastname")));
}
@Test
public void combiningSortByMultipleProperties() {
assertThat(new JpaSort(User_.firstname).and(new JpaSort(User_.lastname)),
hasItems(new Sort.Order("firstname"), new Sort.Order("lastname")));
hasItems(new Order("firstname"), new Order("lastname")));
}
@Test
public void combiningSortByMultiplePropertiesWithDifferentSort() {
assertThat(new JpaSort(User_.firstname).and(new JpaSort(Direction.DESC, User_.lastname)),
hasItems(new Sort.Order("firstname"), new Sort.Order(Direction.DESC, "lastname")));
assertThat(new JpaSort(User_.firstname).and(new JpaSort(DESC, User_.lastname)),
hasItems(new Order("firstname"), new Order(DESC, "lastname")));
}
@Test
public void combiningSortByNestedEmbeddedProperty() {
assertThat(new JpaSort(path(User_.address).dot(Address_.streetName)),
hasItems(new Sort.Order("address.streetName")));
assertThat(new JpaSort(path(User_.address).dot(Address_.streetName)), hasItems(new Order("address.streetName")));
}
@Test
public void buildJpaSortFromJpaMetaModelSingleAttribute() {
assertThat(new JpaSort(Direction.ASC, path(User_.firstname)), //
hasItems(new Sort.Order("firstname")));
assertThat(new JpaSort(ASC, path(User_.firstname)), //
hasItems(new Order("firstname")));
}
@Test
public void buildJpaSortFromJpaMetaModelNestedAttribute() {
assertThat(new JpaSort(Direction.ASC, path(MailMessage_.mailSender).dot(MailSender_.name)),
hasItems(new Sort.Order("mailSender.name")));
assertThat(new JpaSort(ASC, path(MailMessage_.mailSender).dot(MailSender_.name)), //
hasItems(new Order("mailSender.name")));
}
/**
* @see DATAJPA-702
*/
@Test
public void combiningSortByMultiplePropertiesWithDifferentSortUsingSimpleAnd() {
assertThat(new JpaSort(User_.firstname).and(DESC, User_.lastname),
contains(new Order("firstname"), new Order(DESC, "lastname")));
}
/**
* @see DATAJPA-702
*/
@Test
public void combiningSortByMultiplePathsWithDifferentSortUsingSimpleAnd() {
assertThat(new JpaSort(User_.firstname).and(DESC, path(MailMessage_.mailSender).dot(MailSender_.name)),
contains(new Order("firstname"), new Order(DESC, "mailSender.name")));
}
/**
* @see DATAJPA-702
*/
@Test(expected = IllegalArgumentException.class)
public void rejectsNullAttributesForCombiningCriterias() {
new JpaSort(User_.firstname).and(DESC, (Attribute<?, ?>[]) null);
}
/**
* @see DATAJPA-702
*/
@Test(expected = IllegalArgumentException.class)
public void rejectsNullPathsForCombiningCriterias() {
new JpaSort(User_.firstname).and(DESC, (Path<?, ?>[]) null);
}
/**
* @see DATAJPA-702
*/
@Test
public void buildsUpPathForPluralAttributesCorrectly() {
assertThat(new JpaSort(path(User_.colleagues).dot(User_.roles).dot(Role_.name)), //
hasItem(new Order(ASC, "colleagues.roles.name")));
}
}