Eliminate YangModelDependencyInfo
[yangtools.git] / parser / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / repo / DependencyResolver.java
index ba06ab4d64646bbeea3950b99c54dbac98185114..52afb83080799833d20b72a998cc2a784469251c 100644 (file)
@@ -7,23 +7,17 @@
  */
 package org.opendaylight.yangtools.yang.parser.repo;
 
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
-import java.util.ArrayList;
+import com.google.common.collect.Sets;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Optional;
-import org.opendaylight.yangtools.yang.common.Revision;
-import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
-import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.source.SourceDependency;
 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.stmt.ImportEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.spi.source.SourceInfo;
+import org.opendaylight.yangtools.yang.model.spi.source.SourceInfo.Submodule;
 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangModelDependencyInfo;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangModelDependencyInfo.SubmoduleDependencyInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,38 +35,21 @@ abstract class DependencyResolver {
 
     private final ImmutableList<SourceIdentifier> resolvedSources;
     private final ImmutableList<SourceIdentifier> unresolvedSources;
-    private final ImmutableMultimap<SourceIdentifier, ModuleImport> unsatisfiedImports;
+    private final ImmutableMultimap<SourceIdentifier, SourceDependency> unsatisfiedImports;
 
-    protected DependencyResolver(final Map<SourceIdentifier, YangModelDependencyInfo> depInfo) {
-        final var resolved = new ArrayList<SourceIdentifier>(depInfo.size());
-        final var pending = new ArrayList<>(depInfo.keySet());
-        final var submodules = new HashMap<SourceIdentifier, BelongsToDependency>();
+    protected DependencyResolver(final Map<SourceIdentifier, SourceInfo> depInfo) {
+        final var resolved = Sets.<SourceIdentifier>newHashSetWithExpectedSize(depInfo.size());
+        final var pending = new HashMap<>(depInfo);
 
         boolean progress;
         do {
             progress = false;
 
-            final var it = pending.iterator();
+            final var it = pending.values().iterator();
             while (it.hasNext()) {
-                final var sourceId = it.next();
-                final var dep = depInfo.get(sourceId);
-
-                // in case of submodule, remember belongs to
-                if (dep instanceof SubmoduleDependencyInfo submodule) {
-                    final var parent = submodule.getParentModule();
-                    submodules.put(sourceId, new BelongsToDependency(parent));
-                }
-
-                boolean okay = true;
-                for (var dependency : dep.getDependencies()) {
-                    if (!isKnown(resolved, dependency)) {
-                        LOG.debug("Source {} is missing import {}", sourceId, dependency);
-                        okay = false;
-                        break;
-                    }
-                }
-
-                if (okay) {
+                final var dep = it.next();
+                if (tryResolve(resolved, dep)) {
+                    final var sourceId = dep.sourceId();
                     LOG.debug("Resolved source {}", sourceId);
                     resolved.add(sourceId);
                     it.remove();
@@ -81,112 +58,84 @@ abstract class DependencyResolver {
             }
         } while (progress);
 
-        /// Additional check only for belongs-to statement
-        for (var submodule : submodules.entrySet()) {
-            final var sourceId = submodule.getKey();
-            final var belongs = submodule.getValue();
-            if (!isKnown(resolved, belongs)) {
-                LOG.debug("Source {} is missing parent {}", sourceId, belongs);
-                pending.add(sourceId);
-                resolved.remove(sourceId);
-            }
-        }
+        resolvedSources = ImmutableList.copyOf(resolved);
+        unresolvedSources = ImmutableList.copyOf(pending.keySet());
 
-        final var imports = ArrayListMultimap.<SourceIdentifier, ModuleImport>create();
-        for (var sourceId : pending) {
-            for (var dependency : depInfo.get(sourceId).getDependencies()) {
-                if (!isKnown(pending, dependency) && !isKnown(resolved, dependency)) {
-                    imports.put(sourceId, dependency);
+        final var unstatisfied = ImmutableMultimap.<SourceIdentifier, SourceDependency>builder();
+        for (var info : pending.values()) {
+            for (var dep : info.imports()) {
+                if (!isKnown(depInfo.keySet(), dep)) {
+                    unstatisfied.put(info.sourceId(), dep);
+                }
+            }
+            for (var dep : info.includes()) {
+                if (!isKnown(depInfo.keySet(), dep)) {
+                    unstatisfied.put(info.sourceId(), dep);
+                }
+            }
+            if (info instanceof Submodule submodule) {
+                final var dep = submodule.belongsTo();
+                if (!isKnown(depInfo.keySet(), dep)) {
+                    unstatisfied.put(info.sourceId(), dep);
                 }
             }
         }
-
-        resolvedSources = ImmutableList.copyOf(resolved);
-        unresolvedSources = ImmutableList.copyOf(pending);
-        unsatisfiedImports = ImmutableMultimap.copyOf(imports);
+        unsatisfiedImports = unstatisfied.build();
     }
 
-    protected abstract boolean isKnown(Collection<SourceIdentifier> haystack, ModuleImport mi);
-
-    abstract YangParserConfiguration parserConfig();
-
     /**
      * Collection of sources which have been resolved.
      */
-    ImmutableList<SourceIdentifier> resolvedSources() {
+    final ImmutableList<SourceIdentifier> resolvedSources() {
         return resolvedSources;
     }
 
     /**
      * Collection of sources which have not been resolved due to missing dependencies.
      */
-    ImmutableList<SourceIdentifier> unresolvedSources() {
+    final ImmutableList<SourceIdentifier> unresolvedSources() {
         return unresolvedSources;
     }
 
     /**
-     * Detailed information about which imports were missing. The key in the map
-     * is the source identifier of module which was issuing an import, the values
-     * are imports which were unsatisfied.
-     *
-     * <p>
-     * Note that this map contains only imports which are missing from the reactor,
-     * not transitive failures.
+     * Detailed information about which imports were missing. The key in the map is the source identifier of module
+     * which was issuing an import, the values are imports which were unsatisfied.
      *
      * <p>
-     * Examples:
-     * <ul><li>
-     * If A imports B, B imports C, and both A and B are in the reactor, only B->C
-     * will be reported.
-     * </li><li>
-     * If A imports B and C, B imports C, and both A and B are in the reactor,
-     * A->C and B->C will be reported.
-     * </li></ul>
+     * Note that this map contains only imports which are missing from the reactor, not transitive failures. Examples:
+     * <ul>
+     *   <li>if A imports B, B imports C, and both A and B are in the reactor, only B->C will be reported</li>
+     *   <li>if A imports B and C, B imports C, and both A and B are in the reactor, A->C and B->C will be reported</li>
+     * </ul>
      */
-    ImmutableMultimap<SourceIdentifier, ModuleImport> unsatisfiedImports() {
+    final ImmutableMultimap<SourceIdentifier, SourceDependency> unsatisfiedImports() {
         return unsatisfiedImports;
     }
 
-    private static class BelongsToDependency implements ModuleImport {
-        private final Unqualified parent;
-
-        BelongsToDependency(final Unqualified parent) {
-            this.parent = parent;
-        }
-
-        @Override
-        public Unqualified getModuleName() {
-            return parent;
-        }
-
-        @Override
-        public Optional<Revision> getRevision() {
-            return Optional.empty();
-        }
-
-        @Override
-        public Optional<String> getDescription() {
-            return Optional.empty();
+    private boolean tryResolve(final Collection<SourceIdentifier> resolved, final SourceInfo info) {
+        for (var dep : info.imports()) {
+            if (!isKnown(resolved, dep)) {
+                LOG.debug("Source {} is missing import {}", info.sourceId(), dep);
+                return false;
+            }
         }
-
-        @Override
-        public Optional<String> getReference() {
-            return Optional.empty();
+        for (var dep : info.includes()) {
+            if (!isKnown(resolved, dep)) {
+                LOG.debug("Source {} is missing include {}", info.sourceId(), dep);
+                return false;
+            }
         }
-
-        @Override
-        public String getPrefix() {
-            throw new UnsupportedOperationException();
+        if (info instanceof Submodule submodule) {
+            final var dep = submodule.belongsTo();
+            if (!isKnown(resolved, dep)) {
+                LOG.debug("Source {} is missing belongs-to {}", info.sourceId(), dep);
+                return false;
+            }
         }
+        return true;
+    }
 
-        @Override
-        public String toString() {
-            return MoreObjects.toStringHelper(this).add("parent", parent).toString();
-        }
+    abstract boolean isKnown(Collection<SourceIdentifier> haystack, SourceDependency dependency);
 
-        @Override
-        public ImportEffectiveStatement asEffectiveStatement() {
-            throw new UnsupportedOperationException();
-        }
-    }
+    abstract YangParserConfiguration parserConfig();
 }