import com.google.common.collect.Lists;
import com.google.common.collect.Table;
import java.net.URI;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.Submodule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class ModuleDependencySort {
private static final Logger LOG = LoggerFactory.getLogger(ModuleDependencySort.class);
+ private ModuleDependencySort() {
+ // Hidden on purpose
+ }
+
/**
- * It is not desirable to instance this class.
+ * Topological sort of module dependency graph.
+ *
+ * @param modules YANG modules
+ * @return Sorted list of Modules. Modules can be further processed in returned order.
+ * @throws IllegalArgumentException when provided modules are not consistent.
*/
- private ModuleDependencySort() {
- throw new UnsupportedOperationException();
+ public static List<Module> sort(final Module... modules) {
+ return sort(Arrays.asList(modules));
}
/**
* @return Sorted list of Modules. Modules can be further processed in returned order.
* @throws IllegalArgumentException when provided modules are not consistent.
*/
- public static List<Module> sort(final Collection<Module> modules) {
+ public static List<Module> sort(final Collection<? extends Module> modules) {
final List<Node> sorted = sortInternal(modules);
// Cast to Module from Node and return
return Lists.transform(sorted, input -> input == null ? null : ((ModuleNodeImpl) input).getReference());
}
- private static List<Node> sortInternal(final Collection<Module> modules) {
+ private static List<Node> sortInternal(final Collection<? extends Module> modules) {
final Table<String, Optional<Revision>, ModuleNodeImpl> moduleGraph = createModuleGraph(modules);
return TopologicalSort.sort(new HashSet<>(moduleGraph.values()));
}
private static Table<String, Optional<Revision>, ModuleNodeImpl> createModuleGraph(
- final Collection<Module> builders) {
+ final Collection<? extends Module> builders) {
final Table<String, Optional<Revision>, ModuleNodeImpl> moduleGraph = HashBasedTable.create();
processModules(moduleGraph, builders);
* Extract module:revision from modules.
*/
private static void processDependencies(final Table<String, Optional<Revision>, ModuleNodeImpl> moduleGraph,
- final Collection<Module> mmbs) {
+ final Collection<? extends Module> mmbs) {
final Map<URI, Module> allNS = new HashMap<>();
// Create edges in graph
}
// no need to check if other Type of object, check is performed in process modules
- for (final ModuleImport imprt : module.getImports()) {
+ for (final ModuleImport imprt : allImports(module)) {
final String toName = imprt.getModuleName();
final Optional<Revision> toRevision = imprt.getRevision();
}
}
+ private static Collection<? extends ModuleImport> allImports(final Module mod) {
+ if (mod.getSubmodules().isEmpty()) {
+ return mod.getImports();
+ }
+
+ final Collection<ModuleImport> concat = new LinkedHashSet<>();
+ concat.addAll(mod.getImports());
+ for (Submodule sub : mod.getSubmodules()) {
+ concat.addAll(sub.getImports());
+ }
+ return concat;
+ }
+
/**
* Get imported module by its name and revision from moduleGraph.
*/
}
// If revision is not specified in import, but module exists with different revisions, take first one
- if (toRevision == null) {
+ if (toRevision.isEmpty()) {
final Map<Optional<Revision>, ModuleNodeImpl> modulerevs = moduleGraph.row(toName);
if (!modulerevs.isEmpty()) {
* Extract dependencies from modules to fill dependency graph.
*/
private static void processModules(final Table<String, Optional<Revision>, ModuleNodeImpl> moduleGraph,
- final Iterable<Module> modules) {
+ final Iterable<? extends Module> modules) {
// Process nodes
for (final Module momb : modules) {