From 88f8c3e5178ff7c78d275ea3e6e883e04773eaa5 Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 23 Jan 2023 16:09:35 +0100 Subject: [PATCH] Refactor to use new SignatureBuilder API by Gizmo in REST Data Panache From https://github.com/quarkusio/gizmo/pull/147, we can use the latest SignatureBuilder API. To use the new SignatureBuilder API, I had to deal with the gizmo type class, so more changes than expected were necessary. --- .../methods/AddMethodImplementor.java | 9 +- .../methods/CountMethodImplementor.java | 5 +- .../methods/DeleteMethodImplementor.java | 9 +- .../methods/GetMethodImplementor.java | 9 +- .../methods/ListMethodImplementor.java | 16 +-- .../methods/StandardMethodImplementor.java | 14 +++ .../methods/UpdateMethodImplementor.java | 11 +- .../utils/SignatureMethodCreator.java | 113 ++++++++---------- 8 files changed, 98 insertions(+), 88 deletions(-) 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 451e4a0bcdb47..fc24f80f9b3f6 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,7 +1,9 @@ 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 static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.param; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.responseType; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.uniType; import javax.validation.Valid; import javax.ws.rs.core.Response; @@ -102,9 +104,8 @@ public AddMethodImplementor(Capabilities capabilities) { protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, - isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), - resourceMetadata.getEntityType(), UriInfo.class); - methodCreator.setParameterNames(new String[] { "entity", "uriInfo" }); + isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()), + param("entity", resourceMetadata.getEntityType()), param("uriInfo", UriInfo.class)); // Add method annotations addPathAnnotation(methodCreator, resourceProperties.getPath(RESOURCE_METHOD_NAME)); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java index efc45733a161a..a7406f0118fb7 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/CountMethodImplementor.java @@ -1,7 +1,8 @@ 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 static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.responseType; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.uniType; import javax.ws.rs.core.Response; @@ -74,7 +75,7 @@ protected void implementInternal(ClassCreator classCreator, ResourceMetadata res ResourceProperties resourceProperties, FieldDescriptor resourceField) { // Method parameters: sort strings, page index, page size, uri info MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(RESOURCE_METHOD_NAME, classCreator, - isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, Long.class)); + isNotReactivePanache() ? responseType() : uniType(Long.class)); // Add method annotations addGetAnnotation(methodCreator); 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 593a4f33028f0..5585cdc0876f5 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,7 +1,9 @@ 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 static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.param; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.responseType; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.uniType; import javax.ws.rs.core.Response; @@ -82,9 +84,8 @@ public DeleteMethodImplementor(Capabilities capabilities) { protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, - isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), - resourceMetadata.getIdType()); - methodCreator.setParameterNames(new String[] { "id" }); + isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()), + param("id", resourceMetadata.getIdType())); // Add method annotations addPathAnnotation(methodCreator, appendToPath(resourceProperties.getPath(RESOURCE_METHOD_NAME), "{id}")); 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 23906f76c25d7..94c330a5dda06 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,7 +1,9 @@ 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 static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.param; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.responseType; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.uniType; import javax.ws.rs.core.Response; @@ -84,9 +86,8 @@ public GetMethodImplementor(Capabilities capabilities) { protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, - isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), - resourceMetadata.getIdType()); - methodCreator.setParameterNames(new String[] { "id" }); + isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()), + param("id", resourceMetadata.getIdType())); // Add method annotations addPathAnnotation(methodCreator, appendToPath(resourceProperties.getPath(RESOURCE_METHOD_NAME), "{id}")); 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 42d513e83eef5..be4de64d9e5c4 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 @@ -9,10 +9,12 @@ import static io.quarkus.arc.processor.DotNames.STRING; import static io.quarkus.gizmo.MethodDescriptor.ofConstructor; import static io.quarkus.gizmo.MethodDescriptor.ofMethod; +import static io.quarkus.gizmo.Type.intType; 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 static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.param; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.responseType; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.uniType; import java.util.ArrayList; import java.util.Collection; @@ -173,14 +175,14 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource Collection compatibleFieldsForQuery = getFieldsToQuery(resourceMetadata); List parameters = new ArrayList<>(); parameters.add(param("sort", List.class)); - parameters.add(param("page", int.class)); - parameters.add(param("size", int.class)); + parameters.add(param("page", int.class, intType())); + parameters.add(param("size", int.class, intType())); parameters.add(param("uriInfo", UriInfo.class)); parameters.add(param("namedQuery", String.class)); parameters.addAll(compatibleFieldsForQuery); MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(getMethodName(), classCreator, - isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), - parameters); + isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()), + parameters.toArray(new SignatureMethodCreator.Parameter[0])); // Add method annotations addGetAnnotation(methodCreator); @@ -265,8 +267,8 @@ private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resou parameters.add(param("namedQuery", String.class)); parameters.addAll(compatibleFieldsForQuery); MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(getMethodName(), classCreator, - isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), - parameters); + isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()), + parameters.toArray(new SignatureMethodCreator.Parameter[0])); // Add method annotations addGetAnnotation(methodCreator); diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java index 1af632b140993..f7f1e299a2ffa 100644 --- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java +++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/StandardMethodImplementor.java @@ -27,6 +27,7 @@ import io.quarkus.gizmo.ClassCreator; import io.quarkus.gizmo.FieldDescriptor; import io.quarkus.gizmo.TryBlock; +import io.quarkus.gizmo.Type; import io.quarkus.rest.data.panache.RestDataPanacheException; import io.quarkus.rest.data.panache.deployment.ResourceMetadata; import io.quarkus.rest.data.panache.deployment.properties.ResourceProperties; @@ -235,6 +236,19 @@ protected boolean isNotReactivePanache() { return !capabilities.isPresent(Capability.HIBERNATE_REACTIVE); } + public static Type toType(Object object) { + if (object instanceof Type) { + return (Type) object; + } else if (object instanceof String) { + return Type.classType((String) object); + } else if (object instanceof Class) { + return Type.classType((Class) object); + } + + throw new IllegalArgumentException("Unsupported object of type " + object.getClass() + + ". Supported types are Type, String and Class"); + } + private static Class toClass(String className) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); try { 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 b2f4c7dcfbafc..70bf8ec63efef 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,7 +1,9 @@ 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 static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.param; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.responseType; +import static io.quarkus.rest.data.panache.deployment.utils.SignatureMethodCreator.uniType; import java.lang.annotation.Annotation; import java.util.function.Supplier; @@ -134,9 +136,10 @@ public UpdateMethodImplementor(Capabilities capabilities) { protected void implementInternal(ClassCreator classCreator, ResourceMetadata resourceMetadata, ResourceProperties resourceProperties, FieldDescriptor resourceField) { MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(METHOD_NAME, classCreator, - isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()), - resourceMetadata.getIdType(), resourceMetadata.getEntityType(), UriInfo.class); - methodCreator.setParameterNames(new String[] { "id", "entity", "uriInfo" }); + isNotReactivePanache() ? responseType() : uniType(resourceMetadata.getEntityType()), + param("id", resourceMetadata.getIdType()), + param("entity", resourceMetadata.getEntityType()), + param("uriInfo", UriInfo.class)); // Add method annotations addPathAnnotation(methodCreator, appendToPath(resourceProperties.getPath(RESOURCE_UPDATE_METHOD_NAME), "{id}")); 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 index b671754e7f7a7..7cf067627531a 100644 --- 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 @@ -1,14 +1,24 @@ package io.quarkus.rest.data.panache.deployment.utils; +import static io.quarkus.gizmo.Type.classType; +import static io.quarkus.gizmo.Type.parameterizedType; +import static io.quarkus.rest.data.panache.deployment.methods.StandardMethodImplementor.toType; + import java.util.ArrayList; import java.util.List; +import javax.ws.rs.core.Response; + import io.quarkus.gizmo.ClassCreator; -import io.quarkus.gizmo.DescriptorUtils; import io.quarkus.gizmo.MethodCreator; +import io.quarkus.gizmo.SignatureBuilder; +import io.quarkus.gizmo.Type; +import io.smallrye.mutiny.Uni; public final class SignatureMethodCreator { + private static final Type RESPONSE_TYPE = Type.classType(Response.class); + /** * Creates a method using a signature (which allows declaring parameterized types like lists). * @@ -20,86 +30,44 @@ public final class SignatureMethodCreator { * version of the method you want to see the signature. */ public static MethodCreator getMethodCreator(String methodName, ClassCreator classCreator, ReturnType returnType, - List parameters) { - List paramTypes = new ArrayList<>(); + Parameter... parameters) { + List paramTypes = new ArrayList<>(); List paramNames = new ArrayList<>(); + List paramClasses = new ArrayList<>(); for (Parameter param : parameters) { paramNames.add(param.name); paramTypes.add(param.type); + paramClasses.add(param.clazz); } - MethodCreator methodCreator = getMethodCreator(methodName, classCreator, returnType, paramTypes.toArray(new Object[0])); - methodCreator.setParameterNames(paramNames.toArray(new String[0])); - return methodCreator; - } - /** - * 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()); + MethodCreator methodCreator = classCreator.getMethodCreator(methodName, returnType.classType, + paramClasses.toArray(new Object[0])); + SignatureBuilder.MethodSignatureBuilder signatureBuilder = SignatureBuilder.forMethod() + .setReturnType(returnType.type); + paramTypes.forEach(signatureBuilder::addParameterType); + methodCreator.setSignature(signatureBuilder.build()); + methodCreator.setParameterNames(paramNames.toArray(new String[0])); 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 Parameter param(String name, Object type) { + return param(name, type, toType(type)); } - public static Parameter param(String name, Object type) { + public static Parameter param(String name, Object clazz, Type type) { Parameter parameter = new Parameter(); parameter.name = name; + parameter.clazz = clazz; parameter.type = type; + return parameter; } public static class Parameter { private String name; - private Object type; + private Type type; + private Object clazz; public String getName() { return name; @@ -107,7 +75,26 @@ public String getName() { } public static class ReturnType { - private Class type; - private Object[] parameterTypes; + private Class classType; + private Type type; + } + + public static ReturnType responseType() { + ReturnType returnType = new ReturnType(); + returnType.classType = Response.class; + returnType.type = RESPONSE_TYPE; + return returnType; + } + + public static ReturnType uniType(Object... arguments) { + ReturnType returnType = new ReturnType(); + Type[] typeArguments = new Type[arguments.length]; + for (int index = 0; index < arguments.length; index++) { + typeArguments[index] = toType(arguments[index]); + } + + returnType.classType = Uni.class; + returnType.type = parameterizedType(classType(Uni.class), typeArguments); + return returnType; } }