package org.camunda.bpm.swagger.maven.spoon; import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES; import static org.apache.maven.plugins.annotations.ResolutionScope.COMPILE_PLUS_RUNTIME; import static org.camunda.bpm.swagger.maven.spoon.SpoonProcessingMojo.GOAL; import static org.twdata.maven.mojoexecutor.MojoExecutor.executionEnvironment; import java.io.File; import java.nio.file.Files; import java.util.Arrays; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.BuildPluginManager; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.camunda.bpm.swagger.docs.DtoDocsYaml; import org.camunda.bpm.swagger.docs.ServiceDocsYaml; import org.camunda.bpm.swagger.docs.model.DtoDocs; import org.camunda.bpm.swagger.docs.model.ServiceDocs; import org.camunda.bpm.swagger.maven.spoon.fn.DownloadCamundaSources; import org.camunda.bpm.swagger.maven.spoon.processor.*; import org.twdata.maven.mojoexecutor.MojoExecutor; import lombok.Builder; import lombok.Getter; import lombok.NonNull; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import spoon.Launcher; import spoon.SpoonAPI; @Mojo( name = GOAL, defaultPhase = GENERATE_SOURCES, requiresDependencyResolution = COMPILE_PLUS_RUNTIME ) @Slf4j public class SpoonProcessingMojo extends AbstractMojo { @Builder @Getter public static class Context { private final boolean shouldCompile; private final boolean autoImports; private final boolean noClasspath; @NonNull private final File unpackDirectory; @NonNull private final File outputDirectory; @NonNull private final String camundaVersion; @NonNull private final MojoExecutor.ExecutionEnvironment executionEnvironment; private final File dtoYamlFile; private final File serviceYamlFile; // late init private DtoDocs dtoDocumentation; // late init private ServiceDocs serviceDocumentation; @SneakyThrows public Context initDirectory() { if (!unpackDirectory.exists()) { Files.createDirectories(unpackDirectory.toPath()); } return this; } @SneakyThrows private SpoonAPI spoon() { final Launcher spoon = new Launcher(); spoon.getEnvironment().setShouldCompile(shouldCompile); spoon.getEnvironment().setAutoImports(autoImports); spoon.getEnvironment().setNoClasspath(noClasspath); // DTO spoon.addProcessor(new ApiModelProcessor()); spoon.addProcessor(new ApiModelPropertyProcessor(this)); // Sub Resources spoon.addProcessor(new RestResourceProcessor(this)); spoon.addProcessor(new RestResourceMethodProcessor( this )); // Service spoon.addProcessor(new RestServiceProcessor(this)); spoon.addProcessor(new RestServiceMethodProcessor(this)); final String[] classpathElements = executionEnvironment.getMavenProject() .getCompileClasspathElements() .stream() .filter(s -> !executionEnvironment.getMavenProject().getBuild().getOutputDirectory().equals(s)) .toArray(String[]::new); final StringBuilder builder = new StringBuilder(); Arrays.stream(classpathElements).forEach(builder::append); log.debug("Using classpath: {}", builder.toString()); spoon.getEnvironment().setSourceClasspath(classpathElements); spoon.addInputResource(unpackDirectory.getPath()); spoon.setSourceOutputDirectory(outputDirectory.getPath()); return spoon; } public Context loadDtoDocumentation() { this.dtoDocumentation = new DtoDocsYaml().apply(dtoYamlFile); return this; } public Context loadServiceDocumentation() { this.serviceDocumentation = new ServiceDocsYaml().apply(serviceYamlFile); return this; } public Context downloadSources() { new DownloadCamundaSources(this).run(); return this; } public Context processSources() { spoon().run(); return this; } } public static final String GOAL = "process"; @Parameter(property = "camunda.version", required = true) protected String camundaVersion; @Parameter(property = "project", required = true, readonly = true) protected MavenProject project; @Parameter(property = "session", required = true, readonly = true) protected MavenSession session; @Parameter(defaultValue = "target/unpack") protected File unpackDirectory; @Parameter(defaultValue = "target/generated-sources/java") protected File outputDirectory; @Parameter(defaultValue = "${project.build.directory}/generated-sources/camunda-rest-dto-docs.yaml", required = true, readonly = true) protected File dtoYamlFile; @Parameter(defaultValue = "${project.build.directory}/generated-sources/camunda-rest-service-docs.yaml", required = true, readonly = true) protected File serviceYamlFile; @Component protected BuildPluginManager buildPluginManager; @Override @SneakyThrows public void execute() throws MojoExecutionException, MojoFailureException { Context.builder() .executionEnvironment(executionEnvironment(project, session, buildPluginManager)) .camundaVersion(camundaVersion) .unpackDirectory(unpackDirectory) .outputDirectory(outputDirectory) .noClasspath(false) .autoImports(false) .shouldCompile(false) .dtoYamlFile(dtoYamlFile) .serviceYamlFile(serviceYamlFile) .build() .initDirectory() .downloadSources() .loadDtoDocumentation() .loadServiceDocumentation() .processSources() ; } }