import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Verify;
import java.net.URI;
import java.util.Collection;
import java.util.Date;
-import java.util.Map.Entry;
-import java.util.NavigableMap;
import java.util.Optional;
import org.opendaylight.yangtools.concepts.SemVer;
import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
}
private static class SemanticVersionImport {
+
+ private abstract static class CompatibleCriterion extends NamespaceKeyCriterion<SemVerSourceIdentifier> {
+ private final String moduleName;
+
+ CompatibleCriterion(final String moduleName) {
+ this.moduleName = requireNonNull(moduleName);
+ }
+
+ @Override
+ public boolean match(final SemVerSourceIdentifier key) {
+ return moduleName.equals(key.getName());
+ }
+
+ @Override
+ public String toString() {
+ return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("moduleName", moduleName);
+ }
+ }
+
+ private static final class NoVerCompatibleCriterion extends CompatibleCriterion {
+ NoVerCompatibleCriterion(final String moduleName) {
+ super(moduleName);
+ }
+
+ @Override
+ public SemVerSourceIdentifier select(final SemVerSourceIdentifier first,
+ final SemVerSourceIdentifier second) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ }
+
+ private static final class SemVerCompatibleCriterion extends CompatibleCriterion {
+ private final SemVer semVer;
+
+ SemVerCompatibleCriterion(final String moduleName, final SemVer semVer) {
+ super(moduleName);
+ this.semVer = requireNonNull(semVer);
+ }
+
+ @Override
+ public boolean match(final SemVerSourceIdentifier key) {
+ if (!super.match(key)) {
+ return false;
+ }
+ final Optional<SemVer> optKeyVer = key.getSemanticVersion();
+ if (!optKeyVer.isPresent()) {
+ return false;
+ }
+
+ final SemVer keyVer = optKeyVer.get();
+ if (semVer.getMajor() != keyVer.getMajor()) {
+ return false;
+ }
+ if (semVer.getMinor() > keyVer.getMinor()) {
+ return false;
+ }
+ return semVer.getMinor() < keyVer.getMinor() || semVer.getPatch() <= keyVer.getPatch();
+ }
+
+ @Override
+ public SemVerSourceIdentifier select(final SemVerSourceIdentifier first,
+ final SemVerSourceIdentifier second) {
+ return first.getSemanticVersion().get().compareTo(second.getSemanticVersion().get()) >= 0 ? first
+ : second;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return super.addToStringAttributes(toStringHelper).add("version", semVer);
+ }
+ }
+
+
private SemanticVersionImport() {
throw new UnsupportedOperationException("Utility class");
}
private static void onLinkageDeclared(
final Mutable<String, ImportStatement, EffectiveStatement<String, ImportStatement>> stmt) {
- final ModuleIdentifier impIdentifier = getImportedModuleIdentifier(stmt);
final ModelActionBuilder importAction = stmt.newInferenceAction(SOURCE_LINKAGE);
- final Prerequisite<StmtContext<?, ?, ?>> imported = importAction.requiresCtx(stmt, ModuleNamespace.class,
- impIdentifier, SOURCE_LINKAGE);
- final Prerequisite<Mutable<?, ?, ?>> linkageTarget = importAction
- .mutatesCtx(stmt.getRoot(), SOURCE_LINKAGE);
+ final String moduleName = stmt.getStatementArgument();
+ final SemVer semanticVersion = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
+ final CompatibleCriterion criterion = semanticVersion == null ? new NoVerCompatibleCriterion(moduleName)
+ : new SemVerCompatibleCriterion(moduleName, semanticVersion);
+
+ final Prerequisite<StmtContext<?, ?, ?>> imported = importAction.requiresCtx(stmt,
+ SemanticVersionModuleNamespace.class, criterion, SOURCE_LINKAGE);
+ final Prerequisite<Mutable<?, ?, ?>> linkageTarget = importAction.mutatesCtx(stmt.getRoot(),
+ SOURCE_LINKAGE);
importAction.apply(new InferenceAction() {
@Override
public void apply(final InferenceContext ctx) {
- final Entry<SemVer, StmtContext<?, ?, ?>> importedModuleEntry = findRecentCompatibleModuleEntry(
- impIdentifier.getName(), stmt);
- if (importedModuleEntry == null) {
- throw new InferenceException(stmt.getStatementSourceReference(),
- "Unable to find module compatible with requested import [%s(%s)].",
- impIdentifier.getName(), getRequestedImportVersionString(stmt));
- }
-
- final StmtContext<?, ?, ?> importedModule = importedModuleEntry.getValue();
+ final StmtContext<?, ?, ?> importedModule = imported.resolve(ctx);
+ final SemVer importedVersion = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
final ModuleIdentifier importedModuleIdentifier = importedModule.getFromNamespace(
ModuleCtxToModuleIdentifier.class, importedModule);
final SemVerSourceIdentifier semVerModuleIdentifier = createSemVerModuleIdentifier(
- importedModuleIdentifier, importedModuleEntry.getKey());
+ importedModuleIdentifier, importedVersion);
linkageTarget.resolve(ctx).addToNs(ImportedModuleContext.class, importedModuleIdentifier,
importedModule);
public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
if (failed.contains(imported)) {
throw new InferenceException(stmt.getStatementSourceReference(),
- "Unable to find module compatible with requested import [%s(%s)].",
- impIdentifier.getName(), getRequestedImportVersionString(stmt));
+ "Unable to find module compatible with requested import [%s(%s)].", moduleName,
+ getRequestedImportVersionString(stmt));
}
}
});
}
private static String getRequestedImportVersionString(final StmtContext<?, ?, ?> stmt) {
- return getRequestedImportVersion(stmt).map(SemVer::toString).orElse("<any");
- }
-
- private static Entry<SemVer, StmtContext<?, ?, ?>> findRecentCompatibleModuleEntry(final String moduleName,
- final StmtContext<String, ImportStatement, EffectiveStatement<String, ImportStatement>> impStmt) {
- NavigableMap<SemVer, StmtContext<?, ?, ?>> allRelevantModulesMap = impStmt.getFromNamespace(
- SemanticVersionModuleNamespace.class, moduleName);
- if (allRelevantModulesMap == null) {
- return null;
- }
-
- final Optional<SemVer> optImportVer = getRequestedImportVersion(impStmt);
- if (optImportVer.isPresent()) {
- final SemVer importVer = optImportVer.get();
- allRelevantModulesMap = allRelevantModulesMap.subMap(importVer, true,
- SemVer.create(importVer.getMajor() + 1), false);
- }
-
- return allRelevantModulesMap.lastEntry();
- }
-
- private static ModuleIdentifier getImportedModuleIdentifier(
- final StmtContext<String, ImportStatement, ?> impStmt) {
- return ModuleIdentifierImpl.create(impStmt.getStatementArgument(), Optional.empty(),
- Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_IMP));
+ return getRequestedImportVersion(stmt).map(SemVer::toString).orElse("<any>");
}
private static SemVerSourceIdentifier createSemVerModuleIdentifier(
import java.net.URI;
import java.util.Date;
-import java.util.NavigableMap;
import java.util.Optional;
-import java.util.TreeMap;
import org.opendaylight.yangtools.concepts.SemVer;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
+import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
import org.opendaylight.yangtools.yang.model.util.ModuleIdentifierImpl;
import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
stmt.addToNs(ImportPrefixToModuleCtx.class, modulePrefix, stmt);
if (stmt.isEnabledSemanticVersioning()) {
- addToSemVerModuleNamespace(stmt);
+ addToSemVerModuleNamespace(stmt, moduleIdentifier);
}
}
- private static int compareNullableSemVer(final SemVer ver1, final SemVer ver2) {
- if (ver1 == null) {
- return ver2 == null ? 0 : -1;
- }
-
- return ver2 == null ? 1 : ver1.compareTo(ver2);
- }
-
private static void addToSemVerModuleNamespace(
- final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
+ final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt,
+ final ModuleIdentifier moduleIdentifier) {
final String moduleName = stmt.getStatementArgument();
- NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
- SemanticVersionModuleNamespace.class, moduleName);
- if (modulesMap == null) {
- modulesMap = new TreeMap<>(ModuleStatementSupport::compareNullableSemVer);
- }
final SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
- modulesMap.put(moduleSemVer, stmt);
- stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
+ final SemVerSourceIdentifier id = SemVerSourceIdentifier.create(moduleName, moduleSemVer);
+ stmt.addToNs(SemanticVersionModuleNamespace.class, id, stmt);
}
@Override
StatementParserMode.SEMVER_MODE);
fail("Test should fail due to invalid import of openconfig-version module");
} catch (ReactorException e) {
- assertTrue(e.getCause().getMessage().startsWith(
- "Unable to find module compatible with requested import " + "[openconfig-extensions(1.0.0)]."));
+ assertTrue(e.getCause().getCause().getMessage().startsWith(
+ "Unable to find module compatible with requested import [openconfig-extensions(1.0.0)]."));
}
}
StatementParserMode.SEMVER_MODE);
fail("Test should fail due to invalid import of openconfig-version module");
} catch (ReactorException e) {
- assertTrue(e.getCause().getMessage().startsWith(
- "Unable to find module compatible with requested import " + "[openconfig-extensions(0.9.9)]."));
+ assertTrue(e.getCause().getCause().getMessage().startsWith(
+ "Unable to find module compatible with requested import [openconfig-extensions(0.9.9)]."));
}
}
StatementParserMode.SEMVER_MODE);
fail("Test should fail due to invalid import of openconfig-version module");
} catch (ReactorException e) {
- assertTrue(e.getCause().getMessage().startsWith(
- "Unable to find module compatible with requested import " + "[openconfig-extensions(2.0.0)]."));
+ assertTrue(e.getCause().getCause().getMessage().startsWith(
+ "Unable to find module compatible with requested import [openconfig-extensions(2.0.0)]."));
}
}
StatementParserMode.SEMVER_MODE);
fail("Test should fail due to invalid import of openconfig-version module");
} catch (ReactorException e) {
- assertTrue(e.getCause().getMessage().startsWith(
- "Unable to find module compatible with requested import " + "[openconfig-extensions(2.0.5)]."));
+ assertTrue(e.getCause().getCause().getMessage().startsWith(
+ "Unable to find module compatible with requested import [openconfig-extensions(2.0.5)]."));
}
}
}