*/
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.Preconditions;
+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;
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.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.java.api.generator.GeneratorJavaFile;
import org.opendaylight.mdsal.binding.java.api.generator.GeneratorJavaFile.FileKind;
import org.opendaylight.mdsal.binding.java.api.generator.YangModuleInfoTemplate;
import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
-import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
outputBaseDir = outputDir == null ? getDefaultOutputBaseDir() : outputDir;
+ // Step one: determine binding types which we are generating
+ final Stopwatch sw = Stopwatch.createStarted();
final List<Type> types = new BindingGeneratorImpl().generateTypes(context, yangModules);
+ LOG.info("Found {} Binding types in {}", types.size(), sw);
+
final GeneratorJavaFile generator = new GeneratorJavaFile(types);
File persistentSourcesDir = null;
final Table<FileKind, String, Supplier<String>> generatedFiles = generator.generateFileContent(
ignoreDuplicateFiles);
- final List<File> result = new ArrayList<>(generatedFiles.size());
+
+ // Step two: create generation tasks for each target file and group them by parent directory
+ final ListMultimap<Path, GenerationTask> dirs = MultimapBuilder.hashKeys().arrayListValues().build();
for (Cell<FileKind, String, Supplier<String>> cell : generatedFiles.cellSet()) {
final File target;
switch (cell.getRowKey()) {
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<File> 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;
}
File outputBaseDir;
outputBaseDir = new File(DEFAULT_OUTPUT_BASE_DIR_PATH);
setOutputBaseDirAsSourceFolder(outputBaseDir, mavenProject);
- LOG.debug("Adding " + outputBaseDir.getPath() + " as compile source root");
+ LOG.debug("Adding {} as compile source root", outputBaseDir.getPath());
return outputBaseDir;
}
private static void setOutputBaseDirAsSourceFolder(final File outputBaseDir, final MavenProject mavenProject) {
- Preconditions.checkNotNull(mavenProject, "Maven project needs to be set in this phase");
+ requireNonNull(mavenProject, "Maven project needs to be set in this phase");
mavenProject.addCompileSourceRoot(outputBaseDir.getPath());
}
@Override
public void setBuildContext(final BuildContext buildContext) {
- this.buildContext = Preconditions.checkNotNull(buildContext);
+ this.buildContext = requireNonNull(buildContext);
}
private Set<File> generateYangModuleInfo(final File outputBaseDir, final Module module, final SchemaContext ctx,
String providerSource = template.generateModelProvider();
final File packageDir = GeneratorJavaFile.packageToDirectory(outputBaseDir,
- BindingGeneratorUtil.moduleNamespaceToPackageName(module));
+ BindingMapping.getRootPackageName(module.getQNameModule()));
generatedFiles.add(writeJavaSource(packageDir, BindingMapping.MODULE_INFO_CLASS_NAME, moduleInfoSource));
generatedFiles
bw.write(source);
}
} catch (Exception e) {
- LOG.error("Could not write file: {}",file,e);
+ LOG.error("Could not write file: {}", file, e);
}
} catch (Exception e) {
- LOG.error("Could not create file: {}",file,e);
+ LOG.error("Could not create file: {}", file, e);
}
return file;
}
+
+ private static final class GenerationTask {
+ private final BuildContext buildContext;
+ private final Supplier<String> contentSupplier;
+ private final File target;
+
+ GenerationTask(final BuildContext buildContext, final File target, final Supplier<String> 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;
+ }
+ }
}