From aa15ad71a41a54ddb84744ff63b5f320da75b161 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Mar 2021 05:01:57 +0000 Subject: [PATCH 1/9] Assign each provider to a variable Signed-off-by: Jakub Zalas --- Here-man.txt | 4 ++-- .../xoom/codegen/template/bootstrap/StoreProvider.java | 7 +++++++ src/main/resources/codegen/java/XoomInitializer.ftl | 2 +- src/main/resources/codegen/kotlin/XoomInitializer.ftl | 1 + .../resources/text-expectations/java/xoom-initializer.text | 4 ++-- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Here-man.txt b/Here-man.txt index a77ddf8a..a5c185e7 100644 --- a/Here-man.txt +++ b/Here-man.txt @@ -45,8 +45,8 @@ public class XoomInitializer implements XoomInitializationAware { exchangeInitializer.init(grid); final StatefulTypeRegistry statefulTypeRegistry = new StatefulTypeRegistry(grid.world()); - QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); - CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, exchangeInitializer.dispatcher()); + final QueryModelStateStoreProvider queryModelStateStoreProvider = QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); + final CommandModelStateStoreProvider commandModelStateStoreProvider = CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, exchangeInitializer.dispatcher()); final AuthorResource authorResource = new AuthorResource(grid); final BookResource bookResource = new BookResource(grid); diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/StoreProvider.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/StoreProvider.java index 3ade2760..83537996 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/StoreProvider.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/StoreProvider.java @@ -8,6 +8,7 @@ package io.vlingo.xoom.codegen.template.bootstrap; +import io.vlingo.xoom.codegen.content.CodeElementFormatter; import io.vlingo.xoom.codegen.template.TemplateParameters; import io.vlingo.xoom.codegen.template.storage.Model; import io.vlingo.xoom.codegen.template.storage.StorageType; @@ -26,6 +27,7 @@ public class StoreProvider { private final String className; + private final String objectName; private final String arguments; public static List from(final StorageType storageType, @@ -50,6 +52,7 @@ private StoreProvider(final StorageType storageType, .and(MODEL, model); this.className = STORE_PROVIDER.resolveClassname(parameters); + this.objectName = CodeElementFormatter.simpleNameToAttribute(this.className); this.arguments = resolveArguments(model, storageType, useProjections, hasExchange); } @@ -83,6 +86,10 @@ public String getClassName() { return className; } + public String getObjectName() { + return objectName; + } + public String getArguments() { return arguments; } diff --git a/src/main/resources/codegen/java/XoomInitializer.ftl b/src/main/resources/codegen/java/XoomInitializer.ftl index 62525bbd..be482b77 100644 --- a/src/main/resources/codegen/java/XoomInitializer.ftl +++ b/src/main/resources/codegen/java/XoomInitializer.ftl @@ -54,7 +54,7 @@ public class XoomInitializer implements XoomInitializationAware { final ${registry.className} ${registry.objectName} = new ${registry.className}(grid.world()); <#list providers as provider> - ${provider.className}.using(${provider.arguments}); + final ${provider.className} ${provider.objectName} = ${provider.className}.using(${provider.arguments}); <#list restResources as restResource> diff --git a/src/main/resources/codegen/kotlin/XoomInitializer.ftl b/src/main/resources/codegen/kotlin/XoomInitializer.ftl index 12258e2e..8b2c084c 100644 --- a/src/main/resources/codegen/kotlin/XoomInitializer.ftl +++ b/src/main/resources/codegen/kotlin/XoomInitializer.ftl @@ -59,6 +59,7 @@ public class XoomInitializer : XoomInitializationAware { <#list providers as provider> ${provider.className}.using(${provider.arguments}) + val ${provider.objectName}: ${provider.className} = ${provider.className}.using(${provider.arguments}); <#list restResources as restResource> diff --git a/src/test/resources/text-expectations/java/xoom-initializer.text b/src/test/resources/text-expectations/java/xoom-initializer.text index a77ddf8a..a5c185e7 100644 --- a/src/test/resources/text-expectations/java/xoom-initializer.text +++ b/src/test/resources/text-expectations/java/xoom-initializer.text @@ -45,8 +45,8 @@ public class XoomInitializer implements XoomInitializationAware { exchangeInitializer.init(grid); final StatefulTypeRegistry statefulTypeRegistry = new StatefulTypeRegistry(grid.world()); - QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); - CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, exchangeInitializer.dispatcher()); + final QueryModelStateStoreProvider queryModelStateStoreProvider = QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); + final CommandModelStateStoreProvider commandModelStateStoreProvider = CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, exchangeInitializer.dispatcher()); final AuthorResource authorResource = new AuthorResource(grid); final BookResource bookResource = new BookResource(grid); From f2c027a415a8bb30697959ed50c63aab7c972865 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Mar 2021 17:45:06 +0100 Subject: [PATCH 2/9] Do not hard code the list of rest resource arguments Signed-off-by: Jakub Zalas --- .../xoom/codegen/template/bootstrap/RestResource.java | 6 ++++++ src/main/resources/codegen/java/XoomInitializer.ftl | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java index de037bac..27f468be 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java @@ -24,6 +24,7 @@ public class RestResource { private final String className; private final String objectName; + private final String arguments; private final boolean last; public static List from(final List contents) { @@ -43,6 +44,7 @@ private RestResource(final String restResourceName, final int numberOfResources) { this.className = restResourceName; this.objectName = CodeElementFormatter.simpleNameToAttribute(restResourceName); + this.arguments = "grid"; this.last = resourceIndex == numberOfResources - 1; } @@ -54,6 +56,10 @@ public String getObjectName() { return objectName; } + public String getArguments() { + return arguments; + } + public boolean isLast() { return last; } diff --git a/src/main/resources/codegen/java/XoomInitializer.ftl b/src/main/resources/codegen/java/XoomInitializer.ftl index be482b77..557af33d 100644 --- a/src/main/resources/codegen/java/XoomInitializer.ftl +++ b/src/main/resources/codegen/java/XoomInitializer.ftl @@ -58,7 +58,7 @@ public class XoomInitializer implements XoomInitializationAware { <#list restResources as restResource> - final ${restResource.className} ${restResource.objectName} = new ${restResource.className}(grid); + final ${restResource.className} ${restResource.objectName} = new ${restResource.className}(${restResource.arguments}); final Collection> sseResources = Loader.resourcesFrom(initializer.sseConfiguration()).values(); From ca53c905a8d52b33ac7566039d8f799ef2d4a232 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Mar 2021 17:49:32 +0100 Subject: [PATCH 3/9] Pass the useCQRS flag to RestResource Signed-off-by: Jakub Zalas --- .../template/bootstrap/DefaultBootstrapTemplateData.java | 2 +- .../vlingo/xoom/codegen/template/bootstrap/RestResource.java | 2 +- .../template/bootstrap/XoomInitializerTemplateData.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java index 97f22da5..0af2cec9 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java @@ -32,7 +32,7 @@ protected void enrichParameters(final CodeGenerationContext context) { STORE_PROVIDER, PROJECTION_DISPATCHER_PROVIDER, REST_RESOURCE, AUTO_DISPATCH_RESOURCE_HANDLER, EXCHANGE_BOOTSTRAP); - parameters().and(REST_RESOURCES, RestResource.from(context.contents())) + parameters().and(REST_RESOURCES, RestResource.from(useCQRS, context.contents())) .and(EXCHANGE_BOOTSTRAP_NAME, EXCHANGE_BOOTSTRAP.resolveClassname()) .and(HAS_EXCHANGE, ContentQuery.exists(EXCHANGE_BOOTSTRAP, context.contents())) .addImports(qualifiedNames).addImports(storageType.resolveTypeRegistryQualifiedNames(useCQRS)); diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java index 27f468be..3e95c1cf 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java @@ -27,7 +27,7 @@ public class RestResource { private final String arguments; private final boolean last; - public static List from(final List contents) { + public static List from(boolean useCQRS, final List contents) { final Set classNames = ContentQuery.findClassNames(contents, REST_RESOURCE, AUTO_DISPATCH_RESOURCE_HANDLER); diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java index 16e3976a..8f74975e 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java @@ -29,13 +29,14 @@ protected void enrichParameters(final CodeGenerationContext context) { final String xoomInitializerClass = context.parameterOf(XOOM_INITIALIZER_NAME); final Boolean blockingMessaging = context.parameterOf(BLOCKING_MESSAGING, Boolean::valueOf); final Boolean customInitialization = !xoomInitializerClass.equals(XOOM_INITIALIZER.resolveClassname()); + final Boolean useCQRS = context.parameterOf(CQRS, Boolean::valueOf); loadImports(context, contents); parameters().and(TemplateParameter.BLOCKING_MESSAGING, blockingMessaging) .and(TemplateParameter.XOOM_INITIALIZER_CLASS, xoomInitializerClass) .and(TemplateParameter.CUSTOM_INITIALIZATION, customInitialization) - .and(TemplateParameter.REST_RESOURCES, RestResource.from(contents)) + .and(TemplateParameter.REST_RESOURCES, RestResource.from(useCQRS, contents)) .and(TemplateParameter.APPLICATION_NAME, appName) .and(TemplateParameter.EXCHANGE_BOOTSTRAP_NAME, resolveExchangeBootstrapName(context)); } From faa7201c31bd4167f45a37f45812548197279adf Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Mar 2021 17:52:44 +0100 Subject: [PATCH 4/9] Remove a redundant line Signed-off-by: Jakub Zalas --- src/main/resources/codegen/kotlin/XoomInitializer.ftl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/codegen/kotlin/XoomInitializer.ftl b/src/main/resources/codegen/kotlin/XoomInitializer.ftl index 8b2c084c..293a7b3c 100644 --- a/src/main/resources/codegen/kotlin/XoomInitializer.ftl +++ b/src/main/resources/codegen/kotlin/XoomInitializer.ftl @@ -58,7 +58,6 @@ public class XoomInitializer : XoomInitializationAware { val ${registry.objectName}: ${registry.className} = ${registry.className}(world) <#list providers as provider> - ${provider.className}.using(${provider.arguments}) val ${provider.objectName}: ${provider.className} = ${provider.className}.using(${provider.arguments}); From de19377126f943770a592bb7fcfc642bd6dc183b Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Mar 2021 18:18:47 +0100 Subject: [PATCH 5/9] Add an alternative constructor to rest resources using cqrs Signed-off-by: Jakub Zalas --- src/main/resources/codegen/java/RestResource.ftl | 15 +++++++++++++++ .../resources/codegen/kotlin/RestResource.ftl | 12 ++++++++++++ .../java/author-rest-resource.text | 6 ++++++ 3 files changed, 33 insertions(+) diff --git a/src/main/resources/codegen/java/RestResource.ftl b/src/main/resources/codegen/java/RestResource.ftl index 0cabeda1..7f23be67 100644 --- a/src/main/resources/codegen/java/RestResource.ftl +++ b/src/main/resources/codegen/java/RestResource.ftl @@ -54,6 +54,21 @@ public class ${resourceName} extends DynamicResourceHandler { this.$queries = ${storeProviderName}.instance().${queries.attributeName}; } + <#if queries?has_content && !queries.empty> + + public ${resourceName}(final Grid grid, final ${queries.protocolName} ${queries.attributeName}) { + super(grid.world().stage()); + <#if useAutoDispatch> + this.$stage = grid; + this.$logger = super.logger(); + <#else> + this.grid = grid; + + <#if queries?has_content && !queries.empty> + this.$queries = ${queries.attributeName}; + + } + <#list routeMethods as routeMethod> ${routeMethod} diff --git a/src/main/resources/codegen/kotlin/RestResource.ftl b/src/main/resources/codegen/kotlin/RestResource.ftl index 37e45e67..8bac98b1 100644 --- a/src/main/resources/codegen/kotlin/RestResource.ftl +++ b/src/main/resources/codegen/kotlin/RestResource.ftl @@ -47,6 +47,18 @@ public class ${resourceName} : DynamicResourceHandler { this.$queries = ${storeProviderName}.instance().${queries.attributeName} } + <#if queries?has_content && !queries.empty> + + public constructor(stage: Stage, ${queries.attributeName}: ${queries.protocolName}) : super(stage){ + <#if useAutoDispatch> + this.$stage = super.stage() + this.$logger = super.logger() + + <#if queries?has_content && !queries.empty> + this.$queries = ${queries.attributeName} + + } + <#list routeMethods as routeMethod> ${routeMethod} diff --git a/src/test/resources/text-expectations/java/author-rest-resource.text b/src/test/resources/text-expectations/java/author-rest-resource.text index 146063e1..98e674df 100644 --- a/src/test/resources/text-expectations/java/author-rest-resource.text +++ b/src/test/resources/text-expectations/java/author-rest-resource.text @@ -34,6 +34,12 @@ public class AuthorResource extends DynamicResourceHandler { this.$queries = QueryModelStateStoreProvider.instance().authorQueries; } + public AuthorResource(final Grid grid, final AuthorQueries authorQueries) { + super(grid.world().stage()); + this.grid = grid; + this.$queries = authorQueries; + } + public Completes withName(final AuthorData data) { final Name name = Name.from(data.name.firstName, data.name.lastName); return Author.withName(grid, name) From 5d65b0c5c163010bc0fece8d9ab430b155efb51d Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Mar 2021 18:57:25 +0100 Subject: [PATCH 6/9] Pass queries in the rest resource constructor Signed-off-by: Jakub Zalas --- Here-man.txt | 4 +-- .../template/bootstrap/RestResource.java | 33 ++++++++++++++++--- .../java/xoom-initializer.text | 4 +-- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Here-man.txt b/Here-man.txt index a5c185e7..cf8c92ba 100644 --- a/Here-man.txt +++ b/Here-man.txt @@ -48,8 +48,8 @@ public class XoomInitializer implements XoomInitializationAware { final QueryModelStateStoreProvider queryModelStateStoreProvider = QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); final CommandModelStateStoreProvider commandModelStateStoreProvider = CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, exchangeInitializer.dispatcher()); - final AuthorResource authorResource = new AuthorResource(grid); - final BookResource bookResource = new BookResource(grid); + final AuthorResource authorResource = new AuthorResource(grid, queryModelStateStoreProvider.authorQueries); + final BookResource bookResource = new BookResource(grid, queryModelStateStoreProvider.bookQueries); final Collection> sseResources = Loader.resourcesFrom(initializer.sseConfiguration()).values(); final Collection> feedResources = Loader.resourcesFrom(initializer.feedConfiguration()).values(); diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java index 3e95c1cf..7be6c016 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java @@ -10,14 +10,22 @@ import io.vlingo.xoom.codegen.content.CodeElementFormatter; import io.vlingo.xoom.codegen.content.Content; import io.vlingo.xoom.codegen.content.ContentQuery; +import io.vlingo.xoom.codegen.template.TemplateParameters; +import io.vlingo.xoom.codegen.template.TemplateStandard; +import io.vlingo.xoom.codegen.template.storage.Model; +import io.vlingo.xoom.codegen.template.storage.StorageType; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.stream.IntStream; +import java.util.stream.Stream; +import static io.vlingo.xoom.codegen.template.TemplateParameter.MODEL; +import static io.vlingo.xoom.codegen.template.TemplateParameter.STORAGE_TYPE; import static io.vlingo.xoom.codegen.template.TemplateStandard.AUTO_DISPATCH_RESOURCE_HANDLER; import static io.vlingo.xoom.codegen.template.TemplateStandard.REST_RESOURCE; +import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; public class RestResource { @@ -34,20 +42,37 @@ public static List from(boolean useCQRS, final List conte final Iterator iterator = classNames.iterator(); - return IntStream.range(0, classNames.size()).mapToObj(index -> - new RestResource(iterator.next(), index, - classNames.size())).collect(toList()); + return IntStream + .range(0, classNames.size()) + .mapToObj(index -> new RestResource(iterator.next(), useCQRS, index, classNames.size())) + .collect(toList()); } private RestResource(final String restResourceName, + final Boolean useCQRS, final int resourceIndex, final int numberOfResources) { this.className = restResourceName; this.objectName = CodeElementFormatter.simpleNameToAttribute(restResourceName); - this.arguments = "grid"; + this.arguments = resolveArguments(restResourceName, useCQRS); this.last = resourceIndex == numberOfResources - 1; } + private String resolveArguments(String restResourceName, Boolean useCQRS) { + final List arguments = Stream.of("grid").collect(toList()); + + if (useCQRS) { + final String storeProviderClass = TemplateStandard.STORE_PROVIDER.resolveClassname(TemplateParameters.with(STORAGE_TYPE, StorageType.STATE_STORE).and(MODEL, Model.QUERY)); + final String storeProviderName = CodeElementFormatter.simpleNameToAttribute(storeProviderClass); + final String queriesClassName = TemplateStandard.QUERIES.resolveClassname(restResourceName.replace("Resource", "")); + final String queriesAttributeName = CodeElementFormatter.simpleNameToAttribute(queriesClassName); + arguments.add(String.format("%s.%s", storeProviderName, queriesAttributeName)); + } + + return arguments.stream().collect(joining(", ")); + + } + public String getClassName() { return className; } diff --git a/src/test/resources/text-expectations/java/xoom-initializer.text b/src/test/resources/text-expectations/java/xoom-initializer.text index a5c185e7..cf8c92ba 100644 --- a/src/test/resources/text-expectations/java/xoom-initializer.text +++ b/src/test/resources/text-expectations/java/xoom-initializer.text @@ -48,8 +48,8 @@ public class XoomInitializer implements XoomInitializationAware { final QueryModelStateStoreProvider queryModelStateStoreProvider = QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); final CommandModelStateStoreProvider commandModelStateStoreProvider = CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, exchangeInitializer.dispatcher()); - final AuthorResource authorResource = new AuthorResource(grid); - final BookResource bookResource = new BookResource(grid); + final AuthorResource authorResource = new AuthorResource(grid, queryModelStateStoreProvider.authorQueries); + final BookResource bookResource = new BookResource(grid, queryModelStateStoreProvider.bookQueries); final Collection> sseResources = Loader.resourcesFrom(initializer.sseConfiguration()).values(); final Collection> feedResources = Loader.resourcesFrom(initializer.feedConfiguration()).values(); From 588995cd3efbdb5f8641a85d6ba07f381dc25713 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Mar 2021 19:03:29 +0100 Subject: [PATCH 7/9] Pass queries in the rest resource constructor Signed-off-by: Jakub Zalas --- .../resources/codegen/java/RestResource.ftl | 17 +---------- .../resources/codegen/kotlin/RestResource.ftl | 28 ++++++------------- .../java/author-rest-resource.text | 6 ---- 3 files changed, 9 insertions(+), 42 deletions(-) diff --git a/src/main/resources/codegen/java/RestResource.ftl b/src/main/resources/codegen/java/RestResource.ftl index 7f23be67..25974868 100644 --- a/src/main/resources/codegen/java/RestResource.ftl +++ b/src/main/resources/codegen/java/RestResource.ftl @@ -42,21 +42,7 @@ public class ${resourceName} extends DynamicResourceHandler { private final ${queries.protocolName} $queries; - public ${resourceName}(final Grid grid) { - super(grid.world().stage()); - <#if useAutoDispatch> - this.$stage = grid; - this.$logger = super.logger(); - <#else> - this.grid = grid; - - <#if queries?has_content && !queries.empty> - this.$queries = ${storeProviderName}.instance().${queries.attributeName}; - - } - <#if queries?has_content && !queries.empty> - - public ${resourceName}(final Grid grid, final ${queries.protocolName} ${queries.attributeName}) { + public ${resourceName}(final Grid grid<#if queries?has_content && !queries.empty>, final ${queries.protocolName} ${queries.attributeName}) { super(grid.world().stage()); <#if useAutoDispatch> this.$stage = grid; @@ -68,7 +54,6 @@ public class ${resourceName} extends DynamicResourceHandler { this.$queries = ${queries.attributeName}; } - <#list routeMethods as routeMethod> ${routeMethod} diff --git a/src/main/resources/codegen/kotlin/RestResource.ftl b/src/main/resources/codegen/kotlin/RestResource.ftl index 8bac98b1..8f06905f 100644 --- a/src/main/resources/codegen/kotlin/RestResource.ftl +++ b/src/main/resources/codegen/kotlin/RestResource.ftl @@ -38,27 +38,15 @@ public class ${resourceName} : DynamicResourceHandler { val $queries: ${queries.protocolName} - public constructor(stage: Stage) : super(stage){ - <#if useAutoDispatch> - this.$stage = super.stage() - this.$logger = super.logger() - - <#if queries?has_content && !queries.empty> - this.$queries = ${storeProviderName}.instance().${queries.attributeName} - + public constructor(stage: Stage<#if queries?has_content && !queries.empty>, ${queries.attributeName}: ${queries.protocolName}) : super(stage){ + <#if useAutoDispatch> + this.$stage = super.stage() + this.$logger = super.logger() + + <#if queries?has_content && !queries.empty> + this.$queries = ${queries.attributeName} + } - <#if queries?has_content && !queries.empty> - - public constructor(stage: Stage, ${queries.attributeName}: ${queries.protocolName}) : super(stage){ - <#if useAutoDispatch> - this.$stage = super.stage() - this.$logger = super.logger() - - <#if queries?has_content && !queries.empty> - this.$queries = ${queries.attributeName} - - } - <#list routeMethods as routeMethod> ${routeMethod} diff --git a/src/test/resources/text-expectations/java/author-rest-resource.text b/src/test/resources/text-expectations/java/author-rest-resource.text index 98e674df..217dbfa8 100644 --- a/src/test/resources/text-expectations/java/author-rest-resource.text +++ b/src/test/resources/text-expectations/java/author-rest-resource.text @@ -28,12 +28,6 @@ public class AuthorResource extends DynamicResourceHandler { private final Grid grid; private final AuthorQueries $queries; - public AuthorResource(final Grid grid) { - super(grid.world().stage()); - this.grid = grid; - this.$queries = QueryModelStateStoreProvider.instance().authorQueries; - } - public AuthorResource(final Grid grid, final AuthorQueries authorQueries) { super(grid.world().stage()); this.grid = grid; From b8e6e3366c29a9da806ba710e865b8f86669f090 Mon Sep 17 00:00:00 2001 From: Danilo Ambrosio Date: Wed, 31 Mar 2021 02:36:23 -0300 Subject: [PATCH 8/9] Supporting Queries injection for AutoDispatchResourceHandlers --- .../AutoDispatchResourceHandlerDetail.java | 31 +++++++++ .../DefaultBootstrapTemplateData.java | 2 +- .../template/bootstrap/RestResource.java | 67 ++++++++++++------- .../XoomInitializerTemplateData.java | 7 +- .../BootstrapGenerationStepTest.java | 47 +++++++++++-- .../java/default-bootstrap.text | 6 +- .../java/xoom-initializer.text | 11 +-- 7 files changed, 127 insertions(+), 44 deletions(-) create mode 100644 src/main/java/io/vlingo/xoom/codegen/template/autodispatch/AutoDispatchResourceHandlerDetail.java diff --git a/src/main/java/io/vlingo/xoom/codegen/template/autodispatch/AutoDispatchResourceHandlerDetail.java b/src/main/java/io/vlingo/xoom/codegen/template/autodispatch/AutoDispatchResourceHandlerDetail.java new file mode 100644 index 00000000..ed0875f9 --- /dev/null +++ b/src/main/java/io/vlingo/xoom/codegen/template/autodispatch/AutoDispatchResourceHandlerDetail.java @@ -0,0 +1,31 @@ +// Copyright © 2012-2021 VLINGO LABS. All rights reserved. +// +// This Source Code Form is subject to the terms of the +// Mozilla Public License, v. 2.0. If a copy of the MPL +// was not distributed with this file, You can obtain +// one at https://mozilla.org/MPL/2.0/. + +package io.vlingo.xoom.codegen.template.autodispatch; + +import io.vlingo.xoom.codegen.CodeGenerationContext; +import io.vlingo.xoom.codegen.content.CodeElementFormatter; +import io.vlingo.xoom.codegen.template.storage.Queries; + +import java.util.Optional; + +import static io.vlingo.xoom.codegen.template.TemplateParameter.*; +import static io.vlingo.xoom.codegen.template.TemplateStandard.AUTO_DISPATCH_RESOURCE_HANDLER; + +public class AutoDispatchResourceHandlerDetail { + + public static Optional findQueriesAttributeName(final String qualifiedName, final CodeGenerationContext context) { + final String packageName = CodeElementFormatter.packageOf(qualifiedName); + final String className = CodeElementFormatter.simpleNameOf(qualifiedName); + return context.templateParametersOf(AUTO_DISPATCH_RESOURCE_HANDLER).stream() + .filter(data -> data.parameters().find(REST_RESOURCE_NAME).equals(className)) + .filter(data -> data.parameters().find(PACKAGE_NAME).equals(packageName)) + .map(data -> data.parameters().find(QUERIES).getAttributeName()) + .filter(attributeName -> !attributeName.isEmpty()).findFirst(); + } + +} diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java index 0af2cec9..8aecb413 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/DefaultBootstrapTemplateData.java @@ -32,7 +32,7 @@ protected void enrichParameters(final CodeGenerationContext context) { STORE_PROVIDER, PROJECTION_DISPATCHER_PROVIDER, REST_RESOURCE, AUTO_DISPATCH_RESOURCE_HANDLER, EXCHANGE_BOOTSTRAP); - parameters().and(REST_RESOURCES, RestResource.from(useCQRS, context.contents())) + parameters().and(REST_RESOURCES, RestResource.from(context)) .and(EXCHANGE_BOOTSTRAP_NAME, EXCHANGE_BOOTSTRAP.resolveClassname()) .and(HAS_EXCHANGE, ContentQuery.exists(EXCHANGE_BOOTSTRAP, context.contents())) .addImports(qualifiedNames).addImports(storageType.resolveTypeRegistryQualifiedNames(useCQRS)); diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java index 7be6c016..f2a69678 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/RestResource.java @@ -7,24 +7,26 @@ package io.vlingo.xoom.codegen.template.bootstrap; +import io.vlingo.xoom.codegen.CodeGenerationContext; import io.vlingo.xoom.codegen.content.CodeElementFormatter; -import io.vlingo.xoom.codegen.content.Content; import io.vlingo.xoom.codegen.content.ContentQuery; -import io.vlingo.xoom.codegen.template.TemplateParameters; import io.vlingo.xoom.codegen.template.TemplateStandard; -import io.vlingo.xoom.codegen.template.storage.Model; -import io.vlingo.xoom.codegen.template.storage.StorageType; +import io.vlingo.xoom.codegen.template.autodispatch.AutoDispatchResourceHandlerDetail; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.IntStream; import java.util.stream.Stream; import static io.vlingo.xoom.codegen.template.TemplateParameter.MODEL; import static io.vlingo.xoom.codegen.template.TemplateParameter.STORAGE_TYPE; +import static io.vlingo.xoom.codegen.template.TemplateParameters.with; import static io.vlingo.xoom.codegen.template.TemplateStandard.AUTO_DISPATCH_RESOURCE_HANDLER; import static io.vlingo.xoom.codegen.template.TemplateStandard.REST_RESOURCE; +import static io.vlingo.xoom.codegen.template.storage.Model.QUERY; +import static io.vlingo.xoom.codegen.template.storage.StorageType.STATE_STORE; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; @@ -35,42 +37,57 @@ public class RestResource { private final String arguments; private final boolean last; - public static List from(boolean useCQRS, final List contents) { - final Set classNames = - ContentQuery.findClassNames(contents, REST_RESOURCE, - AUTO_DISPATCH_RESOURCE_HANDLER); + public static List from(final CodeGenerationContext context) { + final Set qualifiedNames = + ContentQuery.findFullyQualifiedClassNames(context.contents(), + REST_RESOURCE, AUTO_DISPATCH_RESOURCE_HANDLER); - final Iterator iterator = classNames.iterator(); + final Iterator iterator = qualifiedNames.iterator(); return IntStream - .range(0, classNames.size()) - .mapToObj(index -> new RestResource(iterator.next(), useCQRS, index, classNames.size())) + .range(0, qualifiedNames.size()) + .mapToObj(index -> new RestResource(iterator.next(), context, index, qualifiedNames.size())) .collect(toList()); } - private RestResource(final String restResourceName, - final Boolean useCQRS, + private RestResource(final String restResourceQualifiedName, + final CodeGenerationContext context, final int resourceIndex, final int numberOfResources) { - this.className = restResourceName; - this.objectName = CodeElementFormatter.simpleNameToAttribute(restResourceName); - this.arguments = resolveArguments(restResourceName, useCQRS); + this.className = CodeElementFormatter.simpleNameOf(restResourceQualifiedName); + this.objectName = CodeElementFormatter.qualifiedNameToAttribute(restResourceQualifiedName); + this.arguments = resolveArguments(restResourceQualifiedName, context); this.last = resourceIndex == numberOfResources - 1; } - private String resolveArguments(String restResourceName, Boolean useCQRS) { - final List arguments = Stream.of("grid").collect(toList()); + private String resolveArguments(final String restResourceName, final CodeGenerationContext context) { + final Stream defaultArgument = Stream.of("grid"); - if (useCQRS) { - final String storeProviderClass = TemplateStandard.STORE_PROVIDER.resolveClassname(TemplateParameters.with(STORAGE_TYPE, StorageType.STATE_STORE).and(MODEL, Model.QUERY)); - final String storeProviderName = CodeElementFormatter.simpleNameToAttribute(storeProviderClass); - final String queriesClassName = TemplateStandard.QUERIES.resolveClassname(restResourceName.replace("Resource", "")); - final String queriesAttributeName = CodeElementFormatter.simpleNameToAttribute(queriesClassName); - arguments.add(String.format("%s.%s", storeProviderName, queriesAttributeName)); + final Optional queriesActorInstancePath = + resolveQueriesActorInstancePath(restResourceName, context); + + final Stream queriesArgument = + queriesActorInstancePath.isPresent() ? + Stream.of(queriesActorInstancePath.get()) : Stream.empty(); + + return Stream.of(defaultArgument, queriesArgument).flatMap(s -> s).collect(joining(", ")); + } + + private Optional resolveQueriesActorInstancePath(final String restResourceQualifiedName, final CodeGenerationContext context) { + final Optional queriesAttributeName = + AutoDispatchResourceHandlerDetail.findQueriesAttributeName(restResourceQualifiedName, context); + + if(!queriesAttributeName.isPresent()) { + return Optional.empty(); } - return arguments.stream().collect(joining(", ")); + final String storeProviderClass = + TemplateStandard.STORE_PROVIDER.resolveClassname(with(STORAGE_TYPE, STATE_STORE).and(MODEL, QUERY)); + + final String path = + String.format("%s.%s", CodeElementFormatter.simpleNameToAttribute(storeProviderClass), queriesAttributeName.get()); + return Optional.of(path); } public String getClassName() { diff --git a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java index 8f74975e..ff71390a 100644 --- a/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java +++ b/src/main/java/io/vlingo/xoom/codegen/template/bootstrap/XoomInitializerTemplateData.java @@ -29,15 +29,14 @@ protected void enrichParameters(final CodeGenerationContext context) { final String xoomInitializerClass = context.parameterOf(XOOM_INITIALIZER_NAME); final Boolean blockingMessaging = context.parameterOf(BLOCKING_MESSAGING, Boolean::valueOf); final Boolean customInitialization = !xoomInitializerClass.equals(XOOM_INITIALIZER.resolveClassname()); - final Boolean useCQRS = context.parameterOf(CQRS, Boolean::valueOf); loadImports(context, contents); - parameters().and(TemplateParameter.BLOCKING_MESSAGING, blockingMessaging) + parameters().and(TemplateParameter.APPLICATION_NAME, appName) + .and(TemplateParameter.BLOCKING_MESSAGING, blockingMessaging) .and(TemplateParameter.XOOM_INITIALIZER_CLASS, xoomInitializerClass) .and(TemplateParameter.CUSTOM_INITIALIZATION, customInitialization) - .and(TemplateParameter.REST_RESOURCES, RestResource.from(useCQRS, contents)) - .and(TemplateParameter.APPLICATION_NAME, appName) + .and(TemplateParameter.REST_RESOURCES, RestResource.from(context)) .and(TemplateParameter.EXCHANGE_BOOTSTRAP_NAME, resolveExchangeBootstrapName(context)); } diff --git a/src/test/java/io/vlingo/xoom/codegen/template/bootstrap/BootstrapGenerationStepTest.java b/src/test/java/io/vlingo/xoom/codegen/template/bootstrap/BootstrapGenerationStepTest.java index c1f6b347..7c286abd 100644 --- a/src/test/java/io/vlingo/xoom/codegen/template/bootstrap/BootstrapGenerationStepTest.java +++ b/src/test/java/io/vlingo/xoom/codegen/template/bootstrap/BootstrapGenerationStepTest.java @@ -11,21 +11,21 @@ import io.vlingo.xoom.TextExpectation; import io.vlingo.xoom.codegen.CodeGenerationContext; import io.vlingo.xoom.codegen.content.Content; -import io.vlingo.xoom.codegen.content.TextBasedContent; -import io.vlingo.xoom.codegen.template.OutputFile; +import io.vlingo.xoom.codegen.parameter.CodeGenerationParameter; +import io.vlingo.xoom.codegen.parameter.Label; +import io.vlingo.xoom.codegen.template.*; import io.vlingo.xoom.codegen.template.projections.ProjectionType; -import org.apache.commons.lang3.StringUtils; +import io.vlingo.xoom.codegen.template.storage.Queries; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import javax.annotation.processing.Filer; import javax.lang.model.element.Element; -import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Paths; +import static io.vlingo.xoom.codegen.language.Language.JAVA; import static io.vlingo.xoom.codegen.parameter.Label.*; import static io.vlingo.xoom.codegen.template.TemplateStandard.*; @@ -63,7 +63,6 @@ public void testThatAnnotatedBootstrapIsGenerated() throws IOException { Assert.assertTrue(bootstrap.contains(TextExpectation.onJava().read("annotated-bootstrap"))); } - @Test public void testThatXoomInitializerIsGenerated() throws IOException { final CodeGenerationContext context = @@ -74,11 +73,13 @@ public void testThatXoomInitializerIsGenerated() throws IOException { loadParameters(context, false); loadContents(context); + context.registerTemplateProcessing(JAVA, loadAutoDispatchResourceHanlderTemplateData(), ORDER_RESOURCE_HANDLER_CONTENT); + new BootstrapGenerationStep().process(context); final Content xoomInitializer = context.findContent(XOOM_INITIALIZER, "XoomInitializer"); - Assert.assertEquals(7, context.contents().size()); + Assert.assertEquals(8, context.contents().size()); Assert.assertTrue(xoomInitializer.contains(TextExpectation.onJava().read("xoom-initializer"))); } @@ -98,6 +99,32 @@ private void loadContents(final CodeGenerationContext context) { context.addContent(PROJECTION_DISPATCHER_PROVIDER, new OutputFile(PERSISTENCE_PACKAGE_PATH, "ProjectionDispatcherProvider.java"), PROJECTION_DISPATCHER_PROVIDER_CONTENT); } + private TemplateData loadAutoDispatchResourceHanlderTemplateData() { + final CodeGenerationParameter autoDispatchParameter = + CodeGenerationParameter.of(AUTO_DISPATCH_NAME, "OrderResourceHandler") + .relate(QUERIES_PROTOCOL, "io.vlingo.xoomapp.infrastructure.persistence.OrderQueries") + .relate(Label.QUERIES_ACTOR, "io.vlingo.xoomapp.infrastructure.persistence.OrderQueriesActor"); + + return new TemplateData() { + @Override + public TemplateParameters parameters() { + return TemplateParameters.with(TemplateParameter.REST_RESOURCE_NAME, "OrderResourceHandler") + .and(TemplateParameter.PACKAGE_NAME, "io.vlingo.xoomapp.resource") + .and(TemplateParameter.QUERIES, Queries.from(autoDispatchParameter)); + } + + @Override + public TemplateStandard standard() { + return AUTO_DISPATCH_RESOURCE_HANDLER; + } + + @Override + public String filename() { + return standard().resolveFilename("OrderResource", parameters()); + } + }; + } + private static final String HOME_DIRECTORY = OperatingSystem.detect().isWindows() ? "D:\\projects" : "/home"; private static final String PROJECT_PATH = Paths.get(HOME_DIRECTORY, "xoom-app").toString(); @@ -128,6 +155,12 @@ private void loadContents(final CodeGenerationContext context) { "... \\n" + "}"; + private static final String ORDER_RESOURCE_HANDLER_CONTENT = + "package io.vlingo.xoomapp.resource; \\n" + + "public class OrderResourceHandler { \\n" + + "... \\n" + + "}"; + private static final String EXCHANGE_BOOTSTRAP_CONTENT = "package io.vlingo.xoomapp.infrastructure.exchange; \\n" + "public class ExchangeBootstrap implements ExchangeInitializer { \\n" + diff --git a/src/test/resources/text-expectations/java/default-bootstrap.text b/src/test/resources/text-expectations/java/default-bootstrap.text index 17a0f35e..90fb0b60 100644 --- a/src/test/resources/text-expectations/java/default-bootstrap.text +++ b/src/test/resources/text-expectations/java/default-bootstrap.text @@ -32,12 +32,12 @@ public class Bootstrap { QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, ProjectionDispatcherProvider.using(grid.world().stage()).storeDispatcher, exchangeInitializer.dispatcher()); - final AuthorResource authorResource = new AuthorResource(grid); final BookResource bookResource = new BookResource(grid); + final AuthorResource authorResource = new AuthorResource(grid); Resources allResources = Resources.are( - authorResource.routes(), - bookResource.routes() + bookResource.routes(), + authorResource.routes() ); server = Server.startWith(grid.world().stage(), allResources, Boot.serverPort(), Sizing.define(), Timing.define()); diff --git a/src/test/resources/text-expectations/java/xoom-initializer.text b/src/test/resources/text-expectations/java/xoom-initializer.text index cf8c92ba..2d6aa0d8 100644 --- a/src/test/resources/text-expectations/java/xoom-initializer.text +++ b/src/test/resources/text-expectations/java/xoom-initializer.text @@ -9,6 +9,7 @@ import io.vlingo.xoom.XoomInitializationAware; import io.vlingo.xoom.scooter.plugin.mailbox.blocking.BlockingMailboxPlugin; import io.vlingo.xoomapp.infrastructure.exchange.ExchangeBootstrap; +import io.vlingo.xoomapp.resource.OrderResourceHandler; import io.vlingo.xoomapp.resource.BookResource; import io.vlingo.xoomapp.resource.AuthorResource; import io.vlingo.xoomapp.infrastructure.persistence.ProjectionDispatcherProvider; @@ -48,15 +49,17 @@ public class XoomInitializer implements XoomInitializationAware { final QueryModelStateStoreProvider queryModelStateStoreProvider = QueryModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry); final CommandModelStateStoreProvider commandModelStateStoreProvider = CommandModelStateStoreProvider.using(grid.world().stage(), statefulTypeRegistry, exchangeInitializer.dispatcher()); - final AuthorResource authorResource = new AuthorResource(grid, queryModelStateStoreProvider.authorQueries); - final BookResource bookResource = new BookResource(grid, queryModelStateStoreProvider.bookQueries); + final OrderResourceHandler orderResourceHandler = new OrderResourceHandler(grid, queryModelStateStoreProvider.orderQueries); + final BookResource bookResource = new BookResource(grid); + final AuthorResource authorResource = new AuthorResource(grid); final Collection> sseResources = Loader.resourcesFrom(initializer.sseConfiguration()).values(); final Collection> feedResources = Loader.resourcesFrom(initializer.feedConfiguration()).values(); final Collection> staticResources = Loader.resourcesFrom(initializer.staticFilesConfiguration()).values(); final Collection> restResources = Arrays.asList( - authorResource.routes(), - bookResource.routes() + orderResourceHandler.routes(), + bookResource.routes(), + authorResource.routes() ); final Resource[] resources = From edac7a778641ab0fe4c21fa104923ca1b223363d Mon Sep 17 00:00:00 2001 From: Danilo Ambrosio Date: Wed, 31 Mar 2021 02:44:35 -0300 Subject: [PATCH 9/9] Fix broken test --- .../ProjectSettingsGenerationStepTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/io/vlingo/xoom/codegen/template/projectgenerationsettings/ProjectSettingsGenerationStepTest.java b/src/test/java/io/vlingo/xoom/codegen/template/projectgenerationsettings/ProjectSettingsGenerationStepTest.java index 14a03fa6..98f43ff1 100644 --- a/src/test/java/io/vlingo/xoom/codegen/template/projectgenerationsettings/ProjectSettingsGenerationStepTest.java +++ b/src/test/java/io/vlingo/xoom/codegen/template/projectgenerationsettings/ProjectSettingsGenerationStepTest.java @@ -38,7 +38,6 @@ public void testThatProjectSettingsIsGenerated() throws IOException { new ProjectSettingsGenerationStep().process(context); final Content projectSettings = context.findContent(TemplateStandard.PROJECT_SETTINGS, "xoom-app-generation-settings"); - Assert.assertTrue(projectSettings.contains(TextExpectation.onJava().read("project-settings"))); }