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

io.zenwave360.generator.GeneratorMojo Maven / Gradle / Ivy

The newest version!
package io.zenwave360.generator;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;

/**
 * Goal which generates code with the configured ZenWave Code Generator plugin.
 */
@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
public class GeneratorMojo extends AbstractMojo {

      @Parameter( defaultValue = "${project.artifact}", readonly = true, required = true )
      private Artifact projectArtifact;
    /**
     * The name of the generator to use.
     */
    @Parameter(name = "generatorName", property = "zenwave.generatorName", required = true)
    private String generatorName;

    /**
     * Location of the JSON/YAML spec, as URL or file.
     */
    @Parameter(name = "inputSpec", property = "zenwave.inputSpec", required = true)
    private String inputSpec;

    /**
     * Location of the output directory.
     */
    @Parameter(name = "targetFolder", property = "zenwave.output", defaultValue = "${project.build.directory}/generated-sources/zenwave")
    private File targetFolder;

    /**
     * Add the output directory to the project as a source root, so that the generated java types are compiled and included in the project artifact.
     */
    @Parameter(defaultValue = "true")
    private boolean addCompileSourceRoot = true;
    /**
     * Add the 'src/test/java' directory to the project as a tests source, so that the generated java types are compiled and included in the project tests classpath.
     */
    @Parameter(defaultValue = "false")
    private boolean addTestCompileSourceRoot = false;


    /**
     * Include project classpath to the classpath of the generator. Useful to generate code from specs inside project dependencies.
     */
    @Parameter(defaultValue = "false")
    private boolean includeProjectClasspath = false;

    /**
     * A map of specific options for the called generator plugin.
     */
    @Parameter(name = "configOptions")
    private Map configOptions;

    /**
     * A configOptions string as 'key=value1,value2\nkey2=value3'.
     */
    @Parameter(name = "configKeyValueOptions", property = "zenwave.configOptions")
    private String configKeyValueOptions;

    @Parameter(name = "skip", property = "zenwave.skip", required = false, defaultValue = "false")
    private Boolean skip;

    /**
     * The project being built.
     */
    @Parameter(readonly = true, required = true, defaultValue = "${project}")
    private MavenProject project;

    public void execute() throws MojoExecutionException {
        addCompileSourceRootIfConfigured();

        if (skip) {
            getLog().info("Code generation is skipped.");
            return;
        }

        try {
            Map options = new HashMap<>();
            options.put("basePackage", project.getGroupId());

            if (configOptions != null) {
                options.putAll(configOptions);
            }

            if (StringUtils.isNotBlank(configKeyValueOptions)) {
                options.putAll(buildConfigOptions(configKeyValueOptions));
            }

            URLClassLoader projectClassLoader = null;
            if(includeProjectClasspath) {
                var classpathFiles = getProjectClasspathElements(project);
                projectClassLoader = new URLClassLoader(classpathFiles.toArray(new URL[0]), this.getClass().getClassLoader());
            }

            String specFile = inputSpec.startsWith("classpath:") ? inputSpec : new File(inputSpec).getAbsolutePath();
            Plugin plugin = Plugin.of(this.generatorName)
                    .withSpecFile(specFile)
                    .withTargetFolder(targetFolder.getAbsolutePath())
                    .withProjectClassLoader(projectClassLoader)
                    .withOptions(options);

            new MainGenerator().generate(plugin);
        } catch (Exception e) {
            // Maven logs exceptions thrown by plugins only if invoked with -e
            // I find it annoying to jump through hoops to get basic diagnostic information,
            // so let's log it in any case:
            e.printStackTrace();
            getLog().error(e);
            throw new MojoExecutionException("Code generation failed. See above for the full exception.");
        }
    }

    protected Map buildConfigOptions(String configOptions) {
        Map configMap = Arrays.asList(configOptions.split("\n"))
                .stream()
                .filter(str -> StringUtils.isNotBlank(str))
                .map(str -> str.split("=", 2))
                .collect(Collectors.toMap(split -> StringUtils.trim(split[0]), split -> StringUtils.trim(split[1])));
        return configMap;
    }

    private String getCompileSourceRoot() {
        final Object sourceFolderObject = configOptions == null ? null : configOptions.get("sourceFolder");
        final String sourceFolder = sourceFolderObject == null ? "src/main/java" : sourceFolderObject.toString();
        return new File(targetFolder, sourceFolder).getAbsolutePath();
    }

    private String getTestCompileSourceRoot() {
        final Object sourceFolderObject = configOptions == null ? null : configOptions.get("testSourceFolder");
        final String sourceFolder = sourceFolderObject == null ? "src/test/java" : sourceFolderObject.toString();
        return new File(targetFolder, sourceFolder).getAbsolutePath();
    }

    private void addCompileSourceRootIfConfigured() {
        if (addCompileSourceRoot) {
            String compileSourceRoot = getCompileSourceRoot();
            System.out.println("Adding source root " + compileSourceRoot);
            project.addCompileSourceRoot(compileSourceRoot);
        }
        if (addTestCompileSourceRoot) {
            String testCompileSourceRoot = getTestCompileSourceRoot();
            System.out.println("Adding tests source root " + testCompileSourceRoot);
            project.addTestCompileSourceRoot(testCompileSourceRoot);
        }
    }

    private List getProjectClasspathElements(MavenProject project) {
        List list = new ArrayList<>();
        project.getResources().stream().map(r -> new File(r.getDirectory())).forEach(list::add);
        list.add(new File(project.getBuild().getOutputDirectory()));
        list.addAll(project.getArtifacts().stream().map(Artifact::getFile).collect(Collectors.toList()));
        return list.stream().map(file -> {
            try {
                return file.toURI().toURL();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).collect(Collectors.toList());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy