Adds ignorecase field to pageable spring (#1047)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-2024 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.
|
||||
@@ -33,6 +33,7 @@ import org.springframework.data.domain.Sort;
|
||||
*
|
||||
* @author Pascal Büttiker
|
||||
* @author Yanming Zhou
|
||||
* @author Gokalp Kuscu
|
||||
*/
|
||||
public class PageableSpringEncoder implements Encoder {
|
||||
|
||||
@@ -53,6 +54,11 @@ public class PageableSpringEncoder implements Encoder {
|
||||
*/
|
||||
private String sortParameter = "sort";
|
||||
|
||||
/**
|
||||
* Sort ignoreCase parameter name.
|
||||
*/
|
||||
private final String ignoreCase = "ignorecase";
|
||||
|
||||
/**
|
||||
* Creates a new PageableSpringEncoder with the given delegate for fallback. If no
|
||||
* delegate is provided and this encoder cant handle the request, an EncodeException
|
||||
@@ -115,7 +121,11 @@ public class PageableSpringEncoder implements Encoder {
|
||||
}
|
||||
}
|
||||
for (Sort.Order order : sort) {
|
||||
sortQueries.add(order.getProperty() + "%2C" + order.getDirection());
|
||||
String sortQuery = order.getProperty() + "%2C" + order.getDirection();
|
||||
if (order.isIgnoreCase()) {
|
||||
sortQuery += "%2C" + ignoreCase;
|
||||
}
|
||||
sortQueries.add(sortQuery);
|
||||
}
|
||||
if (!sortQueries.isEmpty()) {
|
||||
template.query(sortParameter, sortQueries);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-2024 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.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.domain.Sort;
|
||||
*
|
||||
* @author Hyeonmin Park
|
||||
* @author Yanming Zhou
|
||||
* @author Gokalp Kuscu
|
||||
* @since 2.2.8
|
||||
*/
|
||||
public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
|
||||
@@ -51,6 +52,11 @@ public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
|
||||
*/
|
||||
private String sortParameter = "sort";
|
||||
|
||||
/**
|
||||
* Sort ignoreCase parameter name.
|
||||
*/
|
||||
private final String ignoreCase = "ignorecase";
|
||||
|
||||
public void setPageParameter(String pageParameter) {
|
||||
this.pageParameter = pageParameter;
|
||||
}
|
||||
@@ -92,7 +98,11 @@ public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
|
||||
private void applySort(Map<String, Object> queryMap, Sort sort) {
|
||||
List<String> sortQueries = new ArrayList<>();
|
||||
for (Sort.Order order : sort) {
|
||||
sortQueries.add(order.getProperty() + "%2C" + order.getDirection());
|
||||
String sortQuery = order.getProperty() + "%2C" + order.getDirection();
|
||||
if (order.isIgnoreCase()) {
|
||||
sortQuery += "%2C" + ignoreCase;
|
||||
}
|
||||
sortQueries.add(sortQuery);
|
||||
}
|
||||
if (!sortQueries.isEmpty()) {
|
||||
queryMap.put(sortParameter, sortQueries);
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.springframework.data.domain.Sort;
|
||||
*
|
||||
* @author Can Bezmen
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Gokalp Kuscu
|
||||
*/
|
||||
public class SortJsonComponent {
|
||||
|
||||
@@ -90,8 +91,23 @@ public class SortJsonComponent {
|
||||
private static Sort toSort(ArrayNode arrayNode) {
|
||||
List<Sort.Order> orders = new ArrayList<>();
|
||||
for (JsonNode jsonNode : arrayNode) {
|
||||
Sort.Order order = new Sort.Order(Sort.Direction.valueOf(jsonNode.get("direction").textValue()),
|
||||
jsonNode.get("property").textValue());
|
||||
Sort.Order order;
|
||||
// there is no way to construct without null handling
|
||||
if ((jsonNode.has("ignoreCase") && jsonNode.get("ignoreCase").isBoolean())
|
||||
&& jsonNode.has("nullHandling") && jsonNode.get("nullHandling").isTextual()) {
|
||||
|
||||
boolean ignoreCase = jsonNode.get("ignoreCase").asBoolean();
|
||||
String nullHandlingValue = jsonNode.get("nullHandling").textValue();
|
||||
|
||||
order = new Sort.Order(Sort.Direction.valueOf(jsonNode.get("direction").textValue()),
|
||||
jsonNode.get("property").textValue(), ignoreCase,
|
||||
Sort.NullHandling.valueOf(nullHandlingValue));
|
||||
}
|
||||
else {
|
||||
// backward compatibility
|
||||
order = new Sort.Order(Sort.Direction.valueOf(jsonNode.get("direction").textValue()),
|
||||
jsonNode.get("property").textValue());
|
||||
}
|
||||
orders.add(order);
|
||||
}
|
||||
return Sort.by(orders);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-2024 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.
|
||||
@@ -53,6 +53,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
|
||||
*
|
||||
* @author Charlie Mordant.
|
||||
* @author Hyeonmin Park
|
||||
* @author Gokalp Kuscu
|
||||
*/
|
||||
@SpringBootTest(classes = FeignPageableEncodingTests.Application.class, webEnvironment = RANDOM_PORT,
|
||||
value = { "spring.cloud.openfeign.compression.request.enabled=true" })
|
||||
@@ -264,6 +265,110 @@ class FeignPageableEncodingTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPageableWithIgnoreCase() {
|
||||
// given
|
||||
Sort.Order anySorting = Sort.Order.asc("anySorting").ignoreCase();
|
||||
Pageable pageable = PageRequest.of(0, 10, Sort.by(anySorting));
|
||||
|
||||
// when
|
||||
final ResponseEntity<Page<Invoice>> response = this.invoiceClient.getInvoicesPaged(pageable);
|
||||
|
||||
// then
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).isNotNull();
|
||||
assertThat(pageable.getPageSize()).isEqualTo(response.getBody().getSize());
|
||||
assertThat(response.getBody().getPageable().getSort()).hasSize(1);
|
||||
Optional<Sort.Order> optionalOrder = response.getBody().getPageable().getSort().get().findFirst();
|
||||
assertThat(optionalOrder.isPresent()).isEqualTo(true);
|
||||
if (optionalOrder.isPresent()) {
|
||||
Sort.Order order = optionalOrder.get();
|
||||
assertThat(order.getDirection()).isEqualTo(Sort.Direction.ASC);
|
||||
assertThat(order.getProperty()).isEqualTo("anySorting");
|
||||
assertThat(order.isIgnoreCase()).as("isIgnoreCase does not have expected value").isEqualTo(true);
|
||||
assertThat(order.getNullHandling()).isEqualTo(Sort.NullHandling.NATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSortWithIgnoreCaseAndBody() {
|
||||
// given
|
||||
Sort.Order anySorting = Sort.Order.desc("amount").ignoreCase();
|
||||
Sort sort = Sort.by(anySorting);
|
||||
|
||||
// when
|
||||
final ResponseEntity<Page<Invoice>> response = this.invoiceClient.getInvoicesSortedWithBody(sort,
|
||||
"InvoiceTitleFromBody");
|
||||
|
||||
// then
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).isNotNull();
|
||||
assertThat(sort).isEqualTo(response.getBody().getSort());
|
||||
|
||||
Optional<Sort.Order> optionalOrder = response.getBody().getPageable().getSort().get().findFirst();
|
||||
assertThat(optionalOrder.isPresent()).isEqualTo(true);
|
||||
if (optionalOrder.isPresent()) {
|
||||
Sort.Order order = optionalOrder.get();
|
||||
assertThat(order.isIgnoreCase()).as("isIgnoreCase does not have expected value").isEqualTo(true);
|
||||
assertThat(order.getNullHandling()).isEqualTo(Sort.NullHandling.NATIVE);
|
||||
}
|
||||
|
||||
List<Invoice> invoiceList = response.getBody().getContent();
|
||||
assertThat(invoiceList).hasSizeGreaterThanOrEqualTo(1);
|
||||
|
||||
Invoice firstInvoice = invoiceList.get(0);
|
||||
assertThat(firstInvoice.getTitle()).startsWith("InvoiceTitleFromBody");
|
||||
|
||||
for (int ind = 0; ind < invoiceList.size() - 1; ind++) {
|
||||
assertThat(invoiceList.get(ind).getAmount()).isGreaterThanOrEqualTo(invoiceList.get(ind + 1).getAmount());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPageableMultipleSortPropertiesWithBodyAndIgnoreCase() {
|
||||
// given
|
||||
Sort.Order anySorting1 = Sort.Order.desc("anySorting1").ignoreCase();
|
||||
Sort.Order anySorting2 = Sort.Order.asc("anySorting2");
|
||||
Pageable pageable = PageRequest.of(0, 10, Sort.by(anySorting1, anySorting2));
|
||||
|
||||
// when
|
||||
final ResponseEntity<Page<Invoice>> response = this.invoiceClient.getInvoicesPagedWithBody(pageable,
|
||||
"InvoiceTitleFromBody");
|
||||
|
||||
// then
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).isNotNull();
|
||||
assertThat(pageable.getPageSize()).isEqualTo(response.getBody().getSize());
|
||||
|
||||
List<Invoice> invoiceList = response.getBody().getContent();
|
||||
assertThat(invoiceList).hasSizeGreaterThanOrEqualTo(1);
|
||||
|
||||
Invoice firstInvoice = invoiceList.get(0);
|
||||
assertThat(firstInvoice.getTitle()).startsWith("InvoiceTitleFromBody");
|
||||
|
||||
Sort sort = response.getBody().getPageable().getSort();
|
||||
assertThat(sort).hasSize(2);
|
||||
|
||||
List<Sort.Order> orderList = sort.toList();
|
||||
assertThat(orderList).hasSize(2);
|
||||
|
||||
Sort.Order firstOrder = orderList.get(0);
|
||||
assertThat(firstOrder.getDirection()).isEqualTo(Sort.Direction.DESC);
|
||||
assertThat(firstOrder.getProperty()).isEqualTo("anySorting1");
|
||||
assertThat(firstOrder.isIgnoreCase()).as("isIgnoreCase does not have expected value").isEqualTo(true);
|
||||
assertThat(firstOrder.getNullHandling()).isEqualTo(Sort.NullHandling.NATIVE);
|
||||
|
||||
Sort.Order secondOrder = orderList.get(1);
|
||||
assertThat(secondOrder.getDirection()).isEqualTo(Sort.Direction.ASC);
|
||||
assertThat(secondOrder.getProperty()).isEqualTo("anySorting2");
|
||||
assertThat(secondOrder.isIgnoreCase()).as("isIgnoreCase does not have expected value").isEqualTo(false);
|
||||
assertThat(secondOrder.getNullHandling()).isEqualTo(Sort.NullHandling.NATIVE);
|
||||
}
|
||||
|
||||
@EnableFeignClients(clients = InvoiceClient.class)
|
||||
@LoadBalancerClient(name = "local", configuration = LocalClientConfiguration.class)
|
||||
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-2024 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.
|
||||
@@ -39,6 +39,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
* @author Can Bezmen
|
||||
* @author Gokalp Kuscu
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SortJacksonModuleTests {
|
||||
@@ -53,7 +54,7 @@ class SortJacksonModuleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializePage() throws JsonProcessingException {
|
||||
public void testDeserializePage() throws JsonProcessingException {
|
||||
// Given
|
||||
String pageJson = "{\"content\":[\"A name\"],\"number\":1,\"size\":2,\"totalElements\":3,\"sort\":[{\"direction\":\"ASC\",\"property\":\"field\",\"ignoreCase\":false,\"nullHandling\":\"NATIVE\",\"descending\":false,\"ascending\":true}]}";
|
||||
// When
|
||||
@@ -68,6 +69,31 @@ class SortJacksonModuleTests {
|
||||
assertThat(result.getPageable().getSort(), notNullValue());
|
||||
result.getPageable().getSort();
|
||||
Optional<Sort.Order> optionalOrder = result.getPageable().getSort().get().findFirst();
|
||||
if (optionalOrder.isPresent()) {
|
||||
Sort.Order order = optionalOrder.get();
|
||||
assertThat(order, hasProperty("property", is("field")));
|
||||
assertThat(order, hasProperty("direction", is(Sort.Direction.ASC)));
|
||||
assertThat(order, hasProperty("ignoreCase", is(false)));
|
||||
assertThat(order, hasProperty("nullHandling", is(Sort.NullHandling.NATIVE)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializePageWithoutIgnoreCaseAndNullHandling() throws JsonProcessingException {
|
||||
// Given
|
||||
String pageJson = "{\"content\":[\"A name\"],\"number\":1,\"size\":2,\"totalElements\":3,\"sort\":[{\"direction\":\"ASC\",\"property\":\"field\",\"descending\":false,\"ascending\":true}]}";
|
||||
// When
|
||||
Page<?> result = objectMapper.readValue(pageJson, Page.class);
|
||||
// Then
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, hasProperty("totalElements", is(3L)));
|
||||
assertThat(result.getContent(), hasSize(1));
|
||||
assertThat(result.getPageable(), notNullValue());
|
||||
assertThat(result.getPageable().getPageNumber(), is(1));
|
||||
assertThat(result.getPageable().getPageSize(), is(2));
|
||||
assertThat(result.getPageable().getSort(), notNullValue());
|
||||
result.getPageable().getSort();
|
||||
Optional<Sort.Order> optionalOrder = result.getPageable().getSort().get().findFirst();
|
||||
if (optionalOrder.isPresent()) {
|
||||
Sort.Order order = optionalOrder.get();
|
||||
assertThat(order, hasProperty("property", is("field")));
|
||||
@@ -76,7 +102,56 @@ class SortJacksonModuleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializePage() throws IOException {
|
||||
public void testDeserializePageWithoutNullHandling() throws JsonProcessingException {
|
||||
// Given
|
||||
String pageJson = "{\"content\":[\"A name\"],\"number\":1,\"size\":2,\"totalElements\":3,\"sort\":[{\"direction\":\"ASC\",\"property\":\"field\",\"ignoreCase\":true,\"descending\":false,\"ascending\":true}]}";
|
||||
// When
|
||||
Page<?> result = objectMapper.readValue(pageJson, Page.class);
|
||||
// Then
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, hasProperty("totalElements", is(3L)));
|
||||
assertThat(result.getContent(), hasSize(1));
|
||||
assertThat(result.getPageable(), notNullValue());
|
||||
assertThat(result.getPageable().getPageNumber(), is(1));
|
||||
assertThat(result.getPageable().getPageSize(), is(2));
|
||||
assertThat(result.getPageable().getSort(), notNullValue());
|
||||
result.getPageable().getSort();
|
||||
Optional<Sort.Order> optionalOrder = result.getPageable().getSort().get().findFirst();
|
||||
if (optionalOrder.isPresent()) {
|
||||
Sort.Order order = optionalOrder.get();
|
||||
assertThat(order, hasProperty("property", is("field")));
|
||||
assertThat(order, hasProperty("direction", is(Sort.Direction.ASC)));
|
||||
assertThat(order, hasProperty("ignoreCase", is(false)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializePageWithTrueMarkedIgnoreCaseAndNullHandling() throws JsonProcessingException {
|
||||
// Given
|
||||
String pageJson = "{\"content\":[\"A name\"],\"number\":1,\"size\":2,\"totalElements\":3,\"sort\":[{\"direction\":\"ASC\",\"property\":\"field\",\"ignoreCase\":true,\"nullHandling\":\"NATIVE\",\"descending\":false,\"ascending\":true}]}";
|
||||
// When
|
||||
Page<?> result = objectMapper.readValue(pageJson, Page.class);
|
||||
// Then
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, hasProperty("totalElements", is(3L)));
|
||||
assertThat(result.getContent(), hasSize(1));
|
||||
assertThat(result.getPageable(), notNullValue());
|
||||
assertThat(result.getPageable().getPageNumber(), is(1));
|
||||
assertThat(result.getPageable().getPageSize(), is(2));
|
||||
assertThat(result.getPageable().getSort(), notNullValue());
|
||||
result.getPageable().getSort();
|
||||
Optional<Sort.Order> optionalOrder = result.getPageable().getSort().get().findFirst();
|
||||
if (optionalOrder.isPresent()) {
|
||||
Sort.Order order = optionalOrder.get();
|
||||
assertThat(order, hasProperty("property", is("field")));
|
||||
assertThat(order, hasProperty("direction", is(Sort.Direction.ASC)));
|
||||
assertThat(order, hasProperty("ignoreCase", is(true)));
|
||||
assertThat(order, hasProperty("nullHandling", is(Sort.NullHandling.NATIVE)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializePage() throws IOException {
|
||||
// Given
|
||||
Sort sort = Sort.by(Sort.Order.by("fieldName"));
|
||||
// When
|
||||
@@ -86,4 +161,16 @@ class SortJacksonModuleTests {
|
||||
assertThat(result, containsString("\"property\":\"fieldName\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializePageWithGivenIgnoreCase() throws IOException {
|
||||
// Given
|
||||
Sort sort = Sort.by(Sort.Order.by("fieldName"), Sort.Order.by("fieldName2").ignoreCase());
|
||||
// When
|
||||
String result = objectMapper.writeValueAsString(sort);
|
||||
// Then
|
||||
assertThat(result, containsString("\"direction\":\"ASC\""));
|
||||
assertThat(result, containsString("\"property\":\"fieldName\""));
|
||||
assertThat(result, containsString("\"property\":\"fieldName2\",\"ignoreCase\":true"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user