All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 annotations, RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {

            Set 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