X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmaven-sal-api-gen-plugin%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fmaven%2Fapi%2Fgen%2Fplugin%2FCodeGeneratorImpl.java;h=7e7e3a1cbc2d8b119a8407c4ba32e403a28b80cc;hb=38dbc9a2dc81bbae83346e2eb1da6fbf38d57c36;hp=98036d61654578937dacdd08c60e2e03a9b3fdc5;hpb=89ffe8626f4addebedc19f4c85e12d35d047b2e0;p=mdsal.git diff --git a/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/maven/api/gen/plugin/CodeGeneratorImpl.java b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/maven/api/gen/plugin/CodeGeneratorImpl.java index 98036d6165..7e7e3a1cbc 100644 --- a/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/maven/api/gen/plugin/CodeGeneratorImpl.java +++ b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/maven/api/gen/plugin/CodeGeneratorImpl.java @@ -10,11 +10,13 @@ package org.opendaylight.mdsal.binding.maven.api.gen.plugin; import static java.util.Objects.requireNonNull; import com.google.common.base.Joiner; +import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.MultimapBuilder; import com.google.common.collect.Table; import com.google.common.collect.Table.Cell; -import com.google.common.io.Files; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; @@ -22,16 +24,19 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.ServiceLoader; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.apache.maven.project.MavenProject; -import org.opendaylight.mdsal.binding.generator.impl.BindingGeneratorImpl; +import org.opendaylight.mdsal.binding.generator.api.BindingGenerator; import org.opendaylight.mdsal.binding.java.api.generator.GeneratorJavaFile; import org.opendaylight.mdsal.binding.java.api.generator.GeneratorJavaFile.FileKind; import org.opendaylight.mdsal.binding.java.api.generator.YangModuleInfoTemplate; @@ -40,7 +45,6 @@ import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator; import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware; import org.opendaylight.yangtools.yang2sources.spi.MavenProjectAware; @@ -54,6 +58,7 @@ public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContext private static final Logger LOG = LoggerFactory.getLogger(CodeGeneratorImpl.class); private static final String FS = File.separator; + private BuildContext buildContext; private File projectBaseDir; private Map additionalConfig; @@ -68,7 +73,13 @@ public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContext outputBaseDir = outputDir == null ? getDefaultOutputBaseDir() : outputDir; - final List types = new BindingGeneratorImpl().generateTypes(context, yangModules); + // Step one: determine binding types which we are generating + final Stopwatch sw = Stopwatch.createStarted(); + final List types = ServiceLoader.load(BindingGenerator.class) + .findFirst().orElseThrow(() -> new IllegalStateException("No BindingGenerator implementation found")) + .generateTypes(context, yangModules); + LOG.info("Found {} Binding types in {}", types.size(), sw); + final GeneratorJavaFile generator = new GeneratorJavaFile(types); File persistentSourcesDir = null; @@ -89,7 +100,9 @@ public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContext final Table> generatedFiles = generator.generateFileContent( ignoreDuplicateFiles); - final List result = new ArrayList<>(generatedFiles.size()); + + // Step two: create generation tasks for each target file and group them by parent directory + final ListMultimap dirs = MultimapBuilder.hashKeys().arrayListValues().build(); for (Cell> cell : generatedFiles.cellSet()) { final File target; switch (cell.getRowKey()) { @@ -107,27 +120,35 @@ public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContext throw new IllegalStateException("Unsupported file type in " + cell); } - Files.createParentDirs(target); - try (OutputStream stream = buildContext.newFileOutputStream(target)) { - try (Writer fw = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) { - try (BufferedWriter bw = new BufferedWriter(fw)) { - bw.write(cell.getValue().get()); - } - } catch (IOException e) { - LOG.error("Failed to write generate output into {}", target.getPath(), e); - throw e; - } + dirs.put(target.getParentFile().toPath(), new GenerationTask(buildContext, target, cell.getValue())); + } + LOG.info("Generating {} Binding source files into {} directories", dirs.size(), dirs.keySet().size()); + + // Step three: submit parent directory creation tasks (via parallelStream()) and wait for them to complete + sw.reset().start(); + dirs.keySet().parallelStream().forEach(path -> { + try { + Files.createDirectories(path); + } catch (IOException e) { + throw new IllegalStateException("Failed to create " + path, e); } + }); + LOG.debug("Parent directories created in {}", sw); - result.add(target); - } + // Step four: submit all code generation tasks (via parallelStream()) and wait for them to complete + sw.reset().start(); + final List result = dirs.values().parallelStream() + .map(GenerationTask::generateFile) + .collect(Collectors.toList()); + LOG.debug("{} Binding source type files generated in {}", result.size(), sw); + // Step five: generate auxiliary files result.addAll(generateModuleInfos(outputBaseDir, yangModules, context, moduleResourcePathResolver)); return result; } private Collection generateModuleInfos(final File outputBaseDir, final Set yangModules, - final SchemaContext context, final Function> moduleResourcePathResolver) { + final EffectiveModelContext context, final Function> moduleResourcePathResolver) { Builder result = ImmutableSet.builder(); Builder bindingProviders = ImmutableSet.builder(); for (Module module : yangModules) { @@ -193,8 +214,8 @@ public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContext this.buildContext = requireNonNull(buildContext); } - private Set generateYangModuleInfo(final File outputBaseDir, final Module module, final SchemaContext ctx, - final Function> moduleResourcePathResolver, + private Set generateYangModuleInfo(final File outputBaseDir, final Module module, + final EffectiveModelContext ctx, final Function> moduleResourcePathResolver, final Builder providerSourceSet) { Builder generatedFiles = ImmutableSet.builder(); @@ -241,4 +262,31 @@ public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContext } return file; } + + private static final class GenerationTask { + private final BuildContext buildContext; + private final Supplier contentSupplier; + private final File target; + + GenerationTask(final BuildContext buildContext, final File target, final Supplier contentSupplier) { + this.buildContext = requireNonNull(buildContext); + this.target = requireNonNull(target); + this.contentSupplier = requireNonNull(contentSupplier); + } + + File generateFile() { + try { + try (OutputStream stream = buildContext.newFileOutputStream(target)) { + try (Writer fw = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) { + try (BufferedWriter bw = new BufferedWriter(fw)) { + bw.write(contentSupplier.get()); + } + } + } + } catch (IOException e) { + throw new IllegalStateException("Failed to generate file " + target, e); + } + return target; + } + } }