import java.io.File;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
+import java.util.Collections;
+import java.util.List;
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.opendaylight.controller.yang.model.api.Module;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
import org.opendaylight.controller.yang.model.api.SchemaContext;
-import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
-import org.opendaylight.controller.yang.model.parser.impl.YangModelParserImpl;
import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-@Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
+/**
+ * Generate sources from yang files using user provided set of
+ * {@link CodeGenerator}s. Steps of this process:
+ * <ol>
+ * <li>List yang files from {@link #yangFilesRootDir}</li>
+ * <li>Process yang files using {@link YangModelParserImpl}</li>
+ * <li>For each {@link CodeGenerator} from {@link #codeGenerators}:</li>
+ * <ol>
+ * <li>Instantiate using default constructor</li>
+ * <li>Call {@link CodeGenerator#generateSources(SchemaContext, File)}</li>
+ * </ol>
+ * </ol>
+ */
+@Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true)
public final class YangToSourcesMojo extends AbstractMojo {
- private static final String LOG_PREFIX = "yang-to-sources:";
-
- @Parameter(required = true)
+ /**
+ * Classes implementing {@link CodeGenerator} interface. An instance will be
+ * created out of every class using default constructor. Method {@link
+ * CodeGenerator#generateSources(SchemaContext, File, Set<String>
+ * yangModulesNames)} will be called on every instance.
+ */
+ @Parameter(required = false)
private CodeGeneratorArg[] codeGenerators;
- @Parameter(required = true)
- private String yangFilesRootDir;
+ /**
+ * Source directory that will be recursively searched for yang files (ending
+ * with .yang suffix).
+ */
+ @Parameter(required = false)
+ private String yangFilesRootDir; // defaults to ${basedir}/src/main/yang
- private final YangModelParser parser;
+ @Parameter(property = "project", required = true, readonly = true)
+ protected MavenProject project;
- @VisibleForTesting
- YangToSourcesMojo(CodeGeneratorArg[] codeGeneratorArgs,
- YangModelParser parser, String yangFilesRootDir) {
- super();
- this.codeGenerators = codeGeneratorArgs;
- this.yangFilesRootDir = yangFilesRootDir;
- this.parser = parser;
- }
+ @Parameter(property = "inspectDependencies", required = true, readonly = true)
+ private boolean inspectDependencies;
+
+ private YangToSourcesProcessor yangToSourcesProcessor;
public YangToSourcesMojo() {
- super();
- parser = new YangModelParserImpl();
- }
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- SchemaContext context = processYang();
- generateSources(context);
}
- /**
- * Generate {@link SchemaContext} with {@link YangModelParserImpl}
- */
- private SchemaContext processYang() throws MojoExecutionException {
- try {
- String[] yangFiles = Util.listFilesAsArrayOfPaths(yangFilesRootDir);
-
- if (yangFiles.length == 0)
- getLog().warn(
- Util.message("No %s file found in %s", LOG_PREFIX,
- Util.YANG_SUFFIX, yangFilesRootDir));
- // TODO only warning or throw exception ?
-
- Set<Module> parsedYang = parser.parseYangModels(yangFiles);
- SchemaContext resolveSchemaContext = parser
- .resolveSchemaContext(parsedYang);
- getLog().info(
- Util.message("%s files parsed from %s", LOG_PREFIX,
- Util.YANG_SUFFIX, Arrays.toString(yangFiles)));
- return resolveSchemaContext;
-
- // MojoExecutionException is thrown since execution cannot continue
- } catch (Exception e) {
- String message = Util.message("Unable to parse %s files from %s",
- LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir);
- getLog().error(message, e);
- throw new MojoExecutionException(message, e);
- }
+ @VisibleForTesting
+ YangToSourcesMojo(YangToSourcesProcessor processor) {
+ this.yangToSourcesProcessor = processor;
}
- /**
- * Call generate on every generator from plugin configuration
- */
- private void generateSources(SchemaContext context)
- throws MojoFailureException {
- if (codeGenerators.length == 0) {
- getLog().warn(
- Util.message("No code generators provided", LOG_PREFIX));
- return;
- }
-
- Map<String, String> thrown = Maps.newHashMap();
-
- for (CodeGeneratorArg codeGenerator : codeGenerators) {
- try {
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (yangToSourcesProcessor == null) {
+ List<CodeGeneratorArg> codeGeneratorArgs = processCodeGenerators(codeGenerators);
- generateSourcesWithOneGenerator(context, codeGenerator);
+ // defaults to ${basedir}/src/main/yang
+ File yangFilesRootFile = processYangFilesRootDir(yangFilesRootDir,
+ project.getBasedir());
- } catch (Exception e) {
- // try other generators, exception will be thrown after
- getLog().error(
- Util.message(
- "Unable to generate sources with %s generator",
- LOG_PREFIX,
- codeGenerator.getCodeGeneratorClass()), e);
- thrown.put(codeGenerator.getCodeGeneratorClass(), e.getClass()
- .getCanonicalName());
- }
+ yangToSourcesProcessor = new YangToSourcesProcessor(getLog(),
+ yangFilesRootFile, codeGeneratorArgs, project,
+ inspectDependencies);
}
+ yangToSourcesProcessor.execute();
+ }
- if (!thrown.isEmpty()) {
- String message = Util
- .message(
- "One or more code generators failed, including failed list(generatorClass=exception) %s",
- LOG_PREFIX, thrown.toString());
- getLog().error(message);
- throw new MojoFailureException(message);
+ private static List<CodeGeneratorArg> processCodeGenerators(
+ CodeGeneratorArg[] codeGenerators) {
+ List<CodeGeneratorArg> codeGeneratorArgs;
+ if (codeGenerators == null) {
+ codeGeneratorArgs = Collections.emptyList();
+ } else {
+ codeGeneratorArgs = Arrays.asList(codeGenerators);
}
+ return codeGeneratorArgs;
}
- /**
- * Instantiate generator from class and call required method
- */
- private void generateSourcesWithOneGenerator(SchemaContext context,
- CodeGeneratorArg codeGenerator) throws ClassNotFoundException,
- InstantiationException, IllegalAccessException {
-
- codeGenerator.check();
-
- CodeGenerator g = Util.getInstance(
- codeGenerator.getCodeGeneratorClass(), CodeGenerator.class);
- getLog().info(
- Util.message("Code generator instantiated from %s", LOG_PREFIX,
- codeGenerator.getCodeGeneratorClass()));
-
- Collection<File> generated = g.generateSources(context,
- codeGenerator.getOutputBaseDir());
- getLog().info(
- Util.message("Sources generated by %s: %s", LOG_PREFIX,
- codeGenerator.getCodeGeneratorClass(), generated));
+ private static File processYangFilesRootDir(String yangFilesRootDir,
+ File baseDir) {
+ File yangFilesRootFile;
+ if (yangFilesRootDir == null) {
+ yangFilesRootFile = new File(baseDir, "src" + File.separator
+ + "main" + File.separator + "yang");
+ } else {
+ File file = new File(yangFilesRootDir);
+ if (file.isAbsolute()) {
+ yangFilesRootFile = file;
+ } else {
+ yangFilesRootFile = new File(baseDir, file.getPath());
+ }
+ }
+ return yangFilesRootFile;
}
-
}