From 428a3c2fcbfefe4df5436a99f01fdb4f835d7648 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sat, 11 Apr 2015 13:49:10 +0200 Subject: [PATCH] =?UTF-8?q?DATAJPA-702=20-=20Added=20simplified=20JpaSort.?= =?UTF-8?q?and(=E2=80=A6).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../data/jpa/domain/JpaSort.java | 90 ++++++++++++------- .../data/jpa/domain/JpaSortTests.java | 80 +++++++++++++---- 2 files changed, 122 insertions(+), 48 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/domain/JpaSort.java b/src/main/java/org/springframework/data/jpa/domain/JpaSort.java index 34111f944..9bbc13695 100644 --- a/src/main/java/org/springframework/data/jpa/domain/JpaSort.java +++ b/src/main/java/org/springframework/data/jpa/domain/JpaSort.java @@ -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> paths) { - super(direction, toString(paths)); + private JpaSort(Direction direction, List> paths) { + this(Collections. emptyList(), direction, paths); + } + + private JpaSort(List orders, Direction direction, List> 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 existing = new ArrayList(); + + 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> paths(List> 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> paths = new ArrayList>(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> paths) { + private static List combine(List orders, Direction direction, List> paths) { - List strings = new ArrayList(paths.size()); + List result = new ArrayList(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 Path path(Attribute attribute) { + public static , T, S> Path path(A attribute) { Assert.notNull(attribute, "Attribute must not be null!"); - - List> attributes = Arrays.asList(attribute); - return new Path(attributes); + return new Path(Arrays.asList(attribute)); } /** @@ -138,12 +168,10 @@ public class JpaSort extends Sort { * @return */ @SuppressWarnings("unchecked") - public static Path path(PluralAttribute attribute) { + public static

, T, S> Path path(P attribute) { Assert.notNull(attribute, "Attribute must not be null!"); - - List> attributes = Arrays.asList(attribute); - return new Path(attributes); + return new Path(Arrays.asList(attribute)); } /** @@ -165,17 +193,17 @@ public class JpaSort extends Sort { * @param attribute must not be {@literal null}. * @return */ - public Path dot(Attribute attribute) { + public , U> Path dot(A attribute) { return new Path(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 Path dot(PluralAttribute attribute) { + public

, U> Path dot(P attribute) { return new Path(add(attribute)); } diff --git a/src/test/java/org/springframework/data/jpa/domain/JpaSortTests.java b/src/test/java/org/springframework/data/jpa/domain/JpaSortTests.java index d015e29b0..56db5736f 100644 --- a/src/test/java/org/springframework/data/jpa/domain/JpaSortTests.java +++ b/src/test/java/org/springframework/data/jpa/domain/JpaSortTests.java @@ -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"))); } }