Skip to content

Commit

Permalink
[KOGITO-3972] Make TemplateGenerator use KogitoBuildContext (#934)
Browse files Browse the repository at this point in the history
* WIP

* [KOGITO-3974] PredictionModels and DecisionModels are now using templates + Created AbstractPredictionModels and AbstractDecisionModels with common code

* [KOGITO-3975] WIP, compile but integration broken tests

* [KOGITO-3975] Fix tests

* [KOGITO-3974] Revert ApplicationContainerGenerator changes and postpone ApplicationTemplate to a different PR

* [KOGITO-3975] Minor

* [KOGITO-3974] Fix missing conf use case

* [KOGITO-3975] Fix missing conf use case

* [KOGITO-3974] Fix test

* [KOGITO-3974] Reviewed DecisionModels/PredictionModels templates to move all the code to abstract

* [KOGITO-3974] Fix test

* [KOGITO-3975] update

* [KOGITO-3975] Minor

* [KOGITO-3972] Updated TemplatedGenerator to use KogitoBuildContext + Now TemplatedGenerator is only used as delegator + Created AbstractConfigGenerator to simplify ConfigGenerator logic

* [KOGITO-3972] Fix DMN hot reload

* Fix DMN hot reload

* Moved packageName, annotator and addonsConfig to AbstractGenerator + Renamed ApplicationGenerator.withGenerator as ApplicationGenerator.registerAndInitGenerator

* Added comment

* Fix tests

* Fix after merge

* Revert ApplicationGenerator.registerAndInitGenerator to ApplicationGenerator.withGenerator

* WIP commit

* Postponing moduleGenerator initialization when used (compilationUnit() module) + ApplicationSection.classDeclaration renamed compilationUnit to return the whole template

* Minor fixes

* Fix post merge

* Fix AbstractConfigGenerator to handle missing templates

* Minor

* Created JavaKogitoBuildContext for non-DI context + Moved DependencyInjectionAnnotator reference inside KogitoBuildContext to prevent inconsistent configuration + Removed all withDependencyInjectionAnnotator (no more needed) + Created a common hasDI() method inside KogitoBuildContext and removed all custom useInjection methods

* Introduced static AtomicReference in AbstractPredictionModels to make DMN+PMML integration works even if DecisionModels is loaded first + Fix native-image check

* After merge fix

* Minor

* Fix code smell

* Fix code smell

* Update DMNCompilationProvider.java

* Update ApplicationContainerGenerator.java

* Minor changes

* Minor fixes

* Make TemplatedGenerator final
  • Loading branch information
danielezonca authored Dec 21, 2020
1 parent 2641981 commit a59a15e
Show file tree
Hide file tree
Showing 78 changed files with 760 additions and 924 deletions.
7 changes: 3 additions & 4 deletions kogito-codegen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ configure its global behavior.

```java
ApplicationGenerator appGen =
new ApplicationGenerator(appPackageName, targetDirectory)
.withDependencyInjection(...)
new ApplicationGenerator(context, appPackageName, targetDirectory)
.withAddons(...);
```

Expand All @@ -22,11 +21,11 @@ configure its global behavior.
- Each `Generator` may come with its own specific configuration

```java
appGen.withGenerator(RuleCodegen.ofPath(ruleSourceDirectory))
appGen.setupGenerator(RuleCodegen.ofPath(ruleSourceDirectory))
.withKModule(getKModuleModel())
.withClassLoader(...);

appGen.withGenerator(ProcessCodegen.ofPath(processSourceDirectory))
appGen.setupGenerator(ProcessCodegen.ofPath(processSourceDirectory))
.withAddons(...);
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

package org.kie.kogito.codegen;

import org.kie.kogito.codegen.context.KogitoBuildContext;

/**
* Base implementation for an {@link ApplicationSection}.
* <p>
Expand All @@ -24,10 +26,12 @@
*/
public abstract class AbstractApplicationSection implements ApplicationSection {

protected final KogitoBuildContext buildContext;
private final String sectionClassName;

public AbstractApplicationSection(String sectionClassName) {
public AbstractApplicationSection(KogitoBuildContext buildContext, String sectionClassName) {
this.sectionClassName = sectionClassName;
this.buildContext = buildContext;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.kie.kogito.codegen;

import com.github.javaparser.ast.CompilationUnit;
import org.kie.kogito.codegen.context.KogitoBuildContext;

import java.util.Optional;

public class AbstractConfigGenerator {

private final TemplatedGenerator templatedGenerator;

public AbstractConfigGenerator(KogitoBuildContext buildContext, String packageName, String targetTypeName, String resourceCdi, String resourceSpring) {
this.templatedGenerator = new TemplatedGenerator(
buildContext,
packageName,
targetTypeName,
resourceCdi,
resourceSpring);
}

public Optional<GeneratedFile> generate() {
Optional<CompilationUnit> compilationUnit = templatedGenerator.compilationUnit();
return compilationUnit.map(cu ->
new GeneratedFile(GeneratedFile.Type.APPLICATION_CONFIG,
templatedGenerator.generatedFilePath(),
cu.toString()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@
import java.util.List;
import java.util.Map;

import org.kie.kogito.codegen.di.DependencyInjectionAnnotator;
import org.kie.kogito.codegen.metadata.DefaultLabeler;
import org.kie.kogito.codegen.metadata.Labeler;

public abstract class AbstractGenerator implements Generator {

protected Path projectDirectory;
protected GeneratorContext context;
protected DependencyInjectionAnnotator annotator;
protected GeneratorContext context = GeneratorContext.emptyContext();
protected String packageName = ApplicationGenerator.DEFAULT_PACKAGE_NAME;
protected AddonsConfig addonsConfig = AddonsConfig.DEFAULT;

Expand Down Expand Up @@ -70,11 +68,6 @@ public final Map<String, String> getLabels() {
return labels;
}

@Override
public void setDependencyInjection(DependencyInjectionAnnotator annotator) {
this.annotator = annotator;
}

@Override
public void setPackageName(String packageName) {
this.packageName = packageName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

package org.kie.kogito.codegen;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
Expand All @@ -26,49 +26,102 @@
import com.github.javaparser.ast.expr.ObjectCreationExpr;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import org.kie.kogito.Addons;
import org.kie.kogito.codegen.context.KogitoBuildContext;
import org.kie.kogito.codegen.decision.config.DecisionConfigGenerator;
import org.kie.kogito.codegen.prediction.config.PredictionConfigGenerator;
import org.kie.kogito.codegen.process.config.ProcessConfigGenerator;
import org.kie.kogito.codegen.rules.config.RuleConfigGenerator;

import static java.util.Arrays.asList;
import static java.util.Optional.ofNullable;
import static org.kie.kogito.codegen.CodegenUtils.newObject;

public class ApplicationConfigGenerator extends TemplatedGenerator {
public class ApplicationConfigGenerator {

private static final String CLASS_NAME = "ApplicationConfig";
private static final String RESOURCE_DEFAULT = "/class-templates/config/ApplicationConfigTemplate.java";
private static final String RESOURCE_CDI = "/class-templates/config/CdiApplicationConfigTemplate.java";
private static final String RESOURCE_SPRING = "/class-templates/config/SpringApplicationConfigTemplate.java";

private final TemplatedGenerator templatedGenerator;

private Collection<String> addons = Collections.emptyList();

public ApplicationConfigGenerator(String packageName) {
super(packageName,
CLASS_NAME,
RESOURCE_CDI,
RESOURCE_SPRING,
RESOURCE_DEFAULT);
private ProcessConfigGenerator processConfig;
private RuleConfigGenerator ruleConfig;
private DecisionConfigGenerator decisionConfig;
private PredictionConfigGenerator predictionConfig;
private ConfigBeanGenerator configBean;

public ApplicationConfigGenerator(KogitoBuildContext buildContext, String packageName) {
this.templatedGenerator = new TemplatedGenerator(
buildContext,
packageName,
CLASS_NAME,
RESOURCE_CDI,
RESOURCE_SPRING,
RESOURCE_DEFAULT);

this.configBean = new ConfigBeanGenerator(buildContext, packageName);
}

public ApplicationConfigGenerator withProcessConfig(ProcessConfigGenerator cfg) {
this.processConfig = cfg;
return this;
}

public ApplicationConfigGenerator withRuleConfig(RuleConfigGenerator cfg) {
this.ruleConfig = cfg;
return this;
}

public ApplicationConfigGenerator withDecisionConfig(DecisionConfigGenerator cfg) {
this.decisionConfig = cfg;
return this;
}

public ApplicationConfigGenerator withPredictionConfig(PredictionConfigGenerator cfg) {
this.predictionConfig = cfg;
return this;
}

@Override
public Optional<CompilationUnit> compilationUnit() {
Optional<CompilationUnit> compilationUnit = super.compilationUnit();
compilationUnit
.flatMap(u -> u.findFirst(ClassOrInterfaceDeclaration.class))
public Collection<GeneratedFile> generate() {
ArrayList<GeneratedFile> generatedFiles = new ArrayList<>();
generatedFiles.add(generateApplicationConfigDescriptor());

asList(processConfig, ruleConfig, predictionConfig, decisionConfig, configBean)
.forEach(configGenerator -> ofNullable(configGenerator)
.flatMap(AbstractConfigGenerator::generate)
.ifPresent(generatedFiles::add));

return generatedFiles;
}

private GeneratedFile generateApplicationConfigDescriptor() {
CompilationUnit compilationUnit = templatedGenerator.compilationUnitOrThrow();

compilationUnit.findFirst(ClassOrInterfaceDeclaration.class)
.ifPresent(this::replaceAddonPlaceHolder);
return compilationUnit;

return new GeneratedFile(GeneratedFile.Type.APPLICATION_CONFIG,
templatedGenerator.generatedFilePath(),
compilationUnit.toString());
}

private void replaceAddonPlaceHolder(ClassOrInterfaceDeclaration cls) {
// get the place holder and replace it with a list of the addons that have been found
NameExpr addonsPlaceHolder =
cls.findFirst(NameExpr.class, e -> e.getNameAsString().equals("$Addons$")).
orElseThrow(() -> new InvalidTemplateException(
typeName(),
templatePath(),
templatedGenerator.typeName(),
templatedGenerator.templatePath(),
"Missing $Addons$ placeholder"));

ObjectCreationExpr addonsList = generateAddonsList();
addonsPlaceHolder.getParentNode()
.orElseThrow(() -> new InvalidTemplateException(
typeName(),
templatePath(),
templatedGenerator.typeName(),
templatedGenerator.templatePath(),
"Cannot replace $Addons$ placeholder"))
.replace(addonsPlaceHolder, addonsList);
}
Expand All @@ -82,8 +135,7 @@ private ObjectCreationExpr generateAddonsList() {
return newObject(Addons.class, asListOfAddons);
}

public ApplicationConfigGenerator withAddons(Collection<String> addons) {
public void withAddons(Collection<String> addons) {
this.addons = addons;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,77 +21,76 @@
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.ObjectCreationExpr;
import com.github.javaparser.ast.expr.ThisExpr;
import org.kie.kogito.codegen.context.JavaKogitoBuildContext;
import org.kie.kogito.codegen.context.KogitoBuildContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

public class ApplicationContainerGenerator extends TemplatedGenerator {
public class ApplicationContainerGenerator {

public static final String APPLICATION_CLASS_NAME = "Application";
private static final String RESOURCE_CDI = "/class-templates/CdiApplicationTemplate.java";
private static final String RESOURCE_SPRING = "/class-templates/SpringApplicationTemplate.java";
private static final String RESOURCE_DEFAULT = "/class-templates/ApplicationTemplate.java";
private final TemplatedGenerator templatedGenerator;

private List<String> sections = new ArrayList<>();

public ApplicationContainerGenerator(String packageName) {
super(packageName,
APPLICATION_CLASS_NAME,
RESOURCE_CDI,
RESOURCE_SPRING,
RESOURCE_DEFAULT);
private KogitoBuildContext buildContext;

public ApplicationContainerGenerator(KogitoBuildContext buildContext, String packageName) {
this.templatedGenerator = new TemplatedGenerator(
buildContext,
packageName,
APPLICATION_CLASS_NAME,
RESOURCE_CDI,
RESOURCE_SPRING,
RESOURCE_DEFAULT);

this.buildContext = buildContext;
}

public ApplicationContainerGenerator withSections(List<String> sections) {
this.sections = sections;
return this;
}

public CompilationUnit getCompilationUnitOrThrow() {
return compilationUnit()
.orElseThrow(() -> new InvalidTemplateException(
APPLICATION_CLASS_NAME,
templatePath(),
"Cannot find template for " + super.typeName()));
}

@Override
public Optional<CompilationUnit> compilationUnit() {
Optional<CompilationUnit> optionalCompilationUnit = super.compilationUnit();
CompilationUnit compilationUnit =
optionalCompilationUnit
.orElseThrow(() -> new InvalidTemplateException(
APPLICATION_CLASS_NAME,
templatePath(),
"Cannot find template for " + super.typeName()));
protected CompilationUnit getCompilationUnitOrThrow() {
CompilationUnit compilationUnit = templatedGenerator.compilationUnitOrThrow("Cannot find template for " + templatedGenerator.typeName());

ClassOrInterfaceDeclaration cls = compilationUnit
.findFirst(ClassOrInterfaceDeclaration.class)
.orElseThrow(() -> new InvalidTemplateException(
APPLICATION_CLASS_NAME,
templatePath(),
templatedGenerator.templatePath(),
"Compilation unit doesn't contain a class or interface declaration!"));

// ApplicationTemplate (no CDI/Spring) has placeholders to replace
if (annotator == null) {
if (buildContext == null || buildContext instanceof JavaKogitoBuildContext) {
replacePlaceholder(getLoadEnginesMethod(cls), sections);
}

cls.getMembers().sort(new BodyDeclarationComparator());
return optionalCompilationUnit;

return compilationUnit;
}

public GeneratedFile generate() {
return new GeneratedFile(GeneratedFile.Type.APPLICATION,
templatedGenerator.generatedFilePath(),
getCompilationUnitOrThrow().toString());
}

private MethodCallExpr getLoadEnginesMethod(ClassOrInterfaceDeclaration cls) {
return cls.findFirst(MethodCallExpr.class, mtd -> "loadEngines".equals(mtd.getNameAsString()))
.orElseThrow(() -> new InvalidTemplateException(
APPLICATION_CLASS_NAME,
templatePath(),
templatedGenerator.templatePath(),
"Impossible to find loadEngines invocation"));
}

Expand Down
Loading

0 comments on commit a59a15e

Please sign in to comment.