Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove singletons from generated code #18

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -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<String> 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().<Queries>find(QUERIES).getAttributeName())
.filter(attributeName -> !attributeName.isEmpty()).findFirst();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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(context))
.and(EXCHANGE_BOOTSTRAP_NAME, EXCHANGE_BOOTSTRAP.resolveClassname())
.and(HAS_EXCHANGE, ContentQuery.exists(EXCHANGE_BOOTSTRAP, context.contents()))
.addImports(qualifiedNames).addImports(storageType.resolveTypeRegistryQualifiedNames(useCQRS));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,89 @@

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.TemplateStandard;
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;

public class RestResource {

private final String className;
private final String objectName;
private final String arguments;
private final boolean last;

public static List<RestResource> from(final List<Content> contents) {
final Set<String> classNames =
ContentQuery.findClassNames(contents, REST_RESOURCE,
AUTO_DISPATCH_RESOURCE_HANDLER);
public static List<RestResource> from(final CodeGenerationContext context) {
final Set<String> qualifiedNames =
ContentQuery.findFullyQualifiedClassNames(context.contents(),
REST_RESOURCE, AUTO_DISPATCH_RESOURCE_HANDLER);

final Iterator<String> iterator = classNames.iterator();
final Iterator<String> iterator = qualifiedNames.iterator();

return IntStream.range(0, classNames.size()).mapToObj(index ->
new RestResource(iterator.next(), index,
classNames.size())).collect(toList());
return IntStream
.range(0, qualifiedNames.size())
.mapToObj(index -> new RestResource(iterator.next(), context, index, qualifiedNames.size()))
.collect(toList());
}

private RestResource(final String restResourceName,
private RestResource(final String restResourceQualifiedName,
final CodeGenerationContext context,
final int resourceIndex,
final int numberOfResources) {
this.className = restResourceName;
this.objectName = CodeElementFormatter.simpleNameToAttribute(restResourceName);
this.className = CodeElementFormatter.simpleNameOf(restResourceQualifiedName);
this.objectName = CodeElementFormatter.qualifiedNameToAttribute(restResourceQualifiedName);
this.arguments = resolveArguments(restResourceQualifiedName, context);
this.last = resourceIndex == numberOfResources - 1;
}

private String resolveArguments(final String restResourceName, final CodeGenerationContext context) {
final Stream<String> defaultArgument = Stream.of("grid");

final Optional<String> queriesActorInstancePath =
resolveQueriesActorInstancePath(restResourceName, context);

final Stream<String> queriesArgument =
queriesActorInstancePath.isPresent() ?
Stream.of(queriesActorInstancePath.get()) : Stream.empty();

return Stream.of(defaultArgument, queriesArgument).flatMap(s -> s).collect(joining(", "));
}

private Optional<String> resolveQueriesActorInstancePath(final String restResourceQualifiedName, final CodeGenerationContext context) {
final Optional<String> queriesAttributeName =
AutoDispatchResourceHandlerDetail.findQueriesAttributeName(restResourceQualifiedName, context);

if(!queriesAttributeName.isPresent()) {
return Optional.empty();
}

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() {
return className;
}
Expand All @@ -54,6 +98,10 @@ public String getObjectName() {
return objectName;
}

public String getArguments() {
return arguments;
}

public boolean isLast() {
return last;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,6 +27,7 @@
public class StoreProvider {

private final String className;
private final String objectName;
private final String arguments;

public static List<StoreProvider> from(final StorageType storageType,
Expand All @@ -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);
}

Expand Down Expand Up @@ -83,6 +86,10 @@ public String getClassName() {
return className;
}

public String getObjectName() {
return objectName;
}

public String getArguments() {
return arguments;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ protected void enrichParameters(final CodeGenerationContext context) {

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(contents))
.and(TemplateParameter.APPLICATION_NAME, appName)
.and(TemplateParameter.REST_RESOURCES, RestResource.from(context))
.and(TemplateParameter.EXCHANGE_BOOTSTRAP_NAME, resolveExchangeBootstrapName(context));
}

Expand Down
22 changes: 11 additions & 11 deletions src/main/resources/codegen/java/RestResource.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ public class ${resourceName} extends DynamicResourceHandler {
private final ${queries.protocolName} $queries;
</#if>

public ${resourceName}(final Grid grid) {
super(grid.world().stage());
<#if useAutoDispatch>
this.$stage = grid;
this.$logger = super.logger();
<#else>
this.grid = grid;
</#if>
<#if queries?has_content && !queries.empty>
this.$queries = ${storeProviderName}.instance().${queries.attributeName};
</#if>
public ${resourceName}(final Grid grid<#if queries?has_content && !queries.empty>, final ${queries.protocolName} ${queries.attributeName}</#if>) {
super(grid.world().stage());
<#if useAutoDispatch>
this.$stage = grid;
this.$logger = super.logger();
<#else>
this.grid = grid;
</#if>
<#if queries?has_content && !queries.empty>
this.$queries = ${queries.attributeName};
</#if>
}

<#list routeMethods as routeMethod>
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/codegen/java/XoomInitializer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ public class XoomInitializer implements XoomInitializationAware {
final ${registry.className} ${registry.objectName} = new ${registry.className}(grid.world());
</#list>
<#list providers as provider>
${provider.className}.using(${provider.arguments});
final ${provider.className} ${provider.objectName} = ${provider.className}.using(${provider.arguments});
</#list>

<#list restResources as restResource>
final ${restResource.className} ${restResource.objectName} = new ${restResource.className}(grid);
final ${restResource.className} ${restResource.objectName} = new ${restResource.className}(${restResource.arguments});
</#list>

final Collection<Resource<?>> sseResources = Loader.resourcesFrom(initializer.sseConfiguration()).values();
Expand Down
16 changes: 8 additions & 8 deletions src/main/resources/codegen/kotlin/RestResource.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ public class ${resourceName} : DynamicResourceHandler {
val $queries: ${queries.protocolName}
</#if>

public constructor(stage: Stage) : super(stage){
<#if useAutoDispatch>
this.$stage = super.stage()
this.$logger = super.logger()
</#if>
<#if queries?has_content && !queries.empty>
this.$queries = ${storeProviderName}.instance().${queries.attributeName}
</#if>
public constructor(stage: Stage<#if queries?has_content && !queries.empty>, ${queries.attributeName}: ${queries.protocolName}</#if>) : super(stage){
<#if useAutoDispatch>
this.$stage = super.stage()
this.$logger = super.logger()
</#if>
<#if queries?has_content && !queries.empty>
this.$queries = ${queries.attributeName}
</#if>
}

<#list routeMethods as routeMethod>
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/codegen/kotlin/XoomInitializer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public class XoomInitializer : XoomInitializationAware {
val ${registry.objectName}: ${registry.className} = ${registry.className}(world)
</#list>
<#list providers as provider>
${provider.className}.using(${provider.arguments})
val ${provider.objectName}: ${provider.className} = ${provider.className}.using(${provider.arguments});
</#list>

<#list restResources as restResource>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;

Expand Down Expand Up @@ -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 =
Expand All @@ -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")));
}

Expand All @@ -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();
Expand Down Expand Up @@ -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" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ 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;
this.$queries = authorQueries;
}

public Completes<Response> withName(final AuthorData data) {
Expand Down
Loading