Skip to content

Commit 3a4c1b0

Browse files
christophstroblodrotbohm
authored andcommitted
DATACMNS-621 - QSort now treats nested paths correctly.
We now inspect intermediate path elements to build sort order accordingly. Original pull request: #111.
1 parent dfdae94 commit 3a4c1b0

File tree

5 files changed

+155
-9
lines changed

5 files changed

+155
-9
lines changed

src/main/java/org/springframework/data/querydsl/QSort.java

+26-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2014 the original author or authors.
2+
* Copyright 2013-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.util.ArrayList;
2020
import java.util.Arrays;
2121
import java.util.List;
22+
import java.util.Stack;
2223

2324
import org.springframework.data.domain.Sort;
2425
import org.springframework.util.Assert;
@@ -31,6 +32,7 @@
3132
* Sort option for queries that wraps a querydsl {@link OrderSpecifier}.
3233
*
3334
* @author Thomas Darimont
35+
* @author Christoph Strobl
3436
*/
3537
public class QSort extends Sort implements Serializable {
3638

@@ -87,8 +89,8 @@ private static Order toOrder(OrderSpecifier<?> orderSpecifier) {
8789
Assert.notNull(orderSpecifier, "Order specifier must not be null!");
8890

8991
Expression<?> target = orderSpecifier.getTarget();
90-
Object targetElement = target instanceof Path ? ((com.mysema.query.types.Path<?>) target).getMetadata()
91-
.getElement() : target;
92+
93+
Object targetElement = target instanceof Path ? preparePropertyPath((Path<?>) target) : target;
9294

9395
Assert.notNull(targetElement, "Target element must not be null!");
9496

@@ -142,4 +144,25 @@ public QSort and(OrderSpecifier<?>... orderSpecifiers) {
142144
Assert.notEmpty(orderSpecifiers, "OrderSpecifiers must not be null or empty!");
143145
return and(Arrays.asList(orderSpecifiers));
144146
}
147+
148+
private static String preparePropertyPath(Path<?> path) {
149+
150+
Stack<String> stack = new Stack<String>();
151+
Path<?> pathElement = path;
152+
while (pathElement.getMetadata() != null && pathElement.getMetadata().getParent() != null) {
153+
154+
stack.push(pathElement.getMetadata().getElement().toString());
155+
pathElement = pathElement.getMetadata().getParent();
156+
}
157+
158+
StringBuilder sb = new StringBuilder();
159+
while (!stack.isEmpty()) {
160+
sb.append(stack.pop());
161+
if (!stack.isEmpty()) {
162+
sb.append(".");
163+
}
164+
}
165+
return sb.toString();
166+
}
167+
145168
}

src/test/java/org/springframework/data/querydsl/QSortUnitTests.java

+44-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2014 the original author or authors.
2+
* Copyright 2013-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,9 +15,8 @@
1515
*/
1616
package org.springframework.data.querydsl;
1717

18-
import static org.hamcrest.Matchers.hasItems;
19-
import static org.hamcrest.Matchers.is;
20-
import static org.junit.Assert.assertThat;
18+
import static org.hamcrest.Matchers.*;
19+
import static org.junit.Assert.*;
2120

2221
import java.util.List;
2322

@@ -34,6 +33,7 @@
3433
*
3534
* @author Thomas Darimont
3635
* @author Oliver Gierke
36+
* @author Christoph Strobl
3737
*/
3838
public class QSortUnitTests {
3939

@@ -147,7 +147,7 @@ public void concatenatesPlainSortCorrectly() {
147147
assertThat(result, is(Matchers.<Order> iterableWithSize(2)));
148148
assertThat(result, hasItems(new Order(Direction.ASC, "lastname"), new Order(Direction.ASC, "firstname")));
149149
}
150-
150+
151151
/**
152152
* @see DATACMNS-566
153153
*/
@@ -159,6 +159,44 @@ public void shouldSupportSortByOperatorExpressions() {
159159

160160
Sort result = sort.and(new Sort(Direction.ASC, "lastname"));
161161
assertThat(result, is(Matchers.<Order> iterableWithSize(2)));
162-
assertThat(result, hasItems(new Order(Direction.ASC, "lastname"), new Order(Direction.ASC, user.dateOfBirth.yearMonth().toString())));
162+
assertThat(
163+
result,
164+
hasItems(new Order(Direction.ASC, "lastname"),
165+
new Order(Direction.ASC, user.dateOfBirth.yearMonth().toString())));
166+
}
167+
168+
/**
169+
* @see DATACMNS-621
170+
*/
171+
@Test
172+
public void shouldCreateSortForNestedPathCorrectly() {
173+
174+
QSort sort = new QSort(QUserWrapper.userWrapper.user.firstname.asc());
175+
176+
assertThat(sort, hasItems(new Order(Direction.ASC, "user.firstname")));
177+
}
178+
179+
/**
180+
* @see DATACMNS-621
181+
*/
182+
@Test
183+
public void shouldCreateSortForDeepNestedPathCorrectly() {
184+
185+
QSort sort = new QSort(QWrapperForUserWrapper.wrapperForUserWrapper.wrapper.user.firstname.asc());
186+
187+
assertThat(sort, hasItems(new Order(Direction.ASC, "wrapper.user.firstname")));
188+
}
189+
190+
/**
191+
* @see DATACMNS-621
192+
*/
193+
@Test
194+
public void shouldCreateSortForReallyDeepNestedPathCorrectly() {
195+
196+
QSort sort = new QSort(
197+
QWrapperToWrapWrapperForUserWrapper.wrapperToWrapWrapperForUserWrapper.wrapperForUserWrapper.wrapper.user.firstname
198+
.asc());
199+
200+
assertThat(sort, hasItems(new Order(Direction.ASC, "wrapperForUserWrapper.wrapper.user.firstname")));
163201
}
164202
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.querydsl;
17+
18+
import com.mysema.query.annotations.QueryEntity;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
@QueryEntity
24+
public class UserWrapper {
25+
26+
User user;
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.querydsl;
17+
18+
import com.mysema.query.annotations.QueryEntity;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
@QueryEntity
24+
public class WrapperForUserWrapper {
25+
26+
UserWrapper wrapper;
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.querydsl;
17+
18+
import com.mysema.query.annotations.QueryEntity;
19+
import com.mysema.query.annotations.QueryInit;
20+
21+
/**
22+
* @author Christoph Strobl
23+
*/
24+
@QueryEntity
25+
public class WrapperToWrapWrapperForUserWrapper {
26+
27+
@QueryInit("wrapper.user")//
28+
WrapperForUserWrapper wrapperForUserWrapper;
29+
}

0 commit comments

Comments
 (0)