1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.maven.plugin;
7   
8   import org.apache.maven.plugin.MojoExecutionException;
9   import org.apache.maven.plugins.annotations.LifecyclePhase;
10  import org.apache.maven.plugins.annotations.Mojo;
11  import org.apache.maven.plugins.annotations.Parameter;
12  
13  import java.io.File;
14  import java.io.IOException;
15  import java.util.Arrays;
16  import java.util.Collections;
17  import java.util.List;
18  import java.util.Set;
19  import java.util.stream.Collectors;
20  
21  import dev.metaschema.core.model.IModule;
22  import dev.metaschema.core.util.ObjectUtils;
23  import dev.metaschema.databind.codegen.IProduction;
24  import dev.metaschema.databind.codegen.JavaGenerator;
25  import dev.metaschema.databind.codegen.config.DefaultBindingConfiguration;
26  import dev.metaschema.databind.io.BindingException;
27  import edu.umd.cs.findbugs.annotations.NonNull;
28  
29  /**
30   * Goal which generates Java source files for a given set of Metaschema modules.
31   */
32  @Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
33  public class GenerateSourcesMojo
34      extends AbstractMetaschemaMojo {
35    private static final String STALE_FILE_NAME = "generateSourcesStaleFile";
36  
37    /**
38     * A set of binding configurations.
39     */
40    @Parameter
41    protected File[] configs;
42  
43    /**
44     * <p>
45     * Gets the last part of the stale filename.
46     * </p>
47     * <p>
48     * The full stale filename will be generated by pre-pending
49     * {@code "." + getExecution().getExecutionId()} to this staleFileName.
50     *
51     * @return the stale filename postfix
52     */
53    @Override
54    protected String getStaleFileName() {
55      return STALE_FILE_NAME;
56    }
57  
58    /**
59     * Retrieve a list of binding configurations.
60     *
61     * @return the collection of binding configurations
62     */
63    protected List<File> getConfigs() {
64      List<File> retval;
65      if (configs == null) {
66        retval = Collections.emptyList();
67      } else {
68        retval = Arrays.asList(configs);
69      }
70      return retval;
71    }
72  
73    /**
74     * Generate the Java source files for the provided Metaschemas.
75     *
76     * @param modules
77     *          the collection of Metaschema modules to generate sources for
78     * @return the list of generated Java source files
79     * @throws MojoExecutionException
80     *           if an error occurred while generating sources
81     */
82    @Override
83    @NonNull
84    protected List<File> generate(@NonNull Set<IModule> modules) throws MojoExecutionException {
85      DefaultBindingConfiguration bindingConfiguration = new DefaultBindingConfiguration();
86      for (File config : getConfigs()) {
87        try {
88          if (getLog().isInfoEnabled()) {
89            getLog().info("Loading binding configuration: " + config.getPath());
90          }
91          bindingConfiguration.load(config);
92        } catch (IOException | BindingException ex) {
93          throw new MojoExecutionException(
94              String.format("Unable to load binding configuration from '%s'.", config.getPath()), ex);
95        }
96      }
97  
98      IProduction production;
99      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 }