diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java index 069a0ce37218d..f760406597d23 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/DataAccessImplementor.java @@ -17,6 +17,15 @@ public interface DataAccessImplementor { */ ResultHandle findById(BytecodeCreator creator, ResultHandle id); + /** + * Find all entities. + * + * @param creator Bytecode creator that should be used for implementation. + * @param page Page instance that should be used in a query. Might be null if pagination is disabled. + * @return Entity list + */ + ResultHandle findAll(BytecodeCreator creator, ResultHandle page); + /** * Find all entities. * diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java index 04f824153411f..3723ca87777cb 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/EntityDataAccessImplementor.java @@ -33,6 +33,17 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { id); } + /** + * Implements Entity.findAll().page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeStaticMethod(ofMethod(entityClassName, "findAll", PanacheQuery.class)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, + page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + /** * Implements Entity.findAll(sort).page(page).list() */ diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java index 49997b76595b2..ae3cd68ed94e3 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/RepositoryDataAccessImplementor.java @@ -38,6 +38,17 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { getRepositoryInstance(creator), id); } + /** + * Implements repository.findAll().page(page).list() + */ + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeInterfaceMethod( + ofMethod(PanacheRepositoryBase.class, "findAll", PanacheQuery.class), getRepositoryInstance(creator)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + /** * Implements repository.findAll(sort).page(page).list() */ diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java index f86b8c7533432..60e005c095306 100644 --- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/main/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/ResourceImplementor.java @@ -1,5 +1,7 @@ package io.quarkus.hibernate.orm.rest.data.panache.deployment; +import static io.quarkus.gizmo.MethodDescriptor.ofMethod; + import java.util.List; import javax.enterprise.context.ApplicationScoped; @@ -8,6 +10,7 @@ import org.jboss.jandex.FieldInfo; import org.jboss.logging.Logger; +import io.quarkus.gizmo.BranchResult; import io.quarkus.gizmo.BytecodeCreator; import io.quarkus.gizmo.ClassCreator; import io.quarkus.gizmo.ClassOutput; @@ -65,7 +68,13 @@ private void implementList(ClassCreator classCreator, DataAccessImplementor data MethodCreator methodCreator = classCreator.getMethodCreator("list", List.class, Page.class, Sort.class); ResultHandle page = methodCreator.getMethodParam(0); ResultHandle sort = methodCreator.getMethodParam(1); - methodCreator.returnValue(dataAccessImplementor.findAll(methodCreator, page, sort)); + ResultHandle columns = methodCreator.invokeVirtualMethod(ofMethod(Sort.class, "getColumns", List.class), sort); + ResultHandle isEmptySort = methodCreator.invokeInterfaceMethod(ofMethod(List.class, "isEmpty", boolean.class), columns); + + BranchResult isEmptySortBranch = methodCreator.ifTrue(isEmptySort); + isEmptySortBranch.trueBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.trueBranch(), page)); + isEmptySortBranch.falseBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.falseBranch(), page, sort)); + methodCreator.close(); } diff --git a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/DataAccessImplementor.java b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/DataAccessImplementor.java index f745813d58d1a..85c3a156a63ba 100644 --- a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/DataAccessImplementor.java +++ b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/DataAccessImplementor.java @@ -17,6 +17,15 @@ public interface DataAccessImplementor { */ ResultHandle findById(BytecodeCreator creator, ResultHandle id); + /** + * Find all entities. + * + * @param creator Bytecode creator that should be used for implementation. + * @param page Page instance that should be used in a query. Might be null if pagination is disabled. + * @return Entity list + */ + ResultHandle findAll(BytecodeCreator creator, ResultHandle page); + /** * Find all entities. * diff --git a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/EntityDataAccessImplementor.java b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/EntityDataAccessImplementor.java index 203f84b1a7965..eb354e78c2e5e 100644 --- a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/EntityDataAccessImplementor.java +++ b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/EntityDataAccessImplementor.java @@ -25,6 +25,14 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { ofMethod(entityClassName, "findById", PanacheMongoEntityBase.class, Object.class), id); } + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeStaticMethod(ofMethod(entityClassName, "findAll", PanacheQuery.class)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, + page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + @Override public ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort) { ResultHandle query = creator.invokeStaticMethod( diff --git a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/RepositoryDataAccessImplementor.java b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/RepositoryDataAccessImplementor.java index 9909a2a9efea6..b8e072ffff3a5 100644 --- a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/RepositoryDataAccessImplementor.java +++ b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/RepositoryDataAccessImplementor.java @@ -30,6 +30,16 @@ public ResultHandle findById(BytecodeCreator creator, ResultHandle id) { getRepositoryInstance(creator), id); } + @Override + public ResultHandle findAll(BytecodeCreator creator, ResultHandle page) { + ResultHandle query = creator.invokeInterfaceMethod( + ofMethod(PanacheMongoRepositoryBase.class, "findAll", PanacheQuery.class), + getRepositoryInstance(creator)); + creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "page", PanacheQuery.class, Page.class), query, + page); + return creator.invokeInterfaceMethod(ofMethod(PanacheQuery.class, "list", List.class), query); + } + @Override public ResultHandle findAll(BytecodeCreator creator, ResultHandle page, ResultHandle sort) { ResultHandle query = creator.invokeInterfaceMethod( diff --git a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java index 9d67fbdc9e063..4ade89140d210 100644 --- a/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java +++ b/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/ResourceImplementor.java @@ -1,5 +1,7 @@ package io.quarkus.mongodb.rest.data.panache.deployment; +import static io.quarkus.gizmo.MethodDescriptor.ofMethod; + import java.util.List; import javax.enterprise.context.ApplicationScoped; @@ -7,6 +9,7 @@ import org.jboss.jandex.FieldInfo; import org.jboss.logging.Logger; +import io.quarkus.gizmo.BranchResult; import io.quarkus.gizmo.BytecodeCreator; import io.quarkus.gizmo.ClassCreator; import io.quarkus.gizmo.ClassOutput; @@ -60,7 +63,13 @@ private void implementList(ClassCreator classCreator, DataAccessImplementor data MethodCreator methodCreator = classCreator.getMethodCreator("list", List.class, Page.class, Sort.class); ResultHandle page = methodCreator.getMethodParam(0); ResultHandle sort = methodCreator.getMethodParam(1); - methodCreator.returnValue(dataAccessImplementor.findAll(methodCreator, page, sort)); + ResultHandle columns = methodCreator.invokeVirtualMethod(ofMethod(Sort.class, "getColumns", List.class), sort); + ResultHandle isEmptySort = methodCreator.invokeInterfaceMethod(ofMethod(List.class, "isEmpty", boolean.class), columns); + + BranchResult isEmptySortBranch = methodCreator.ifTrue(isEmptySort); + isEmptySortBranch.trueBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.trueBranch(), page)); + isEmptySortBranch.falseBranch().returnValue(dataAccessImplementor.findAll(isEmptySortBranch.falseBranch(), page, sort)); + methodCreator.close(); } diff --git a/integration-tests/hibernate-orm-rest-data-panache/src/main/resources/import.sql b/integration-tests/hibernate-orm-rest-data-panache/src/main/resources/import.sql index af8c71c169c95..91854e2f738d8 100644 --- a/integration-tests/hibernate-orm-rest-data-panache/src/main/resources/import.sql +++ b/integration-tests/hibernate-orm-rest-data-panache/src/main/resources/import.sql @@ -2,3 +2,5 @@ insert into author(id, name, dob) values (nextval('hibernate_sequence'), 'Fyodor insert into book(id, title, author_id) values (nextval('hibernate_sequence'), 'Crime and Punishment', 1); insert into book(id, title, author_id) values (nextval('hibernate_sequence'), 'Idiot', 1); +insert into book(id, title, author_id) values (nextval('hibernate_sequence'), 'Demons', 1); +insert into book(id, title, author_id) values (nextval('hibernate_sequence'), 'The adolescent', 1); diff --git a/integration-tests/hibernate-orm-rest-data-panache/src/test/java/io/quarkus/it/hibernate/orm/rest/data/panache/HibernateOrmRestDataPanacheTest.java b/integration-tests/hibernate-orm-rest-data-panache/src/test/java/io/quarkus/it/hibernate/orm/rest/data/panache/HibernateOrmRestDataPanacheTest.java index 1e06b96817565..656972dd443dd 100644 --- a/integration-tests/hibernate-orm-rest-data-panache/src/test/java/io/quarkus/it/hibernate/orm/rest/data/panache/HibernateOrmRestDataPanacheTest.java +++ b/integration-tests/hibernate-orm-rest-data-panache/src/test/java/io/quarkus/it/hibernate/orm/rest/data/panache/HibernateOrmRestDataPanacheTest.java @@ -33,6 +33,14 @@ class HibernateOrmRestDataPanacheTest { private static final String IDIOT_TITLE = "Idiot"; + private static final int DEMONS_ID = 4; + + private static final String DEMONS_TITLE = "Demons"; + + private static final int THE_ADOLESCENT_ID = 5; + + private static final String THE_ADOLESCENT_TITLE = "The adolescent"; + @Test void shouldGetAuthor() { given().accept("application/json") @@ -94,11 +102,19 @@ void shouldListBooks() { given().accept("application/json") .when().get("/books") .then().statusCode(200) - .and().body("id", contains(CRIME_AND_PUNISHMENT_ID, IDIOT_ID)) - .and().body("title", contains(CRIME_AND_PUNISHMENT_TITLE, IDIOT_TITLE)) - .and().body("author.id", contains(DOSTOEVSKY_ID, DOSTOEVSKY_ID)) - .and().body("author.name", contains(DOSTOEVSKY_NAME, DOSTOEVSKY_NAME)) - .and().body("author.dob", contains(DOSTOEVSKY_DOB, DOSTOEVSKY_DOB)); + .and().body("id", contains(CRIME_AND_PUNISHMENT_ID, IDIOT_ID, DEMONS_ID, THE_ADOLESCENT_ID)) + .and().body("title", contains(CRIME_AND_PUNISHMENT_TITLE, IDIOT_TITLE, DEMONS_TITLE, THE_ADOLESCENT_TITLE)) + .and().body("author.id", contains(DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID)) + .and().body("author.name", contains(DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME)) + .and().body("author.dob", contains(DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB)); + given().accept("application/json") + .when().get("/books?sort=title") + .then().statusCode(200) + .and().body("id", contains(CRIME_AND_PUNISHMENT_ID, DEMONS_ID, IDIOT_ID, THE_ADOLESCENT_ID)) + .and().body("title", contains(CRIME_AND_PUNISHMENT_TITLE, DEMONS_TITLE, IDIOT_TITLE, THE_ADOLESCENT_TITLE)) + .and().body("author.id", contains(DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID)) + .and().body("author.name", contains(DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME)) + .and().body("author.dob", contains(DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB)); } @Test @@ -106,19 +122,61 @@ void shouldListBooksHal() { given().accept("application/hal+json") .when().get("/books") .then().statusCode(200) - .and().body("_embedded.books.id", contains(CRIME_AND_PUNISHMENT_ID, IDIOT_ID)) - .and().body("_embedded.books.title", contains(CRIME_AND_PUNISHMENT_TITLE, IDIOT_TITLE)) - .and().body("_embedded.books.author.id", contains(DOSTOEVSKY_ID, DOSTOEVSKY_ID)) - .and().body("_embedded.books.author.name", contains(DOSTOEVSKY_NAME, DOSTOEVSKY_NAME)) - .and().body("_embedded.books.author.dob", contains(DOSTOEVSKY_DOB, DOSTOEVSKY_DOB)) - .and().body("_embedded.books._links.add.href", contains(endsWith("/books"), endsWith("/books"))) - .and().body("_embedded.books._links.list.href", contains(endsWith("/books"), endsWith("/books"))) + .and().body("_embedded.books.id", contains(CRIME_AND_PUNISHMENT_ID, IDIOT_ID, DEMONS_ID, THE_ADOLESCENT_ID)) + .and() + .body("_embedded.books.title", + contains(CRIME_AND_PUNISHMENT_TITLE, IDIOT_TITLE, DEMONS_TITLE, THE_ADOLESCENT_TITLE)) + .and().body("_embedded.books.author.id", contains(DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID)) + .and() + .body("_embedded.books.author.name", + contains(DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME)) + .and() + .body("_embedded.books.author.dob", contains(DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB)) + .and() + .body("_embedded.books._links.add.href", + contains(endsWith("/books"), endsWith("/books"), endsWith("/books"), endsWith("/books"))) + .and() + .body("_embedded.books._links.list.href", + contains(endsWith("/books"), endsWith("/books"), endsWith("/books"), endsWith("/books"))) + .and().body("_embedded.books._links.self.href", + contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + IDIOT_ID), + endsWith("/books/" + DEMONS_ID), endsWith("/books/" + THE_ADOLESCENT_ID))) + .and().body("_embedded.books._links.update.href", + contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + IDIOT_ID), + endsWith("/books/" + DEMONS_ID), endsWith("/books/" + THE_ADOLESCENT_ID))) + .and().body("_embedded.books._links.remove.href", + contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + IDIOT_ID), + endsWith("/books/" + DEMONS_ID), endsWith("/books/" + THE_ADOLESCENT_ID))) + .and().body("_links.add.href", endsWith("/books")) + .and().body("_links.list.href", endsWith("/books")); + given().accept("application/hal+json") + .when().get("/books?sort=title") + .then().statusCode(200) + .and().body("_embedded.books.id", contains(CRIME_AND_PUNISHMENT_ID, DEMONS_ID, IDIOT_ID, THE_ADOLESCENT_ID)) + .and() + .body("_embedded.books.title", + contains(CRIME_AND_PUNISHMENT_TITLE, DEMONS_TITLE, IDIOT_TITLE, THE_ADOLESCENT_TITLE)) + .and().body("_embedded.books.author.id", contains(DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID, DOSTOEVSKY_ID)) + .and() + .body("_embedded.books.author.name", + contains(DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME, DOSTOEVSKY_NAME)) + .and() + .body("_embedded.books.author.dob", contains(DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB, DOSTOEVSKY_DOB)) + .and() + .body("_embedded.books._links.add.href", + contains(endsWith("/books"), endsWith("/books"), endsWith("/books"), endsWith("/books"))) + .and() + .body("_embedded.books._links.list.href", + contains(endsWith("/books"), endsWith("/books"), endsWith("/books"), endsWith("/books"))) .and().body("_embedded.books._links.self.href", - contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + IDIOT_ID))) + contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + DEMONS_ID), + endsWith("/books/" + IDIOT_ID), endsWith("/books/" + THE_ADOLESCENT_ID))) .and().body("_embedded.books._links.update.href", - contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + IDIOT_ID))) + contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + DEMONS_ID), + endsWith("/books/" + IDIOT_ID), endsWith("/books/" + THE_ADOLESCENT_ID))) .and().body("_embedded.books._links.remove.href", - contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + IDIOT_ID))) + contains(endsWith("/books/" + CRIME_AND_PUNISHMENT_ID), endsWith("/books/" + DEMONS_ID), + endsWith("/books/" + IDIOT_ID), endsWith("/books/" + THE_ADOLESCENT_ID))) .and().body("_links.add.href", endsWith("/books")) .and().body("_links.list.href", endsWith("/books")); }