*/
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;
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();
}
} 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();
}