diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/openapi/OpenApiIntegrationTest.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/openapi/OpenApiIntegrationTest.java new file mode 100644 index 0000000000000..030293d1eebbd --- /dev/null +++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/openapi/OpenApiIntegrationTest.java @@ -0,0 +1,67 @@ +package io.quarkus.hibernate.orm.rest.data.panache.deployment.openapi; + +import java.util.List; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.bootstrap.model.AppArtifact; +import io.quarkus.builder.Version; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.AbstractEntity; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.AbstractItem; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.Collection; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.CollectionsRepository; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.CollectionsResource; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.EmptyListItem; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.EmptyListItemsRepository; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.EmptyListItemsResource; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.Item; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.ItemsRepository; +import io.quarkus.hibernate.orm.rest.data.panache.deployment.repository.ItemsResource; +import io.quarkus.test.QuarkusProdModeTest; +import io.restassured.RestAssured; + +class OpenApiIntegrationTest { + + private static final String OPEN_API_PATH = "/q/openapi"; + + @RegisterExtension + static final QuarkusProdModeTest TEST = new QuarkusProdModeTest() + .withApplicationRoot((jar) -> jar + .addClasses(Collection.class, CollectionsResource.class, CollectionsRepository.class, + AbstractEntity.class, AbstractItem.class, Item.class, ItemsResource.class, + ItemsRepository.class, EmptyListItem.class, EmptyListItemsRepository.class, + EmptyListItemsResource.class) + .addAsResource("application.properties") + .addAsResource("import.sql")) + .setForcedDependencies(List.of( + new AppArtifact("io.quarkus", "quarkus-smallrye-openapi", Version.getVersion()), + new AppArtifact("io.quarkus", "quarkus-jdbc-h2-deployment", Version.getVersion()), + new AppArtifact("io.quarkus", "quarkus-resteasy-jsonb-deployment", Version.getVersion()))) + .setRun(true); + + @Test + public void testOpenApiForGeneratedResources() { + RestAssured.given().queryParam("format", "JSON") + .when().get(OPEN_API_PATH) + .then() + .header("Content-Type", "application/json;charset=UTF-8") + .body("info.title", Matchers.equalTo("quarkus-hibernate-orm-rest-data-panache-deployment API")) + .body("paths.'/collections'", Matchers.hasKey("get")) + .body("paths.'/collections'", Matchers.hasKey("post")) + .body("paths.'/collections/{id}'", Matchers.hasKey("get")) + .body("paths.'/collections/{id}'", Matchers.hasKey("put")) + .body("paths.'/collections/{id}'", Matchers.hasKey("delete")) + .body("paths.'/empty-list-items'", Matchers.hasKey("get")) + .body("paths.'/empty-list-items'", Matchers.hasKey("post")) + .body("paths.'/empty-list-items/{id}'", Matchers.hasKey("get")) + .body("paths.'/empty-list-items/{id}'", Matchers.hasKey("put")) + .body("paths.'/empty-list-items/{id}'", Matchers.hasKey("delete")) + .body("paths.'/items'", Matchers.hasKey("get")) + .body("paths.'/items'", Matchers.hasKey("post")) + .body("paths.'/items/{id}'", Matchers.hasKey("get")) + .body("paths.'/items/{id}'", Matchers.hasKey("put")) + .body("paths.'/items/{id}'", Matchers.hasKey("delete")); + } +} diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/pom.xml b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/pom.xml index e3a9b09d1a2eb..1725b33eb1e17 100644 --- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/pom.xml +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/pom.xml @@ -10,7 +10,7 @@ quarkus-hibernate-reactive-rest-data-panache-deployment - Quarkus - Hibernate ORM Reactive data with Panache - Deployment + Quarkus - Hibernate Reactive Reactive data with Panache - Deployment diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/openapi/OpenApiIntegrationTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/openapi/OpenApiIntegrationTest.java new file mode 100644 index 0000000000000..1911dd96969c1 --- /dev/null +++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/openapi/OpenApiIntegrationTest.java @@ -0,0 +1,67 @@ +package io.quarkus.hibernate.reactive.rest.data.panache.deployment.openapi; + +import java.util.List; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.bootstrap.model.AppArtifact; +import io.quarkus.builder.Version; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.AbstractEntity; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.AbstractItem; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.Collection; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.CollectionsRepository; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.CollectionsResource; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.EmptyListItem; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.EmptyListItemsRepository; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.EmptyListItemsResource; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.Item; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.ItemsRepository; +import io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository.ItemsResource; +import io.quarkus.test.QuarkusProdModeTest; +import io.restassured.RestAssured; + +class OpenApiIntegrationTest { + + private static final String OPEN_API_PATH = "/q/openapi"; + + @RegisterExtension + static final QuarkusProdModeTest TEST = new QuarkusProdModeTest() + .withApplicationRoot((jar) -> jar + .addClasses(Collection.class, CollectionsResource.class, CollectionsRepository.class, + AbstractEntity.class, AbstractItem.class, Item.class, ItemsResource.class, + ItemsRepository.class, EmptyListItem.class, EmptyListItemsRepository.class, + EmptyListItemsResource.class) + .addAsResource("application.properties") + .addAsResource("import.sql")) + .setForcedDependencies(List.of( + new AppArtifact("io.quarkus", "quarkus-smallrye-openapi", Version.getVersion()), + new AppArtifact("io.quarkus", "quarkus-reactive-pg-client-deployment", Version.getVersion()), + new AppArtifact("io.quarkus", "quarkus-resteasy-reactive-jsonb-deployment", Version.getVersion()))) + .setRun(true); + + @Test + public void testOpenApiForGeneratedResources() { + RestAssured.given().queryParam("format", "JSON") + .when().get(OPEN_API_PATH) + .then() + .header("Content-Type", "application/json;charset=UTF-8") + .body("info.title", Matchers.equalTo("quarkus-hibernate-reactive-rest-data-panache-deployment API")) + .body("paths.'/collections'", Matchers.hasKey("get")) + .body("paths.'/collections'", Matchers.hasKey("post")) + .body("paths.'/collections/{id}'", Matchers.hasKey("get")) + .body("paths.'/collections/{id}'", Matchers.hasKey("put")) + .body("paths.'/collections/{id}'", Matchers.hasKey("delete")) + .body("paths.'/empty-list-items'", Matchers.hasKey("get")) + .body("paths.'/empty-list-items'", Matchers.hasKey("post")) + .body("paths.'/empty-list-items/{id}'", Matchers.hasKey("get")) + .body("paths.'/empty-list-items/{id}'", Matchers.hasKey("put")) + .body("paths.'/empty-list-items/{id}'", Matchers.hasKey("delete")) + .body("paths.'/items'", Matchers.hasKey("get")) + .body("paths.'/items'", Matchers.hasKey("post")) + .body("paths.'/items/{id}'", Matchers.hasKey("get")) + .body("paths.'/items/{id}'", Matchers.hasKey("put")) + .body("paths.'/items/{id}'", Matchers.hasKey("delete")); + } +} \ No newline at end of file diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java index 8ffddc7a573dc..5bbf4c6e7bef8 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/AddMethodImplementor.java @@ -1,6 +1,7 @@ package io.quarkus.rest.data.panache.deployment.methods; import static io.quarkus.gizmo.MethodDescriptor.ofMethod; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.ofType; import javax.validation.Valid; import javax.ws.rs.core.Response; @@ -13,6 +14,7 @@ import io.quarkus.rest.data.panache.RestDataResource; import io.quarkus.rest.data.panache.deployment.ResourceMetadata; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; +import io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator; import io.quarkus.rest.data.panache.deployment.utils.UniImplementor; import io.smallrye.mutiny.Uni; @@ -100,8 +102,8 @@ public AddMethodImplementor(boolean withValidation, boolean isResteasyClassic, b @Override protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), resourceMetadata.getEntityType()); // Add method annotations diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java index a312b8d7ece56..9909001964d9f 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/DeleteMethodImplementor.java @@ -1,6 +1,7 @@ package io.quarkus.rest.data.panache.deployment.methods; import static io.quarkus.gizmo.MethodDescriptor.ofMethod; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.ofType; import javax.ws.rs.core.Response; @@ -13,6 +14,7 @@ import io.quarkus.rest.data.panache.RestDataResource; import io.quarkus.rest.data.panache.deployment.ResourceMetadata; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; +import io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator; import io.quarkus.rest.data.panache.deployment.utils.UniImplementor; import io.smallrye.mutiny.Uni; @@ -83,8 +85,8 @@ public DeleteMethodImplementor(boolean isResteasyClassic, boolean isReactivePana @Override protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), resourceMetadata.getIdType()); // Add method annotations diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java index 0d3b4a1a5121f..5fe26b819380b 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/GetMethodImplementor.java @@ -1,6 +1,7 @@ package io.quarkus.rest.data.panache.deployment.methods; import static io.quarkus.gizmo.MethodDescriptor.ofMethod; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.ofType; import javax.ws.rs.core.Response; @@ -13,6 +14,7 @@ import io.quarkus.rest.data.panache.RestDataResource; import io.quarkus.rest.data.panache.deployment.ResourceMetadata; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; +import io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator; import io.quarkus.rest.data.panache.deployment.utils.UniImplementor; import io.smallrye.mutiny.Uni; @@ -85,8 +87,8 @@ public GetMethodImplementor(boolean isResteasyClassic, boolean isReactivePanache @Override protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), resourceMetadata.getIdType()); // Add method annotations diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java index bfd1544b8c988..534dfa881d331 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java @@ -3,6 +3,7 @@ import static io.quarkus.gizmo.MethodDescriptor.ofMethod; import static io.quarkus.rest.data.panache.deployment.utils.PaginationImplementor.DEFAULT_PAGE_INDEX; import static io.quarkus.rest.data.panache.deployment.utils.PaginationImplementor.DEFAULT_PAGE_SIZE; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.ofType; import java.util.List; @@ -21,6 +22,7 @@ import io.quarkus.rest.data.panache.deployment.ResourceMetadata; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; import io.quarkus.rest.data.panache.deployment.utils.PaginationImplementor; +import io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator; import io.quarkus.rest.data.panache.deployment.utils.SortImplementor; import io.quarkus.rest.data.panache.deployment.utils.UniImplementor; import io.smallrye.mutiny.Uni; @@ -131,8 +133,8 @@ protected String getResourceMethodName() { private void implementPaged(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { // Method parameters: sort strings, page index, page size, uri info - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), List.class, int.class, int.class, UriInfo.class); // Add method annotations @@ -196,8 +198,8 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceFieldDescriptor) { - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), List.class); // Add method annotations diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java index 6924d7ab17bab..b2847251ac2c0 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/UpdateMethodImplementor.java @@ -1,6 +1,7 @@ package io.quarkus.rest.data.panache.deployment.methods; import static io.quarkus.gizmo.MethodDescriptor.ofMethod; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.ofType; import java.lang.annotation.Annotation; import java.util.function.Supplier; @@ -23,6 +24,7 @@ import io.quarkus.rest.data.panache.RestDataResource; import io.quarkus.rest.data.panache.deployment.ResourceMetadata; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; +import io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator; import io.quarkus.rest.data.panache.deployment.utils.UniImplementor; import io.quarkus.rest.data.panache.runtime.UpdateExecutor; import io.smallrye.mutiny.Uni; @@ -132,8 +134,8 @@ public UpdateMethodImplementor(boolean withValidation, boolean isResteasyClassic @Override protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), resourceMetadata.getIdType(), resourceMetadata.getEntityType()); // Add method annotations diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/hal/ListHalMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/hal/ListHalMethodImplementor.java index cd5f899397b15..55b54691f3e61 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/hal/ListHalMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/hal/ListHalMethodImplementor.java @@ -3,6 +3,7 @@ import static io.quarkus.gizmo.MethodDescriptor.ofMethod; import static io.quarkus.rest.data.panache.deployment.utils.PaginationImplementor.DEFAULT_PAGE_INDEX; import static io.quarkus.rest.data.panache.deployment.utils.PaginationImplementor.DEFAULT_PAGE_SIZE; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.ofType; import java.util.List; @@ -24,6 +25,7 @@ import io.quarkus.rest.data.panache.deployment.ResourceMetadata; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; import io.quarkus.rest.data.panache.deployment.utils.PaginationImplementor; +import io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator; import io.quarkus.rest.data.panache.deployment.utils.SortImplementor; import io.quarkus.rest.data.panache.deployment.utils.UniImplementor; import io.smallrye.mutiny.Uni; @@ -123,8 +125,8 @@ protected String getResourceMethodName() { private void implementPaged(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { // Method parameters: sort strings, page index, page size, uri info - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), List.class, int.class, int.class, UriInfo.class); // Add method annotations @@ -197,8 +199,8 @@ private void returnWrappedHalEntitiesWithLinks(BytecodeCreator body, ResourceMet private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceFieldDescriptor) { - MethodCreator methodCreator = classCreator.getMethodCreator(METHOD_NAME, - isNotReactivePanache() ? Response.class : Uni.class, + MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, + isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), List.class); // Add method annotations diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/utils/SignatureMethodCreator.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/utils/SignatureMethodCreator.java new file mode 100644 index 0000000000000..25c8af6af189a --- /dev/null +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/utils/SignatureMethodCreator.java @@ -0,0 +1,71 @@ +package io.quarkus.rest.data.panache.deployment.utils; + +import io.quarkus.gizmo.ClassCreator; +import io.quarkus.gizmo.DescriptorUtils; +import io.quarkus.gizmo.MethodCreator; + +public final class SignatureMethodCreator { + + /** + * Creates a method using a signature (which allows declaring parameterized types like lists). + * + * For example, for the method: "List list(List sort, int size, int other, String uri)" + * It will use the following signature the generated the method: + * "(Ljava/util/List;IILjava/lang/String;)Ljava/util/List;". + * + * One useful utility to verify the method signatures is using "javap -v Test.class" where the Test java class is a compiled + * version of the method you want to see the signature. + */ + public static MethodCreator getMethodCreator(String methodName, ClassCreator classCreator, ReturnType returnType, + Object... parameters) { + MethodCreator methodCreator = classCreator.getMethodCreator(methodName, returnType.type, parameters); + + StringBuilder signatureBuilder = new StringBuilder(); + // Params first within parenthesis. If method is: "void method(Integer a)", it should return "(Ljava/lang/Integer;)": + signatureBuilder.append("("); + parametersToSignature(signatureBuilder, parameters); + + signatureBuilder.append(")"); + + // Then, result type. If method is: "List method(Integer a)", + // it should return "Ljava/util/List;" + signatureBuilder.append(stringToSignature(returnType.type.getName())); + if (returnType.parameterTypes.length > 0) { + signatureBuilder.append("<"); + parametersToSignature(signatureBuilder, returnType.parameterTypes); + signatureBuilder.append(">"); + } + + signatureBuilder.append(";"); + + methodCreator.setSignature(signatureBuilder.toString()); + + return methodCreator; + } + + private static void parametersToSignature(StringBuilder signatureBuilder, Object[] parameters) { + for (Object parameter : parameters) { + if (parameter instanceof Class) { + signatureBuilder.append(DescriptorUtils.classToStringRepresentation((Class) parameter)); + } else if (parameter instanceof String) { + signatureBuilder.append(stringToSignature((String) parameter) + ";"); + } + } + } + + private static String stringToSignature(String className) { + return "L" + className.replace('.', '/'); + } + + public static ReturnType ofType(Class type, Object... parameterTypes) { + ReturnType returnType = new ReturnType(); + returnType.type = type; + returnType.parameterTypes = parameterTypes; + return returnType; + } + + public static class ReturnType { + private Class type; + private Object[] parameterTypes; + } +}