From 8eee54c5621b304af7f4775ad9c9ecff5aa7016b Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 07:11:05 +0100 Subject: [PATCH 1/9] feat: fix special parameter using the sort mapper Signed-off-by: Otavio Santana --- .../core/repository/DynamicReturn.java | 5 +- .../core/repository/SpecialParameters.java | 20 ++++++-- .../core/repository/DynamicReturnTest.java | 2 +- .../repository/SpecialParametersTest.java | 48 +++++++++++++++---- ...AbstractSemiStructuredRepositoryProxy.java | 4 +- .../query/BaseSemiStructuredRepository.java | 6 ++- .../semistructured/query/DynamicQuery.java | 6 ++- .../query/DynamicQueryTest.java | 5 +- 8 files changed, 74 insertions(+), 22 deletions(-) diff --git a/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturn.java b/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturn.java index 68eca34e7..c9ee8edd2 100644 --- a/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturn.java +++ b/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturn.java @@ -57,13 +57,14 @@ public static Function>, Supplier>> toSingleResul * Finds {@link SpecialParameters} from array object * * @param params the params + * @param sortParser the sort parser * @return a {@link SpecialParameters} instance */ - public static SpecialParameters findSpecialParameters(Object[] params) { + public static SpecialParameters findSpecialParameters(Object[] params, Function sortParser) { if (params == null || params.length == 0) { return SpecialParameters.EMPTY; } - return SpecialParameters.of(params); + return SpecialParameters.of(params, sortParser); } /** diff --git a/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java b/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java index 629b2c022..0a40529f0 100644 --- a/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java +++ b/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.function.Function; /** * The repository features has support for specific types like PageRequest and Sort, @@ -124,23 +125,23 @@ public String toString() { '}'; } - static SpecialParameters of(Object[] parameters) { + static SpecialParameters of(Object[] parameters, Function sortParser) { List> sorts = new ArrayList<>(); PageRequest pageRequest = null; Limit limit = null; for (Object parameter : parameters) { if (parameter instanceof Sort sort) { - sorts.add(sort); + sorts.add(mapper(sort, sortParser)); } else if (parameter instanceof Limit limitInstance) { limit = limitInstance; } else if (parameter instanceof Order order) { - order.iterator().forEachRemaining(sorts::add); + order.sorts().stream().map(s -> mapper(s, sortParser)).forEach(sorts::add); } else if (parameter instanceof PageRequest request) { pageRequest = request; } else if (parameter instanceof Iterable iterable) { for (Object value : iterable) { if (value instanceof Sort sortValue) { - sorts.add(sortValue); + sorts.add(mapper(sortValue, sortParser)); } } } @@ -193,4 +194,15 @@ public static boolean isSpecialParameter(Class parameter) { public static boolean isNotSpecialParameter(Class parameter) { return !isSpecialParameter(parameter); } + + /** + * Returns the sort with the property updated from the sort parser + * @param sort the sort + * @param sortParser the sort parser + * @return the special parameters + */ + private static Sort mapper(Sort sort, Function sortParser) { + var property = sortParser.apply(sort.property()); + return sort.isAscending()? Sort.asc(property): Sort.desc(property); + } } diff --git a/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturnTest.java b/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturnTest.java index 536a7f807..af0954de3 100644 --- a/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturnTest.java +++ b/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/DynamicReturnTest.java @@ -1 +1 @@ -/* * Copyright (c) 2022 Contributors to the Eclipse Foundation * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. * * You may elect to redistribute this code under either of these licenses. * * Contributors: * * Otavio Santana */ package org.eclipse.jnosql.mapping.core.repository; import jakarta.data.exceptions.NonUniqueResultException; import jakarta.data.repository.CrudRepository; import jakarta.data.page.Page; import jakarta.data.page.PageRequest; import org.eclipse.jnosql.mapping.DynamicQueryException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.Collection; import java.util.Deque; import java.util.List; import java.util.NavigableSet; import java.util.Optional; import java.util.Queue; import java.util.Set; import java.util.SortedSet; import java.util.function.Supplier; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; class DynamicReturnTest { @Test void shouldReturnNPEWhenThereIsPagination() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = Stream::empty; Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); assertThrows(NullPointerException.class, () -> DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult) .withPagination(PageRequest.ofPage(1L).size(2)).build()); } @Test void shouldReturnEmptyOptional() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = Stream::empty; Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Optional); Optional optional = (Optional) execute; Assertions.assertFalse(optional.isPresent()); } @Test void shouldReturnOptional() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Optional); Optional optional = (Optional) execute; assertTrue(optional.isPresent()); Assertions.assertEquals(new Person("Ada"), optional.get()); } @Test void shouldReturnOptionalError() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = () -> Stream.of(new Person("Poliana"), new Person("Otavio")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); assertThrows(NonUniqueResultException.class, dynamicReturn::execute); } @Test void shouldReturnAnInstance() { Method method = getMethod(PersonRepository.class, "getInstance"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Person); Person person = (Person) execute; Assertions.assertEquals(new Person("Ada"), person); } @Test void shouldReturnNull() { Method method = getMethod(PersonRepository.class, "getInstance"); Supplier> stream = Stream::empty; Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertNull(execute); } @Test void shouldReturnList() { Method method = getMethod(PersonRepository.class, "getList"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof List); List persons = (List) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.get(0)); } @Test void shouldReturnIterable() { Method method = getMethod(PersonRepository.class, "getIterable"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Iterable); Iterable persons = (List) execute; Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnCollection() { Method method = getMethod(PersonRepository.class, "getCollection"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Collection); Collection persons = (Collection) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnSet() { Method method = getMethod(PersonRepository.class, "getSet"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Set); Set persons = (Set) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnQueue() { Method method = getMethod(PersonRepository.class, "getQueue"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Queue); Queue persons = (Queue) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnStream() { Method method = getMethod(PersonRepository.class, "getStream"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Stream); Stream persons = (Stream) execute; Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnSortedSet() { Method method = getMethod(PersonRepository.class, "getSortedSet"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof SortedSet); SortedSet persons = (SortedSet) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnNavigableSet() { Method method = getMethod(PersonRepository.class, "getNavigableSet"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof NavigableSet); NavigableSet persons = (NavigableSet) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnDeque() { Method method = getMethod(PersonRepository.class, "getDeque"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Deque); Deque persons = (Deque) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnErrorWhenExecutePage() { Method method = getMethod(PersonRepository.class, "getPage"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); assertThrows(DynamicQueryException.class, dynamicReturn::execute); } @Test void shouldReturnErrorNavigableSetEntityIsNotComparable() { Method method = getMethod(AnimalRepository.class, "getSortedSet"); Supplier> stream = () -> Stream.of(new Animal("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Animal.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); assertThrows(DynamicQueryException.class, dynamicReturn::execute); } @Test void shouldReturnNullWhenParamIsEmptyOnFindSpecial() { assertTrue(DynamicReturn.findSpecialParameters(null).isEmpty()); assertTrue(DynamicReturn.findSpecialParameters(new Object[0]).isEmpty()); } @Test void shouldFindSpecial() { PageRequest pageRequest = PageRequest.ofPage(1L).size(2); SpecialParameters specialParameters = DynamicReturn.findSpecialParameters(new Object[]{"value", 23, pageRequest}); Assertions.assertEquals(pageRequest, specialParameters.pageRequest().orElseThrow()); } @Test void shouldReturnNullWhenThereIsNotSpecial() { SpecialParameters pagination = DynamicReturn.findSpecialParameters(new Object[]{"value", 23, BigDecimal.TEN}); assertTrue(pagination.isEmpty()); } // @Test void shouldReturnNullWhenParamIsEmptyOnFindPagination() { assertNull(DynamicReturn.findPageRequest(null)); assertNull(DynamicReturn.findPageRequest(new Object[0])); } @Test void shouldFindPagination() { PageRequest pageRequest = PageRequest.ofPage(1L).size(2); PageRequest pageRequest2 = DynamicReturn.findPageRequest(new Object[]{"value", 23, pageRequest}); Assertions.assertEquals(pageRequest, pageRequest2); } @Test void shouldReturnNullWhenThereIsNotPagination() { PageRequest pageRequest = DynamicReturn.findPageRequest(new Object[]{"value", 23, BigDecimal.TEN}); assertNull(pageRequest); } private Method getMethod(Class repository, String methodName) { return Stream.of(repository.getDeclaredMethods()) .filter(m -> m.getName().equals(methodName)) .findFirst().get(); } private record Animal(String name) { } private record Person(String name) implements Comparable { @Override public int compareTo(Person o) { return name.compareTo(o.name); } } private interface AnimalRepository extends CrudRepository { SortedSet getSortedSet(); } private interface PersonRepository extends CrudRepository { Optional getOptional(); Person getInstance(); List getList(); Iterable getIterable(); Collection getCollection(); Set getSet(); Queue getQueue(); Stream getStream(); SortedSet getSortedSet(); NavigableSet getNavigableSet(); Deque getDeque(); Page getPage(); } } \ No newline at end of file +/* * Copyright (c) 2022 Contributors to the Eclipse Foundation * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. * * You may elect to redistribute this code under either of these licenses. * * Contributors: * * Otavio Santana */ package org.eclipse.jnosql.mapping.core.repository; import jakarta.data.exceptions.NonUniqueResultException; import jakarta.data.repository.CrudRepository; import jakarta.data.page.Page; import jakarta.data.page.PageRequest; import org.eclipse.jnosql.mapping.DynamicQueryException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.Collection; import java.util.Deque; import java.util.List; import java.util.NavigableSet; import java.util.Optional; import java.util.Queue; import java.util.Set; import java.util.SortedSet; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; class DynamicReturnTest { private static final Function SORT_MAPPER = Function.identity(); @Test void shouldReturnNPEWhenThereIsPagination() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = Stream::empty; Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); assertThrows(NullPointerException.class, () -> DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult) .withPagination(PageRequest.ofPage(1L).size(2)).build()); } @Test void shouldReturnEmptyOptional() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = Stream::empty; Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Optional); Optional optional = (Optional) execute; Assertions.assertFalse(optional.isPresent()); } @Test void shouldReturnOptional() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Optional); Optional optional = (Optional) execute; assertTrue(optional.isPresent()); Assertions.assertEquals(new Person("Ada"), optional.get()); } @Test void shouldReturnOptionalError() { Method method = getMethod(PersonRepository.class, "getOptional"); Supplier> stream = () -> Stream.of(new Person("Poliana"), new Person("Otavio")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); assertThrows(NonUniqueResultException.class, dynamicReturn::execute); } @Test void shouldReturnAnInstance() { Method method = getMethod(PersonRepository.class, "getInstance"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Person); Person person = (Person) execute; Assertions.assertEquals(new Person("Ada"), person); } @Test void shouldReturnNull() { Method method = getMethod(PersonRepository.class, "getInstance"); Supplier> stream = Stream::empty; Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertNull(execute); } @Test void shouldReturnList() { Method method = getMethod(PersonRepository.class, "getList"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof List); List persons = (List) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.get(0)); } @Test void shouldReturnIterable() { Method method = getMethod(PersonRepository.class, "getIterable"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Iterable); Iterable persons = (List) execute; Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnCollection() { Method method = getMethod(PersonRepository.class, "getCollection"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Collection); Collection persons = (Collection) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnSet() { Method method = getMethod(PersonRepository.class, "getSet"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Set); Set persons = (Set) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnQueue() { Method method = getMethod(PersonRepository.class, "getQueue"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Queue); Queue persons = (Queue) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnStream() { Method method = getMethod(PersonRepository.class, "getStream"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Stream); Stream persons = (Stream) execute; Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnSortedSet() { Method method = getMethod(PersonRepository.class, "getSortedSet"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof SortedSet); SortedSet persons = (SortedSet) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnNavigableSet() { Method method = getMethod(PersonRepository.class, "getNavigableSet"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof NavigableSet); NavigableSet persons = (NavigableSet) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnDeque() { Method method = getMethod(PersonRepository.class, "getDeque"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); Object execute = dynamicReturn.execute(); assertTrue(execute instanceof Deque); Deque persons = (Deque) execute; Assertions.assertFalse(persons.isEmpty()); Assertions.assertEquals(new Person("Ada"), persons.iterator().next()); } @Test void shouldReturnErrorWhenExecutePage() { Method method = getMethod(PersonRepository.class, "getPage"); Supplier> stream = () -> Stream.of(new Person("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Person.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); assertThrows(DynamicQueryException.class, dynamicReturn::execute); } @Test void shouldReturnErrorNavigableSetEntityIsNotComparable() { Method method = getMethod(AnimalRepository.class, "getSortedSet"); Supplier> stream = () -> Stream.of(new Animal("Ada")); Supplier> singleResult = DynamicReturn.toSingleResult(method).apply(stream); DynamicReturn dynamicReturn = DynamicReturn.builder() .withClassSource(Animal.class) .withMethodSource(method).withResult(stream) .withSingleResult(singleResult).build(); assertThrows(DynamicQueryException.class, dynamicReturn::execute); } @Test void shouldReturnNullWhenParamIsEmptyOnFindSpecial() { assertTrue(DynamicReturn.findSpecialParameters(null, SORT_MAPPER).isEmpty()); assertTrue(DynamicReturn.findSpecialParameters(new Object[0], SORT_MAPPER).isEmpty()); } @Test void shouldFindSpecial() { PageRequest pageRequest = PageRequest.ofPage(1L).size(2); SpecialParameters specialParameters = DynamicReturn.findSpecialParameters(new Object[]{"value", 23, pageRequest}, SORT_MAPPER); Assertions.assertEquals(pageRequest, specialParameters.pageRequest().orElseThrow()); } @Test void shouldReturnNullWhenThereIsNotSpecial() { SpecialParameters pagination = DynamicReturn.findSpecialParameters(new Object[]{"value", 23, BigDecimal.TEN}, SORT_MAPPER); assertTrue(pagination.isEmpty()); } @Test void shouldReturnNullWhenParamIsEmptyOnFindPagination() { assertNull(DynamicReturn.findPageRequest(null)); assertNull(DynamicReturn.findPageRequest(new Object[0])); } @Test void shouldFindPagination() { PageRequest pageRequest = PageRequest.ofPage(1L).size(2); PageRequest pageRequest2 = DynamicReturn.findPageRequest(new Object[]{"value", 23, pageRequest}); Assertions.assertEquals(pageRequest, pageRequest2); } @Test void shouldReturnNullWhenThereIsNotPagination() { PageRequest pageRequest = DynamicReturn.findPageRequest(new Object[]{"value", 23, BigDecimal.TEN}); assertNull(pageRequest); } private Method getMethod(Class repository, String methodName) { return Stream.of(repository.getDeclaredMethods()) .filter(m -> m.getName().equals(methodName)) .findFirst().get(); } private record Animal(String name) { } private record Person(String name) implements Comparable { @Override public int compareTo(Person o) { return name.compareTo(o.name); } } private interface AnimalRepository extends CrudRepository { SortedSet getSortedSet(); } private interface PersonRepository extends CrudRepository { Optional getOptional(); Person getInstance(); List getList(); Iterable getIterable(); Collection getCollection(); Set getSet(); Queue getQueue(); Stream getStream(); SortedSet getSortedSet(); NavigableSet getNavigableSet(); Deque getDeque(); Page getPage(); } } \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java b/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java index 0f3b372d4..9afa7ab7e 100644 --- a/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java +++ b/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java @@ -28,6 +28,7 @@ import java.math.BigDecimal; import java.util.List; import java.util.Optional; +import java.util.function.Function; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -36,22 +37,24 @@ class SpecialParametersTest { + private static final Function SORT_MAPPER = Function.identity(); + @Test void shouldReturnEmpty() { - SpecialParameters parameters = SpecialParameters.of(new Object[0]); + SpecialParameters parameters = SpecialParameters.of(new Object[0], SORT_MAPPER); assertTrue(parameters.isEmpty()); } @Test void shouldReturnEmptyNonSpecialParameters() { - SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio"}); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio"}, SORT_MAPPER); assertTrue(parameters.isEmpty()); } @Test void shouldReturnPageRequest() { PageRequest pageRequest = PageRequest.ofPage(10); - SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", pageRequest}); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", pageRequest}, SORT_MAPPER); assertFalse(parameters.isEmpty()); Assertions.assertEquals(pageRequest, parameters.pageRequest().orElseThrow()); assertTrue(parameters.isSortEmpty()); @@ -60,7 +63,7 @@ void shouldReturnPageRequest() { @Test void shouldReturnSort() { Sort sort = Sort.asc("name"); - SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", sort}); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", sort}, SORT_MAPPER); assertFalse(parameters.isEmpty()); assertTrue(parameters.hasOnlySort()); assertTrue(parameters.pageRequest().isEmpty()); @@ -74,7 +77,7 @@ void shouldKeepOrder() { Sort sort = Sort.asc("name"); PageRequest pageRequest = PageRequest.ofPage(10); - SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", sort, pageRequest}); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", sort, pageRequest}, SORT_MAPPER); assertFalse(parameters.isEmpty()); assertFalse(parameters.hasOnlySort()); Assertions.assertEquals(pageRequest, parameters.pageRequest().orElseThrow()); @@ -85,7 +88,7 @@ void shouldKeepOrder() { @Test void shouldReturnLimit() { - SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", Limit.of(10)}); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", Limit.of(10)}, SORT_MAPPER); assertFalse(parameters.isEmpty()); Optional limit = parameters.limit(); assertTrue(limit.isPresent()); @@ -97,7 +100,7 @@ void shouldReturnLimit() { @Test void shouldReturnIterableSort(){ SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", - List.of(Sort.asc("name"), Sort.desc("age"))}); + List.of(Sort.asc("name"), Sort.desc("age"))}, SORT_MAPPER); assertFalse(parameters.isEmpty()); assertThat(parameters.sorts()).hasSize(2) .containsExactly(Sort.asc("name"), @@ -107,7 +110,7 @@ void shouldReturnIterableSort(){ @Test void shouldReturnOrder(){ Order order = Order.by(Sort.asc("name"), Sort.desc("age")); - SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", order}); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", order}, SORT_MAPPER); assertFalse(parameters.isEmpty()); assertFalse(parameters.isSortEmpty()); assertThat(parameters.sorts()).hasSize(2) @@ -120,7 +123,7 @@ void shouldReturnIterableOrder(){ PageRequest pageRequest = PageRequest.ofPage(10); Order order = Order.by(Sort.asc("name")); SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", - List.of(Sort.asc("name"), Sort.desc("age")), pageRequest, order}); + List.of(Sort.asc("name"), Sort.desc("age")), pageRequest, order}, SORT_MAPPER); assertFalse(parameters.isEmpty()); Assertions.assertEquals(pageRequest, parameters.pageRequest().orElseThrow()); assertFalse(parameters.isSortEmpty()); @@ -129,6 +132,33 @@ void shouldReturnIterableOrder(){ Sort.desc("age")); } + @Test + void shouldReturnOrderMapper(){ + Function upper = String::toUpperCase; + Order order = Order.by(Sort.asc("name"), Sort.desc("age")); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", order}, upper); + assertFalse(parameters.isEmpty()); + assertFalse(parameters.isSortEmpty()); + assertThat(parameters.sorts()).hasSize(2) + .contains(Sort.asc("NAME"), + Sort.desc("AGE")); + } + + @Test + void shouldReturnIterableOrderMapper(){ + Function upper = String::toUpperCase; + PageRequest pageRequest = PageRequest.ofPage(10); + Order order = Order.by(Sort.asc("name")); + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", + List.of(Sort.asc("name"), Sort.desc("age")), pageRequest, order}, upper); + assertFalse(parameters.isEmpty()); + Assertions.assertEquals(pageRequest, parameters.pageRequest().orElseThrow()); + assertFalse(parameters.isSortEmpty()); + assertThat(parameters.sorts()).hasSize(3) + .contains(Sort.asc("NAME"), + Sort.desc("AGE")); + } + @ParameterizedTest @ValueSource(classes = {Sort.class, Limit.class, PageRequest.class, Order.class}) void shouldReturnTrueSpecialParameter(Class type){ diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/AbstractSemiStructuredRepositoryProxy.java b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/AbstractSemiStructuredRepositoryProxy.java index 279c6b748..6af62f4f7 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/AbstractSemiStructuredRepositoryProxy.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/AbstractSemiStructuredRepositoryProxy.java @@ -56,14 +56,14 @@ protected Object executeQuery(Object instance, Method method, Object[] params) { protected Object executeCursorPagination(Object instance, Method method, Object[] params) { if (method.getAnnotation(Find.class) == null) { var query = query(method, params); - SpecialParameters special = DynamicReturn.findSpecialParameters(params); + SpecialParameters special = DynamicReturn.findSpecialParameters(params, sortParser()); PageRequest pageRequest = special.pageRequest() .orElseThrow(() -> new IllegalArgumentException("Pageable is required in the method signature as parameter at " + method)); return this.template().selectCursor(query, pageRequest); } else { Map parameters = RepositoryReflectionUtils.INSTANCE.getBy(method, params); var query = SemiStructuredParameterBasedQuery.INSTANCE.toQuery(parameters, getSorts(method, entityMetadata()), entityMetadata()); - SpecialParameters special = DynamicReturn.findSpecialParameters(params); + SpecialParameters special = DynamicReturn.findSpecialParameters(params, sortParser()); PageRequest pageRequest = special.pageRequest() .orElseThrow(() -> new IllegalArgumentException("Pageable is required in the method signature as parameter at " + method)); return this.template().selectCursor(query, pageRequest); diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/BaseSemiStructuredRepository.java b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/BaseSemiStructuredRepository.java index 3c7c7865c..704faf751 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/BaseSemiStructuredRepository.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/BaseSemiStructuredRepository.java @@ -202,7 +202,7 @@ protected Function> streamPagination(org.eclipse.jnosql.c protected org.eclipse.jnosql.communication.semistructured.SelectQuery updateQueryDynamically(Object[] args, org.eclipse.jnosql.communication.semistructured.SelectQuery query) { var documentQuery = includeInheritance(query); - SpecialParameters special = DynamicReturn.findSpecialParameters(args); + SpecialParameters special = DynamicReturn.findSpecialParameters(args, sortParser()); if (special.isEmpty()) { return documentQuery; @@ -243,5 +243,9 @@ protected org.eclipse.jnosql.communication.semistructured.SelectQuery updateQuer }).orElse(documentQuery); } + protected Function sortParser() { + return property -> parser().fireField(entityMetadata().name(), property); + } + } diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQuery.java b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQuery.java index 305c562b4..4199bef88 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQuery.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQuery.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.function.Function; import java.util.function.Supplier; /** @@ -90,12 +91,13 @@ public SelectQuery get() { * Creates a {@link DynamicQuery} instance * @param args the method parameters * @param query the column query + * @param sortParser the sort parser * @return the {@link DynamicQuery} instance * @throws NullPointerException when either args or query are null */ - public static DynamicQuery of(Object[] args, SelectQuery query) { + public static DynamicQuery of(Object[] args, SelectQuery query, Function sortParser) { Objects.requireNonNull(args, "args is required"); Objects.requireNonNull(query, "query is required"); - return new DynamicQuery(DynamicReturn.findSpecialParameters(args), query); + return new DynamicQuery(DynamicReturn.findSpecialParameters(args, sortParser), query); } } diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQueryTest.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQueryTest.java index cb93f0736..ab52253cc 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQueryTest.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/DynamicQueryTest.java @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.function.Function; import static org.assertj.core.api.SoftAssertions.assertSoftly; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -139,8 +140,10 @@ void shouldReturnWhenThereIsLimitAndSort(){ when(query.skip()).thenReturn(0L); when(query.limit()).thenReturn(10L); + Function sortParser = Function.identity(); + DynamicQuery dynamicQuery = DynamicQuery.of(new Object[]{Sort.asc("name"), Limit.of(20)} - , query); + , query, sortParser); SelectQuery columnQuery = dynamicQuery.get(); assertEquals("sampleQuery", columnQuery.name()); From 67e82fb91e3359d03ed8cacc8e100fc22b2c3c3a Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 07:15:15 +0100 Subject: [PATCH 2/9] feat: add support to array Signed-off-by: Otavio Santana --- .../mapping/core/repository/SpecialParameters.java | 3 +++ .../mapping/core/repository/SpecialParametersTest.java | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java b/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java index 0a40529f0..25f393f7f 100644 --- a/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java +++ b/jnosql-mapping/jnosql-mapping-core/src/main/java/org/eclipse/jnosql/mapping/core/repository/SpecialParameters.java @@ -21,6 +21,7 @@ import jakarta.data.Sort; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -136,6 +137,8 @@ static SpecialParameters of(Object[] parameters, Function sortPa limit = limitInstance; } else if (parameter instanceof Order order) { order.sorts().stream().map(s -> mapper(s, sortParser)).forEach(sorts::add); + } else if(parameter instanceof Sort[] sortArray){ + Arrays.stream(sortArray).map(s -> mapper(s, sortParser)).forEach(sorts::add); } else if (parameter instanceof PageRequest request) { pageRequest = request; } else if (parameter instanceof Iterable iterable) { diff --git a/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java b/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java index 9afa7ab7e..90ea1d3be 100644 --- a/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java +++ b/jnosql-mapping/jnosql-mapping-core/src/test/java/org/eclipse/jnosql/mapping/core/repository/SpecialParametersTest.java @@ -132,6 +132,16 @@ void shouldReturnIterableOrder(){ Sort.desc("age")); } + @Test + void shouldReturnArrayOrder(){ + SpecialParameters parameters = SpecialParameters.of(new Object[]{10, "Otavio", + new Sort[]{Sort.asc("name"), Sort.desc("age")}}, SORT_MAPPER); + assertFalse(parameters.isEmpty()); + assertThat(parameters.sorts()).hasSize(2) + .containsExactly(Sort.asc("name"), + Sort.desc("age")); + } + @Test void shouldReturnOrderMapper(){ Function upper = String::toUpperCase; From 68f4d54431f9fbf71a2e5f98c279564ab527ecb0 Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 16:56:55 +0100 Subject: [PATCH 3/9] chore: update ignorecase keyword Signed-off-by: Otavio Santana --- .../jnosql/query/grammar/method/Method.g4 | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 b/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 index 835cbaff6..26ddd9fe6 100644 --- a/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 +++ b/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 @@ -14,18 +14,19 @@ asc: 'Asc'; desc: 'Desc'; truth: variable 'True'; untruth: variable 'False'; -eq: variable | variable not? 'Equals'| variable not; -gt: variable not? 'GreaterThan'; -gte: variable not? 'GreaterThanEqual'; -lt: variable not? 'LessThan'; -lte: variable not? 'LessThanEqual'; -between: variable not? 'Between'; -in: variable not? 'In'; -like: variable not? 'Like'; -contains: variable not? 'Contains'; -endsWith: variable not? 'EndsWith'; -startsWith: variable not? 'StartsWith'; -nullable: variable not? 'Null'; +eq: variable | variable ignoreCase? not? 'Equals'| variable not; +gt: variable ignoreCase? not? 'GreaterThan'; +gte: variable ignoreCase? not? 'GreaterThanEqual'; +lt: variable ignoreCase? not? 'LessThan'; +lte: variable ignoreCase? not? 'LessThanEqual'; +between: variable ignoreCase? not? 'Between'; +in: variable ignoreCase? not? 'In'; +like: variable ignoreCase? not? 'Like'; +contains: variable ignoreCase? not? 'Contains'; +endsWith: variable ignoreCase? not? 'EndsWith'; +startsWith: variable ignoreCase? not? 'StartsWith'; +nullable: variable ignoreCase? not? 'Null'; +ignoreCase: 'IgnoreCase'; not: 'Not'; variable: ANY_NAME; max: INT; From 2ece94b1c498642cadbcf4837d2e95d8688c62f9 Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 18:02:12 +0100 Subject: [PATCH 4/9] feat: include ignore case at method query Signed-off-by: Otavio Santana --- .../query/method/AbstractMethodQueryProvider.java | 5 +++++ .../jnosql/communication/query/method/MethodQuery.java | 2 +- .../query/method/SelectMethodQueryProviderTest.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/AbstractMethodQueryProvider.java b/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/AbstractMethodQueryProvider.java index 1f6144960..1b4fb3aa4 100644 --- a/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/AbstractMethodQueryProvider.java +++ b/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/AbstractMethodQueryProvider.java @@ -198,6 +198,11 @@ public void exitStartsWith(MethodParser.StartsWithContext ctx) { throw new UnsupportedOperationException("StartsWith is not supported in Eclipse JNoSQL method query"); } + @Override + public void exitIgnoreCase(MethodParser.IgnoreCaseContext ctx) { + throw new UnsupportedOperationException("IgnoreCase is not supported in Eclipse JNoSQL method query"); + } + private void appendCondition(boolean hasNot, String variable, Condition operator) { ParamQueryValue queryValue = new MethodParamQueryValue(variable); checkCondition(new MethodCondition(variable, operator, queryValue), hasNot); diff --git a/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/MethodQuery.java b/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/MethodQuery.java index 86c928831..1907eac16 100644 --- a/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/MethodQuery.java +++ b/jnosql-communication/jnosql-communication-query/src/main/java/org/eclipse/jnosql/communication/query/method/MethodQuery.java @@ -22,7 +22,7 @@ public final class MethodQuery implements Supplier { private final String value; private static final Pattern PATTERN = Pattern.compile("findBy|deleteBy|countAll|countBy|existsBy|" - + "OrderBy|First(?=\\d+By)|(?<=First\\d{1,})By|" + + "OrderBy|First(?=\\d+By)|(?<=First\\d{1,})By|IgnoreCase|" + "And|Or(?!der)|Null|Not|Equals|GreaterThanEqual|True|False|Contains|EndsWith|StartsWith|" + "LessThanEqual|GreaterThan|LessThan|Between|In|Like|Asc|Desc"); private static final Map CACHE = Collections.synchronizedMap(new WeakHashMap<>()); diff --git a/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java b/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java index fbb0c5e06..53630a4d2 100644 --- a/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java +++ b/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java @@ -539,7 +539,7 @@ void shouldReturnParserQuery37(String query) { } @ParameterizedTest(name = "Should parser the query {0}") - @ValueSource(strings = {"findByNameContains", "findByNameEndsWith", "findByNameStartsWith"}) + @ValueSource(strings = {"findByNameContains", "findByNameEndsWith", "findByNameStartsWith", "findByStreetNameIgnoreCaseLike"}) void shouldReturnUnsupportedOperationExceptionQuery(String query) { String entity = "entity"; Assertions.assertThrows(UnsupportedOperationException.class, () -> queryProvider.apply(query, entity)); From 3e42f191825c9b215b08c349e93ad4c7bc1a129c Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 18:29:08 +0100 Subject: [PATCH 5/9] chore: fix ignore case Signed-off-by: Otavio Santana --- .../query/method/SelectMethodQueryProviderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java b/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java index 53630a4d2..3332114d0 100644 --- a/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java +++ b/jnosql-communication/jnosql-communication-query/src/test/java/org/eclipse/jnosql/communication/query/method/SelectMethodQueryProviderTest.java @@ -539,14 +539,14 @@ void shouldReturnParserQuery37(String query) { } @ParameterizedTest(name = "Should parser the query {0}") - @ValueSource(strings = {"findByNameContains", "findByNameEndsWith", "findByNameStartsWith", "findByStreetNameIgnoreCaseLike"}) + @ValueSource(strings = {"findByNameContains", "findByNameEndsWith", "findByNameStartsWith", "findByStreetNameIgnoreCaseLike", "findByHexadecimalIgnoreCase"}) void shouldReturnUnsupportedOperationExceptionQuery(String query) { String entity = "entity"; Assertions.assertThrows(UnsupportedOperationException.class, () -> queryProvider.apply(query, entity)); } @ParameterizedTest(name = "Should parser the query {0}") - @ValueSource(strings = {"findByNameNotContains", "findByNameNotEndsWith", "findByNameNotStartsWith"}) + @ValueSource(strings = {"findByNameNotContains", "findByNameNotEndsWith", "findByNameNotStartsWith", "findByStreetNameIgnoreCaseNotLike", "findByHexadecimalIgnoreCaseNot"}) void shouldReturnUnsupportedOperationExceptionQueryWithNegation(String query) { String entity = "entity"; Assertions.assertThrows(UnsupportedOperationException.class, () -> queryProvider.apply(query, entity)); From 7b749abb51ab32ff08c300f02d0199b55ccba1f9 Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 18:29:57 +0100 Subject: [PATCH 6/9] chore: update method query Signed-off-by: Otavio Santana --- antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 b/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 index 26ddd9fe6..efddf9faf 100644 --- a/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 +++ b/antlr4/org/eclipse/jnosql/query/grammar/method/Method.g4 @@ -14,7 +14,7 @@ asc: 'Asc'; desc: 'Desc'; truth: variable 'True'; untruth: variable 'False'; -eq: variable | variable ignoreCase? not? 'Equals'| variable not; +eq: variable | variable ignoreCase? not? 'Equals'?; gt: variable ignoreCase? not? 'GreaterThan'; gte: variable ignoreCase? not? 'GreaterThanEqual'; lt: variable ignoreCase? not? 'LessThan'; From 9a6aff92261a58f0503f718be432e7367db22c27 Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 18:38:21 +0100 Subject: [PATCH 7/9] feat: update semistructure template Signed-off-by: Otavio Santana --- .../semistructured/AbstractSemiStructuredTemplate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/AbstractSemiStructuredTemplate.java b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/AbstractSemiStructuredTemplate.java index 804d8a469..e65be7401 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/AbstractSemiStructuredTemplate.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/AbstractSemiStructuredTemplate.java @@ -271,8 +271,8 @@ public org.eclipse.jnosql.mapping.PreparedStatement prepare(String query, String @Override - public long count(String columnFamily) { - return manager().count(columnFamily); + public long count(String entity) { + return manager().count(entity); } From 6935c7e9330f49a660addef67531561380681523 Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 18:45:44 +0100 Subject: [PATCH 8/9] feat: create parser to query empty Signed-off-by: Otavio Santana --- .../jnosql/communication/semistructured/QueryParser.java | 7 ++++--- .../mapping/semistructured/query/RepositoryProxyTest.java | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java b/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java index 8d3e7468c..0eff5648b 100644 --- a/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java +++ b/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java @@ -12,6 +12,7 @@ import org.eclipse.jnosql.communication.QueryException; +import java.util.Locale; import java.util.Objects; import java.util.stream.Stream; @@ -69,6 +70,9 @@ public CommunicationPreparedStatement prepare(String query, String entity, Datab } private String extractQueryCommand(String query){ + if(query.length() < 6){ + return ""; + } return query.substring(0, 6).toUpperCase(); } @@ -76,8 +80,5 @@ private void validation(String query, DatabaseManager manager, CommunicationObse Objects.requireNonNull(query, "query is required"); Objects.requireNonNull(manager, "manager is required"); Objects.requireNonNull(observer, "manager is observer"); - if (query.length() < 6) { - throw new QueryException(String.format("The query %s is invalid", query)); - } } } \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/RepositoryProxyTest.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/RepositoryProxyTest.java index 66da02d84..23ea22944 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/RepositoryProxyTest.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/query/RepositoryProxyTest.java @@ -1036,6 +1036,9 @@ default Map> partcionate(String name) { @Query("FROM Person") Optional findByQuery(); + @Query(" ") + Optional all(); + @Query("FROM Person WHERE id = :id") Optional findByQuery(@Param("id") String id); From 979445ecce21b2e4b2e65ca1ddd3d5c0e33c53db Mon Sep 17 00:00:00 2001 From: Otavio Santana Date: Sun, 30 Jun 2024 18:46:29 +0100 Subject: [PATCH 9/9] feat: remove unsed import Signed-off-by: Otavio Santana --- .../eclipse/jnosql/communication/semistructured/QueryParser.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java b/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java index 0eff5648b..fb0212f79 100644 --- a/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java +++ b/jnosql-communication/jnosql-communication-semistructured/src/main/java/org/eclipse/jnosql/communication/semistructured/QueryParser.java @@ -12,7 +12,6 @@ import org.eclipse.jnosql.communication.QueryException; -import java.util.Locale; import java.util.Objects; import java.util.stream.Stream;