fr.ird.observe.toolkit.eugene.templates.ModelInitializerTransformer Maven / Gradle / Ivy
Show all versions of eugene-templates-extension Show documentation
package fr.ird.observe.toolkit.eugene.templates;
/*-
* #%L
* ObServe Toolkit :: Eugene Templates Extension
* %%
* Copyright (C) 2017 - 2019 IRD, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* .
* #L%
*/
import com.google.auto.service.AutoService;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import fr.ird.observe.spi.model.initializer.GlobalModelInitializer;
import fr.ird.observe.spi.model.initializer.ModelInitializer;
import fr.ird.observe.spi.model.initializer.ModelInitializerRunner;
import io.ultreia.java4all.lang.Strings;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.java.BeanTransformer;
import org.nuiton.eugene.java.BeanTransformerContext;
import org.nuiton.eugene.java.BeanTransformerTagValues;
import org.nuiton.eugene.java.EugeneJavaTagValues;
import org.nuiton.eugene.java.ObjectModelTransformerToJava;
import org.nuiton.eugene.java.extension.ObjectModelAnnotation;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelInterface;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelPackage;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;
/**
* To generate model initializers per package.
*
*
* @author Tony Chemit - [email protected]
* @plexus.component role="org.nuiton.eugene.Template" role-hint="fr.ird.observe.toolkit.eugene.templates.ModelInitializerTransformer"
* @since 4.0
*/
public class ModelInitializerTransformer extends ObjectModelTransformerToJava {
private final EugeneJavaTagValues javaTemplatesTagValues;
private final BeanTransformerTagValues beanTagValues;
private final EugeneCoreTagValues coreTagValues;
private final ObserveTagValues observeTagValues;
private final String initializerPackageName;
public ModelInitializerTransformer() {
javaTemplatesTagValues = new EugeneJavaTagValues();
beanTagValues = new BeanTransformerTagValues();
coreTagValues = new EugeneCoreTagValues();
observeTagValues = new ObserveTagValues();
initializerPackageName = ModelInitializer.class.getPackage().getName();
}
@Override
public void transformFromModel(ObjectModel model) {
super.transformFromModel(model);
Multimap typesByPackage = ArrayListMultimap.create();
TreeMap packages = new TreeMap<>();
BeanTransformerContext context = new BeanTransformerContext(model, coreTagValues, javaTemplatesTagValues, beanTagValues, true, true, aClass -> {
ObjectModelPackage aPackage = model.getPackage(aClass.getPackageName());
boolean keep = !BeanTransformer.skipForInitializer(aPackage, aClass);
if (keep) {
if (!packages.containsValue(aPackage)) {
String priorityTagValue = observeTagValues.getPackagePriorityTagValue(aPackage);
if (priorityTagValue == null) {
throw new IllegalStateException("No `packagePriority` tag value defined on package: " + aPackage.getName());
}
int priority = Integer.parseInt(priorityTagValue);
if (packages.containsKey(priority)) {
throw new IllegalStateException(String.format("Can't add package %s, his priority %s is already used by package %s", packages.get(priority).getName(), priority, aPackage.getName()));
}
packages.put(priority, aPackage);
}
typesByPackage.put(aPackage.getName(), aClass);
}
return keep;
}, getLog());
context.report();
boolean useRelativeName = context.useRelativeName;
String[] relativeNameExcludes = context.relativeNameExcludes;
String globalInitializerClassName = model.getName() + "GlobalModelInitializer";
boolean generateGlobalModelInitializer = !getResourcesHelper().isJavaFileInClassPath(initializerPackageName + "." + globalInitializerClassName);
List modelInitializerNames = new LinkedList<>();
for (ObjectModelPackage aPackage : packages.values()) {
String packageName = aPackage.getName();
Collection classes = typesByPackage.get(packageName);
String initializerClassName = model.getName()+ Strings.getRelativeCamelCaseName(getDefaultPackageName(), packageName + ".") + "ModelInitializer";
modelInitializerNames.add(initializerClassName);
boolean generateModelInitializer = !getResourcesHelper().isJavaFileInClassPath(initializerPackageName + "." + initializerClassName);
String initializerRunnerClassName = initializerClassName + "Runner";
boolean generateInitializerRunner = !getResourcesHelper().isJavaFileInClassPath(initializerPackageName + "." + initializerRunnerClassName);
List methodNames = classes.stream().map(beanClass -> {
String beanName = context.classesNameTranslation.get(beanClass);
return getMethodName(useRelativeName, relativeNameExcludes, "init", packageName, beanName);
}).sorted().collect(Collectors.toList());
if (generateModelInitializer) {
generateModelInitializer(initializerClassName, methodNames);
}
if (generateInitializerRunner) {
generateModelInitializerRunner(initializerClassName, initializerRunnerClassName, methodNames);
}
}
if (generateGlobalModelInitializer) {
generateGlobalModelInitializer(globalInitializerClassName, modelInitializerNames);
}
}
private void generateGlobalModelInitializer(String globalInitializerClassName, List modelInitializerNames) {
ObjectModelClass output = createAbstractClass(globalInitializerClassName, initializerPackageName);
addInterface(output, GlobalModelInitializer.class);
StringBuilder bodyBuilder = new StringBuilder();
bodyBuilder.append(""
+"\n"
+" initializer.start();"
);
for (String modelInitializerName : modelInitializerNames) {
String methodName = "create" + modelInitializerName;
addOperation(output, methodName, modelInitializerName, ObjectModelJavaModifier.ABSTRACT);
bodyBuilder.append(""
+"\n"
+" new "+modelInitializerName+"Runner().run(initializer."+methodName+"());"
);
}
ObjectModelOperation runOperation = addOperation(output, "run", "void", ObjectModelJavaModifier.STATIC);
addParameter(runOperation, globalInitializerClassName,"initializer");
bodyBuilder.append(""
+"\n"
+" initializer.end();\n"
+" "
);
setOperationBody(runOperation, bodyBuilder.toString());
}
private void generateModelInitializer(String initializerClassName, List methodNames) {
ObjectModelInterface output = createInterface(initializerClassName, initializerPackageName);
addInterface(output, ModelInitializer.class);
for (String methodName : methodNames) {
addOperation(output, methodName, "void");
}
}
private void generateModelInitializerRunner(String initializerClassName, String initializerRunnerClassName, List methodNames) {
ObjectModelClass output = createClass(initializerRunnerClassName, initializerPackageName);
ObjectModelAnnotation annotation = addAnnotation(output, output, AutoService.class);
addAnnotationParameter(output, annotation, "value", "{" + ModelInitializerRunner.class.getSimpleName() + ".class}");
addInterface(output, ModelInitializerRunner.class.getName() + "<" + initializerClassName + ">");
ObjectModelOperation getTypeOperation = addOperation(output, "getInitializerType", "Class<" + initializerClassName + ">", ObjectModelJavaModifier.PUBLIC);
addAnnotation(output, getTypeOperation, Override.class);
setOperationBody(getTypeOperation, ""
+"\n"
+" return "+initializerClassName+".class;"
);
StringBuilder bodyBuilder = new StringBuilder();
bodyBuilder.append(""
+"\n"
+" initializer.start();"
);
for (String methodName : methodNames) {
bodyBuilder.append(""
+"\n"
+" initializer."+methodName+"();"
);
}
bodyBuilder.append(""
+"\n"
+" initializer.end();\n"
+""
);
ObjectModelOperation operation = addOperation(output, "run", "void", ObjectModelJavaModifier.PUBLIC);
addAnnotation(output, operation, Override.class);
addParameter(operation, initializerClassName, "initializer");
setOperationBody(operation, bodyBuilder.toString());
}
}