io.ultreia.java4all.application.template.spi.GenerateTemplateProcessor Maven / Gradle / Ivy
package io.ultreia.java4all.application.template.spi;
/*-
* #%L
* Application template
* %%
* Copyright (C) 2019 Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import com.google.auto.service.AutoService;
import io.ultreia.java4all.application.template.TemplateSupport;
import io.ultreia.java4all.util.ImportManager;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Generated;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
@SupportedAnnotationTypes("io.ultreia.java4all.application.template.spi.GenerateTemplate")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
@SupportedOptions({"debug", "quiet"})
public class GenerateTemplateProcessor extends AbstractProcessor {
private static final String TEMPLATE_JAVA_FILE = "package %1$s;\n" +
"\n" +
"%2$s" +
"\n@Generated(value = \"%3$s\", date = \"%4$s\")" +
"\npublic class %5$sTemplate extends TemplateSupport<%5$s> {\n" +
" private static %5$sTemplate INSTANCE = new %5$sTemplate();\n " +
"\n" +
"%6$s\n" +
"}\n";
private static final String METHOD_TEMPLATE =
" public static String generate%1$s(%2$s model) {\n" +
" return INSTANCE.generate(\"%3$s\", model);\n" +
" }\n";
private Set done = new TreeSet<>();
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
Set extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
for (Element annotatedElement : annotatedElements) {
TypeElement classElement = (TypeElement) annotatedElement;
String fullyQualifiedName = classElement.getQualifiedName().toString();
String packageName = processingEnv.getElementUtils().getPackageOf(classElement).toString();
String fullClassName = fullyQualifiedName.substring(packageName.length() + 1);
String className = fullClassName;
int i = className.indexOf(".");
if (i > -1) {
className = className.substring(i + 1);
}
String generatedClassName = packageName + "." + className + "Template";
if (!done.add(generatedClassName)) {
// Already done
logWarning(String.format("Skip already processed class: %s", generatedClassName));
continue;
}
logDebug(String.format("Detect application template: %s", classElement));
GenerateTemplate realAnnotation = classElement.getAnnotation(GenerateTemplate.class);
try {
generateFile(realAnnotation, packageName, generatedClassName, fullClassName, className);
} catch (IOException e) {
throw new RuntimeException(String.format("Can't generate template file for: %s", classElement), e);
}
}
}
return true;
}
private void generateFile(GenerateTemplate realAnnotation, String packageName, String generatedClassName, String fullClassName, String className) throws IOException {
ImportManager importManager = new ImportManager(packageName);
importManager.addImport(Generated.class);
importManager.addImport(TemplateSupport.class);
if (!className.equals(fullClassName)) {
importManager.addImport(packageName + "." + fullClassName);
}
String imports = importManager.getImportsSection("\n");
StringBuilder methodsBuilder = new StringBuilder();
String[] templates = realAnnotation.template();
if (templates.length == 1) {
methodsBuilder.append(String.format(METHOD_TEMPLATE, "", className, templates[0]));
} else {
for (String template : templates) {
String name = StringUtils.capitalize(StringUtils.removeEnd(template, ".ftl"));
methodsBuilder.append(String.format(METHOD_TEMPLATE, name, className, template));
}
}
String content = String.format(TEMPLATE_JAVA_FILE,
packageName,
imports,
getClass().getName(),
new Date(),
className,
methodsBuilder.toString());
generate(generatedClassName, content);
}
private void generate(String generatedClassName, String content) throws IOException {
logInfo(String.format("Generate application template: %s", generatedClassName));
JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(generatedClassName);
try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
out.print(content);
}
}
private void logDebug(String msg) {
if (processingEnv.getOptions().containsKey("debug")) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
}
}
private void logWarning(String msg) {
// if (processingEnv.getOptions().containsKey("debug")) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg);
// }
}
private void logInfo(String msg) {
if (!processingEnv.getOptions().containsKey("quiet")) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy