Improve SchemaInferenceStack.enterSchemaTree()
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / ModuleDependencySort.java
index 1d04ee310fee44559d23ca5be1bdb710a9ccfc66..5e9ba484de9d0cb5432f03bd1e5cbcf6368d7f4e 100644 (file)
@@ -12,9 +12,11 @@ import com.google.common.collect.HashBasedTable;
 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;
@@ -26,6 +28,7 @@ import org.opendaylight.yangtools.yang.common.Revision;
 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;
 
@@ -38,11 +41,19 @@ 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));
     }
 
     /**
@@ -52,19 +63,19 @@ public final class ModuleDependencySort {
      * @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);
@@ -77,7 +88,7 @@ public final class ModuleDependencySort {
      * 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
@@ -98,7 +109,7 @@ public final class ModuleDependencySort {
             }
 
             // 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();
 
@@ -127,6 +138,19 @@ public final class ModuleDependencySort {
         }
     }
 
+    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.
      */
@@ -140,7 +164,7 @@ public final class ModuleDependencySort {
         }
 
         // 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()) {
@@ -165,7 +189,7 @@ public final class ModuleDependencySort {
      * 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) {