From ed7316e2a14eebe9574d7afbdd7f4269a8fa0220 Mon Sep 17 00:00:00 2001 From: Matheus Cruz Date: Tue, 25 Jun 2024 15:05:58 -0300 Subject: [PATCH] Add JsonObject ValueResolver to Qute --- .../qute/deployment/JsonObjectProcessor.java | 17 ++++++ .../JsonObjectValueResolverTest.java | 37 +++++++++++++ extensions/qute/runtime/pom.xml | 5 ++ .../jsonobject/JsonObjectConfigurator.java | 17 ++++++ .../jsonobject/JsonObjectValueResolver.java | 52 +++++++++++++++++++ 5 files changed, 128 insertions(+) create mode 100644 extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/JsonObjectProcessor.java create mode 100644 extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/jsonobject/JsonObjectValueResolverTest.java create mode 100644 extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectConfigurator.java create mode 100644 extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectValueResolver.java diff --git a/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/JsonObjectProcessor.java b/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/JsonObjectProcessor.java new file mode 100644 index 00000000000000..7ea96fb637acd9 --- /dev/null +++ b/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/JsonObjectProcessor.java @@ -0,0 +1,17 @@ +package io.quarkus.qute.deployment; + +import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.deployment.Capabilities; +import io.quarkus.deployment.Capability; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; + +public class JsonObjectProcessor { + + @BuildStep + void init(Capabilities capabilities, BuildProducer beans) { + if (capabilities.isPresent(Capability.VERTX)) { + beans.produce(new AdditionalBeanBuildItem("io.quarkus.qute.runtime.jsonobject.JsonObjectConfigurator")); + } + } +} diff --git a/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/jsonobject/JsonObjectValueResolverTest.java b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/jsonobject/JsonObjectValueResolverTest.java new file mode 100644 index 00000000000000..692f7735d84589 --- /dev/null +++ b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/jsonobject/JsonObjectValueResolverTest.java @@ -0,0 +1,37 @@ +package io.quarkus.qute.deployment.jsonobject; + +import java.util.HashMap; + +import jakarta.inject.Inject; + +import org.assertj.core.api.Assertions; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.qute.Template; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.core.json.JsonObject; + +public class JsonObjectValueResolverTest { + + @RegisterExtension + static final QuarkusUnitTest quarkusApp = new QuarkusUnitTest() + .withApplicationRoot( + app -> app.addAsResource(new StringAsset( + "{tool.name} {tool.fieldNames} {tool.fields} {tool.size} {tool.empty} {tool.isEmpty} {tool.get('name')} {tool.containsKey('name')}"), + "templates/foo.txt")); + + @Inject + Template foo; + + @Test + void testJsonObjectValueResolver() { + HashMap toolMap = new HashMap<>(); + toolMap.put("name", "Roq"); + JsonObject jsonObject = new JsonObject(toolMap); + String render = foo.data("tool", jsonObject).render(); + + Assertions.assertThat(render).isEqualTo("Roq [name] [name] 1 false false Roq true"); + } +} diff --git a/extensions/qute/runtime/pom.xml b/extensions/qute/runtime/pom.xml index 1a0b7d3243d8ff..f6b3e3a03b3d39 100644 --- a/extensions/qute/runtime/pom.xml +++ b/extensions/qute/runtime/pom.xml @@ -31,6 +31,11 @@ quarkus-cache true + + io.quarkus + quarkus-vertx + true + diff --git a/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectConfigurator.java b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectConfigurator.java new file mode 100644 index 00000000000000..818753fc4636b6 --- /dev/null +++ b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectConfigurator.java @@ -0,0 +1,17 @@ +package io.quarkus.qute.runtime.jsonobject; + +import jakarta.enterprise.event.Observes; + +import io.quarkus.qute.EngineBuilder; + +public class JsonObjectConfigurator { + + /** + * Configure the engine to use the {@link JsonObjectValueResolver}. + * + * @param builder the engine builder. + */ + void configureEngine(@Observes EngineBuilder builder) { + builder.addValueResolver(new JsonObjectValueResolver()); + } +} diff --git a/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectValueResolver.java b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectValueResolver.java new file mode 100644 index 00000000000000..df7aad77549af0 --- /dev/null +++ b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/jsonobject/JsonObjectValueResolver.java @@ -0,0 +1,52 @@ +package io.quarkus.qute.runtime.jsonobject; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import io.quarkus.qute.EvalContext; +import io.quarkus.qute.Results; +import io.quarkus.qute.ValueResolver; +import io.vertx.core.json.JsonObject; + +/** + * A value resolver for {@link JsonObject}. + */ +public class JsonObjectValueResolver implements ValueResolver { + + @Override + public boolean appliesTo(EvalContext context) { + return ValueResolver.matchClass(context, JsonObject.class); + } + + @Override + public CompletionStage resolve(EvalContext context) { + + JsonObject jsonObject = (JsonObject) context.getBase(); + switch (context.getName()) { + case "fieldNames": + case "fields": + return CompletableFuture.completedFuture(jsonObject.fieldNames()); + case "size": + return CompletableFuture.completedFuture(jsonObject.size()); + case "empty": + case "isEmpty": + return CompletableFuture.completedFuture(jsonObject.isEmpty()); + case "get": + if (context.getParams().size() == 1) { + return context.evaluate(context.getParams().get(0)).thenCompose(k -> { + return CompletableFuture.completedFuture(jsonObject.getValue((String) k)); + }); + } + case "containsKey": + if (context.getParams().size() == 1) { + return context.evaluate(context.getParams().get(0)).thenCompose(k -> { + return CompletableFuture.completedFuture(jsonObject.containsKey((String) k)); + }); + } + default: + return jsonObject.containsKey(context.getName()) + ? CompletableFuture.completedFuture(jsonObject.getValue(context.getName())) + : Results.notFound(context); + } + } +}