com.jaxio.celerio.template.TemplateExecution.java Source code

Java tutorial

Introduction

Here is the source code for com.jaxio.celerio.template.TemplateExecution.java

Source

/*
 * Copyright 2015 JAXIO http://www.jaxio.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     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 com.jaxio.celerio.template;

import com.jaxio.celerio.Config;
import com.jaxio.celerio.configuration.HeaderComment;
import com.jaxio.celerio.configuration.Module;
import com.jaxio.celerio.convention.CommentStyle;
import com.jaxio.celerio.convention.GeneratedPackage;
import com.jaxio.celerio.convention.WellKnownFolder;
import com.jaxio.celerio.model.Attribute;
import com.jaxio.celerio.model.support.ClassNamer;
import com.jaxio.celerio.model.support.ClassNamer2;
import com.jaxio.celerio.model.support.EnumNamer;
import com.jaxio.celerio.model.support.PackageImport;
import com.jaxio.celerio.output.OutputResult;
import com.jaxio.celerio.support.Namer;
import com.jaxio.celerio.template.pack.Template;
import com.jaxio.celerio.template.pack.TemplatePack;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.List;
import java.util.Map;

import static com.google.common.collect.Lists.newArrayList;
import static com.jaxio.celerio.convention.WellKnownFolder.*;
import static java.lang.Boolean.TRUE;
import static org.apache.commons.lang.StringUtils.*;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;

/**
 * The TemplateExecution is used from the template file (<code>$output</code> var) to:
 * <ul>
 * <li>configure where to write the evaluated template</li>
 * <li>manage java imports</li>
 * <li>abort the generation if needed</li>
 * </ul>
 */
@Slf4j
@Component
@Scope(SCOPE_PROTOTYPE)
public class TemplateExecution {

    private static final String DEFAULT_BASE_FOLDER = ""; // means '.'
    private static String JAVA_FILE_EXTENSION = ".java";
    private static String XML_FILE_EXTENSION = ".xml";

    @Autowired
    @Setter
    private PreviousEngine previousEngine;
    @Autowired
    private Config config;
    @Getter
    private String module;

    private TemplatePack templatePack;
    private Template template;

    // ------------------------------------------------------------
    // public methods below are called from templates to set
    // the target folder and filename
    // ------------------------------------------------------------

    // ---------------------------------
    // JAVA
    // ---------------------------------

    public String java(GeneratedPackage generatedPackage, String javaClassName) {
        generatedPackageRestriction(generatedPackage);
        return java(generatedPackage.getPackageName(), javaClassName);
    }

    public String java(EnumNamer enumNamer) {
        return java(enumNamer.getPackageName(), enumNamer.getType());
    }

    public String java(ClassNamer classNamer) {
        classTypeRestriction(classNamer);
        return java(classNamer.getPackageName(), classNamer.getType());
    }

    private String classTypeRestriction(ClassNamer classNamer) {
        return stopFileGeneration(
                !config.getCelerio().getConfiguration().getRestriction().canGenerate(classNamer.getClassType()));
    }

    private String wellKnownFolderRestriction(WellKnownFolder wellKnownFolder) {
        return stopFileGeneration(
                !config.getCelerio().getConfiguration().getRestriction().canGenerate(wellKnownFolder));
    }

    private String generatedPackageRestriction(GeneratedPackage generatedPackage) {
        return stopFileGeneration(
                !config.getCelerio().getConfiguration().getRestriction().canGenerate(generatedPackage));
    }

    public String java(ClassNamer classNamer, String javaClassName) {
        classTypeRestriction(classNamer);
        return java(classNamer.getPackageName(), javaClassName);
    }

    public String java(String javaPackageOrFolder, String javaClassName) {
        String filename = javaClassName;
        if (javaClassName.indexOf('.') == -1) {
            filename = filename + JAVA_FILE_EXTENSION;
        }
        return setCurrentFilename(javaPackageOrFolder.replace('.', '/'), filename, JAVA);
    }

    public String java(ClassNamer2 classNamer2) {
        return java(classNamer2.getPackageName(), classNamer2.getType());
    }

    public String java(ClassNamer2 classNamer2, String javaClassName) {
        return java(classNamer2.getPackageName(), javaClassName);
    }

    // ---------------------------------
    // JAVA TEST
    // ---------------------------------

    public String javaTest(GeneratedPackage generatedPackage, String javaClassName) {
        generatedPackageRestriction(generatedPackage);
        return javaTest(generatedPackage.getPackageName(), javaClassName);
    }

    public String javaTest(ClassNamer classNamer) {
        classTypeRestriction(classNamer);
        return javaTest(classNamer.getPackageName(), classNamer.getTestType());
    }

    public String javaInTest(ClassNamer classNamer) {
        classTypeRestriction(classNamer);
        return javaTest(classNamer.getPackageName(), classNamer.getType());
    }

    public String javaTest(ClassNamer classNamer, String javaClassName) {
        classTypeRestriction(classNamer);
        return javaTest(classNamer.getPackageName(), javaClassName);
    }

    public String javaTest(String javaPackageOrFolder, String javaClassName) {
        return setCurrentFilename(javaPackageOrFolder.replace('.', '/'), javaClassName + JAVA_FILE_EXTENSION,
                JAVA_TEST);
    }

    // Support for ClassNamer2 (defined in configuration)
    public void javaTest(ClassNamer2 classNamer2) {
        javaTest(classNamer2.getPackageName(), classNamer2.getType());
    }

    // ---------------------------------
    // Others
    // ---------------------------------

    public String config(String subFolder, String fileName) {
        return setCurrentFilename(subFolder, fileName, CONFIG);
    }

    public String resource(String resourceName) {
        return setCurrentFilename(resourceName, RESOURCES);
    }

    public String resource(String subFolder, String resourceName) {
        return setCurrentFilename(subFolder, resourceName, RESOURCES);
    }

    public String resource(GeneratedPackage generatedPackage, String resourceName) {
        return resource(generatedPackage.getPackagePath(), resourceName);
    }

    public String localization(String resourceName) {
        return setCurrentFilename(DEFAULT_BASE_FOLDER, resourceName, LOCALIZATION);
    }

    public String localization(String subFolder, String resourceName) {
        return setCurrentFilename(subFolder, resourceName, LOCALIZATION);
    }

    public String domainLocalization(String resourceName) {
        return setCurrentFilename(DEFAULT_BASE_FOLDER, resourceName, DOMAIN_LOCALIZATION);
    }

    public String domainLocalization(String subFolder, String resourceName) {
        return setCurrentFilename(subFolder, resourceName, DOMAIN_LOCALIZATION);
    }

    public String resourceTest(String resourceName) {
        return setCurrentFilename("", resourceName, RESOURCES_TEST);
    }

    public String resourceTest(String subFolder, String resourceName) {
        return setCurrentFilename(subFolder, resourceName, RESOURCES_TEST);
    }

    public String resourceTest(GeneratedPackage generatedPackage, String resourceName) {
        return resourceTest(generatedPackage.getPackagePath(), resourceName);
    }

    public String sql(String sqlFilename) {
        return setCurrentFilename(sqlFilename, SQL);
    }

    public String sql(String subFolder, String sqlFilename) {
        return setCurrentFilename(subFolder, sqlFilename, SQL);
    }

    public String spring(String springFilename) {
        return setCurrentFilename(springFilename, SPRING);
    }

    public String spring(String subFolder, String springFilename) {
        return setCurrentFilename(subFolder, springFilename, SPRING);
    }

    public String springTest(String springFilename) {
        return setCurrentFilename(springFilename, SPRING_TEST);
    }

    public String webapp(String filename) {
        return setCurrentFilename(filename, WEBAPP);
    }

    public String webapp(String subFolder, String filename) {
        return setCurrentFilename(subFolder, filename, WEBAPP);
    }

    public String flow(String subFolder, String filename) {
        return setCurrentFilename(subFolder, filename, FLOWS);
    }

    public String webinf(String filename) {
        return setCurrentFilename(filename, WEBINF);
    }

    public String webinf(String filePath, String filename) {
        return setCurrentFilename(filePath, filename, WEBINF);
    }

    public String view(String filename) {
        return setCurrentFilename(filename, VIEWS);
    }

    public String view(String filePath, String filename) {
        return setCurrentFilename(filePath, filename, VIEWS);
    }

    public String file(String filename) {
        return setCurrentFilename(DEFAULT_BASE_FOLDER, filename, DEFAULT_BASE_FOLDER, DEFAULT_BASE_FOLDER);
    }

    public String file(String filePath, String filename) {
        return setCurrentFilename(filePath, filename, DEFAULT_BASE_FOLDER, DEFAULT_BASE_FOLDER);
    }

    public String site(String filename) {
        return setCurrentFilename(filename, WellKnownFolder.SITE);
    }

    public String site(String filePath, String filename) {
        return setCurrentFilename(filePath, filename, WellKnownFolder.SITE);
    }

    private String setCurrentFilename(String filename, WellKnownFolder output) {
        wellKnownFolderRestriction(output);
        return setCurrentFilename(DEFAULT_BASE_FOLDER, filename, output.getFolder(), output.getGeneratedFolder());
    }

    private String setCurrentFilename(String folder, String filename, WellKnownFolder output) {
        wellKnownFolderRestriction(output);
        return setCurrentFilename(folder, filename, output.getFolder(), output.getGeneratedFolder());
    }

    private String setCurrentFilename(String folder, String filename, String userSpaceFolder,
            String generatedFolder) {
        try {
            previousEngine.setCurrentFilename(folder, filename, userSpaceFolder, generatedFolder);
        } catch (Exception e) {
            throw new RuntimeException("ouch", e);
        }
        if (filename.endsWith(JAVA_FILE_EXTENSION)) {
            return "" //
                    + getHeaderComment() + "package " + folder.replace("/", ".") + ";\n" //
                    + enableDynaImports();
        }
        if (filename.endsWith(XML_FILE_EXTENSION)) {
            return "" //
                    + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" //
                    + chop(getHeaderComment() + "\n");
        }
        return getHeaderComment();
    }

    public String getHeaderComment() {
        return getHeaderComment("");
    }

    public String getHeaderComment(String prepend) {
        String currentFilename = previousEngine.getCurrentFullFilename();
        if (!StringUtils.hasLength(currentFilename)) {
            throw new IllegalStateException("You cannot set a header before setting the output filename");
        }
        HeaderComment headerComment = config.getCelerio().getConfiguration().getHeaderComment();
        if (!headerComment.getInclude()) {
            return "";
        }
        CommentStyle commentStyle = CommentStyle.fromFilename(currentFilename);
        if (commentStyle == null) {
            return "";
        }
        List<String> comments = newArrayList(headerComment.getComments());
        if (TRUE == headerComment.getShowTemplateName()
                || config.getCelerio().getConfiguration().getRootPackage().startsWith("integration.test.")) {
            comments.add("Template " + templatePack.getName() + ":" + template.getName().replace('\\', '/'));
            if (template.hasProjectLink()) {
                comments.add("Template is part of Open Source Project: "
                        + template.getTemplatePackInfo().getProjectLink());
            }
        }
        return commentStyle.decorate(comments, prepend);
    }

    // ----------------------------------------------------
    // Module support
    // ----------------------------------------------------

    public void module(String module) {
        this.module = module;
    }

    // ---------------------------------------------------------------
    // Called from template, the filename is supposed be already set.
    // ---------------------------------------------------------------

    public String getCurrentClass() {
        return previousEngine.getCurrentClass();
    }

    public String getCurrentRootClass() {
        return previousEngine.getCurrentRootClass();
    }

    public String getCurrentRootCast() {
        return previousEngine.getCurrentRootCast();
    }

    // velocity does not work with varargs
    public String getCurrentRootCast(String generic1) {
        return previousEngine.getCurrentRootCast(generic1);
    }

    public String getCurrentRootCast(String generic1, String generic2) {
        return previousEngine.getCurrentRootCast(generic1, generic2);
    }

    public String getCurrentRootCast(String generic1, String generic2, String generic3) {
        return previousEngine.getCurrentRootCast(generic1, generic2, generic3);
    }

    public String getCurrentClassWithout_() {
        return previousEngine.getCurrentClassWithout_();
    }

    /**
     * Whether the current class is extended by the user using take over feature ?
     */
    public boolean isAbstract() {
        return ImportsContext.isExtendedByUser();
    }

    public String getAbstractSpace() {
        return isAbstract() ? "abstract " : "";
    }

    // ----------------------------------------------------
    // Dynamic package import manager
    // ----------------------------------------------------
    public String enableDynaImports() {
        return previousEngine.enableDynaImports();
    }

    public boolean isDynamicImportEnabled() {
        return previousEngine.isCurrentEnableDynamicImport();
    }

    /**
     * Import the passed fullType.
     */
    public void require(String fullType) {
        requireFirstTime(fullType);
    }

    /**
     * Import the passed namer's fullType.
     */
    public void require(Namer namer) {
        require(namer.getFullType());
    }

    /**
     * Import the passed namer's fullType corresponding metamodel (i.e. appends '_');
     */
    public void requireMetamodel(Namer namer) {
        require(namer.getFullType() + "_");
    }

    /**
     * Import the passed simpleClassName present in the passed generatedPackage.
     */
    public void require(GeneratedPackage generatedPackage, String simpleClassName) {
        requireFirstTime(generatedPackage.getPackageName() + "." + simpleClassName);
    }

    /**
     * Import the passed classNamer's type present in the passed packageNamer's package name.
     */
    public void require(Namer packageNamer, Namer classNamer) {
        requireFirstTime(packageNamer.getPackageName() + "." + classNamer.getType());
    }

    /**
     * Import all the packageImports.
     */
    public void require(List<PackageImport> packageImports) {
        ImportsContext.getCurrentImportsHolder().addImports(packageImports);
    }

    /**
     * Import statically the passed fullType.
     */
    public void requireStatic(String fullType) {
        requireFirstTime("static " + fullType);
    }

    /**
     * Import statically the passed simpleClassName present in the passed generatedPackage.
     */
    public void requireStatic(GeneratedPackage generatedPackage, String simpleClassName) {
        requireStatic(generatedPackage.getPackageName() + "." + simpleClassName);
    }

    /**
     * Import the passed fullType.
     *
     * @return true if the passed fullType is imported for the first time.
     */
    public boolean requireFirstTime(String fullType) {
        return ImportsContext.getCurrentImportsHolder().add(fullType);
    }

    /**
     * Import the passed namer's fullType.
     *
     * @return true if the passed namer's fullType is imported for the first time.
     */
    public boolean requireFirstTime(Namer namer) {
        return requireFirstTime(namer.getFullType());
    }

    /**
     * Import the passed attribute type.
     */
    public void require(Attribute attribute) {
        requireFirstTime(attribute);
    }

    /**
     * Import the passed attribute type.
     *
     * @return true if the passed attribute type is imported for the first time.
     */
    public boolean requireFirstTime(Attribute attribute) {
        if (!attribute.isJavaBaseClass()) {
            return ImportsContext.getCurrentImportsHolder().add(attribute.getFullType());
        }
        return false;
    }

    /**
     * Import the passed fullType and returns the corresponding annotation.
     * For example passing <code>com.comp.MyAnno</code> returns <code>@MyAno</code>
     * and imports <code>com.comp.MyAnno</code>.
     */
    public String dynamicAnnotation(String fullType) {
        return dynamicAnnotationSupport(fullType, true, false);
    }

    protected String dynamicAnnotationSupport(String fullType, boolean invokeRequire, boolean appendEol) {
        String eol = appendEol ? "\n" : "";
        if (fullType.contains("(")) {
            String fullTypeToImport = substringBefore(fullType, "(");
            String body = "(" + substringAfter(fullType, "(");
            if (invokeRequire) {
                require(fullTypeToImport);
            }
            if (fullTypeToImport.contains(".")) {
                return "@" + substringAfterLast(fullTypeToImport, ".") + body + eol;
            } else {
                return "@" + fullTypeToImport + body + eol;
            }
        } else {
            if (invokeRequire) {
                require(fullType);
            }
            if (fullType.contains(".")) {
                return "@" + substringAfterLast(fullType, ".") + eol;
            } else {
                return "@" + fullType + eol;
            }
        }
    }

    /**
     * Import the passed fullTypes and returns the corresponding annotations (one per line).
     * In case the current class is taken over by the user, the fullTypes are not imported
     * and each annotation line returned is commented out. A comment informs the java developer
     * that he should use these commented annotations in his subclass.
     */
    public String dynamicAnnotationTakeOver(String... fullTypes) {
        StringBuilder sb = new StringBuilder();
        if (!isAbstract()) {
            for (String fullType : fullTypes) {
                sb.append(dynamicAnnotationSupport(fullType, true, true));
            }
        } else {
            if (fullTypes.length > 1) {
                sb.append("// Make sure you use these " + fullTypes.length + " annotations in your subclass")
                        .append("\n");
            } else {
                sb.append("// Make sure you use this annotation in your subclass").append("\n");
            }

            for (String fullType : fullTypes) {
                sb.append("// ").append("@" + fullType).append("\n");
            }
        }
        return sb.toString();
    }

    // ----------------------------------------------------
    // Control generation
    // ----------------------------------------------------

    public String generateIf(Module module) {
        return generateIf(config.getCelerio().getConfiguration().has(module));
    }

    public String generateIf(boolean value) {
        return stopFileGeneration(!value);
    }

    public String generateIf(boolean value1, boolean value2) {
        return stopFileGeneration(!(value1 && value2));
    }

    public String skipIf(Module module) {
        return stopFileGeneration(config.getCelerio().getConfiguration().has(module));
    }

    public String skipIf(boolean value) {
        return stopFileGeneration(value);
    }

    public String stopFileGeneration(boolean stop) {
        if (stop) {
            stopFileGeneration();
        }
        return "";
    }

    public String stopFileGeneration() {
        previousEngine.stopFileGeneration();
        return "";
    }

    protected void write(OutputResult outputResult, Map<String, Object> context, TemplatePack templatePack,
            Template template) throws Exception {
        this.templatePack = templatePack;
        this.template = template;
        previousEngine.setOutputResult(outputResult);
        previousEngine.processDynamicFile(context, templatePack, template);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    public void createMetaModelTakeOver(ClassNamer entityModel, String content) {
        try {
            // we create automatically the take over only if the user has not himself for whatever reason 
            // taken over the meta model. BDF reported it as EVOSOCLE-283
            String potentialUserCreatedMetaModelPath = JAVA.getFolder() + "/" + entityModel.getPath() + "/"
                    + entityModel.getType() + "_.java";

            if (new File(
                    previousEngine.getOutputResult().getUserSource().getFullPath(potentialUserCreatedMetaModelPath))
                            .exists()) {
                log.info("Skip automatic take over for metamodel " + entityModel.getType()
                        + " since it was done by the developer");
                return;
            }

            String filePath = JAVA.getGeneratedFolder() + "/" + entityModel.getPath() + "/" + entityModel.getType()
                    + "_.java";
            filePath = filePath.replace("/", "" + File.separatorChar);
            previousEngine.getOutputResult().addContent(content.getBytes("UTF-8"), filePath, null, null);
            log.info("Automatic take over for metamodel " + entityModel.getType()
                    + " to be in sync with entity taken over.");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}