001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.maven.plugin;
007
008import org.apache.maven.plugin.MojoExecutionException;
009import org.apache.maven.plugins.annotations.LifecyclePhase;
010import org.apache.maven.plugins.annotations.Mojo;
011import org.apache.maven.plugins.annotations.Parameter;
012
013import java.io.File;
014import java.io.IOException;
015import java.util.Arrays;
016import java.util.Collections;
017import java.util.List;
018import java.util.Set;
019import java.util.stream.Collectors;
020
021import dev.metaschema.core.model.IModule;
022import dev.metaschema.core.util.ObjectUtils;
023import dev.metaschema.databind.codegen.IProduction;
024import dev.metaschema.databind.codegen.JavaGenerator;
025import dev.metaschema.databind.codegen.config.DefaultBindingConfiguration;
026import dev.metaschema.databind.io.BindingException;
027import edu.umd.cs.findbugs.annotations.NonNull;
028
029/**
030 * Goal which generates Java source files for a given set of Metaschema modules.
031 */
032@Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
033public class GenerateSourcesMojo
034    extends AbstractMetaschemaMojo {
035  private static final String STALE_FILE_NAME = "generateSourcesStaleFile";
036
037  /**
038   * A set of binding configurations.
039   */
040  @Parameter
041  protected File[] configs;
042
043  /**
044   * <p>
045   * Gets the last part of the stale filename.
046   * </p>
047   * <p>
048   * The full stale filename will be generated by pre-pending
049   * {@code "." + getExecution().getExecutionId()} to this staleFileName.
050   *
051   * @return the stale filename postfix
052   */
053  @Override
054  protected String getStaleFileName() {
055    return STALE_FILE_NAME;
056  }
057
058  /**
059   * Retrieve a list of binding configurations.
060   *
061   * @return the collection of binding configurations
062   */
063  protected List<File> getConfigs() {
064    List<File> retval;
065    if (configs == null) {
066      retval = Collections.emptyList();
067    } else {
068      retval = Arrays.asList(configs);
069    }
070    return retval;
071  }
072
073  /**
074   * Generate the Java source files for the provided Metaschemas.
075   *
076   * @param modules
077   *          the collection of Metaschema modules to generate sources for
078   * @return the list of generated Java source files
079   * @throws MojoExecutionException
080   *           if an error occurred while generating sources
081   */
082  @Override
083  @NonNull
084  protected List<File> generate(@NonNull Set<IModule> modules) throws MojoExecutionException {
085    DefaultBindingConfiguration bindingConfiguration = new DefaultBindingConfiguration();
086    for (File config : getConfigs()) {
087      try {
088        if (getLog().isInfoEnabled()) {
089          getLog().info("Loading binding configuration: " + config.getPath());
090        }
091        bindingConfiguration.load(config);
092      } catch (IOException | BindingException ex) {
093        throw new MojoExecutionException(
094            String.format("Unable to load binding configuration from '%s'.", config.getPath()), ex);
095      }
096    }
097
098    IProduction production;
099    try {
100      if (getLog().isInfoEnabled()) {
101        getLog().info("Generating Java classes in: " + getOutputDirectory().getPath());
102      }
103      production = JavaGenerator.generate(
104          modules,
105          ObjectUtils.notNull(getOutputDirectory().toPath()),
106          bindingConfiguration);
107    } catch (IOException ex) {
108      throw new MojoExecutionException("Creation of Java classes failed.", ex);
109    }
110
111    // add generated sources to Maven
112    try {
113      getMavenProject().addCompileSourceRoot(getOutputDirectory().getCanonicalFile().getPath());
114    } catch (IOException ex) {
115      throw new MojoExecutionException("Unable to add output directory to maven sources.", ex);
116    }
117
118    return ObjectUtils.notNull(production.getGeneratedClasses()
119        .map(gen -> gen.getClassFile().toFile())
120        .collect(Collectors.toUnmodifiableList()));
121  }
122}