Introducing of semantic version concept into SchemaContextFactory.
Change-Id: I382d6d6107852cd39a8e4023bbf2ae4d079782c7
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.model.repo.api;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.util.Objects;
+
+/**
+ * YANG Schema revision source identifier
+ *
+ * Simple transfer object represents revision identifier of source for YANG
+ * schema (module or submodule), which consists of
+ * <ul>
+ * <li>YANG schema name ({@link #getName()}
+ * <li>Module revision (optional) ({link {@link #getRevision()})
+ * </ul>
+ *
+ * Revision source identifier is designated to be carry only necessary
+ * information to look-up YANG model source and to be used by various
+ * SchemaSourceProviders.
+ *
+ * <b>Note:</b>On source retrieval layer it is impossible to distinguish between
+ * YANG module and/or submodule unless source is present.
+ *
+ * <p>
+ * (For further reference see: http://tools.ietf.org/html/rfc6020#section-5.2
+ * and http://tools.ietf.org/html/rfc6022#section-3.1 ).
+ */
+@Beta
+public final class RevisionSourceIdentifier extends SourceIdentifier {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ *
+ * Creates new YANG Schema revision source identifier for sources without
+ * revision. {@link SourceIdentifier#NOT_PRESENT_FORMATTED_REVISION} as
+ * default revision.
+ *
+ * @param name
+ * Name of schema
+ */
+ RevisionSourceIdentifier(final String name) {
+ this(name, NOT_PRESENT_FORMATTED_REVISION);
+ }
+
+ /**
+ * Creates new YANG Schema revision source identifier.
+ *
+ * @param name
+ * Name of schema
+ * @param formattedRevision
+ * Revision of source in format YYYY-mm-dd
+ */
+ RevisionSourceIdentifier(final String name, final String formattedRevision) {
+ super(Preconditions.checkNotNull(name), Preconditions.checkNotNull(formattedRevision));
+ }
+
+ /**
+ *
+ * Creates new YANG Schema revision source identifier.
+ *
+ * @param name
+ * Name of schema
+ * @param formattedRevision
+ * Revision of source in format YYYY-mm-dd. If not present,
+ * default value will be used.
+ */
+ RevisionSourceIdentifier(final String name, final Optional<String> formattedRevision) {
+ this(name, formattedRevision.or(NOT_PRESENT_FORMATTED_REVISION));
+ }
+
+ /**
+ *
+ * Creates new YANG Schema revision source identifier.
+ *
+ * @param moduleName
+ * Name of schema
+ * @param revision
+ * Revision of source in format YYYY-mm-dd. If not present,
+ * default value will be used.
+ */
+ public static RevisionSourceIdentifier create(final String moduleName,
+ final Optional<String> revision) {
+ return new RevisionSourceIdentifier(moduleName, revision);
+ }
+
+ /**
+ * Creates new YANG Schema revision source identifier.
+ *
+ * @param moduleName
+ * Name of schema
+ * @param revision
+ * Revision of source in format YYYY-mm-dd
+ */
+ public static RevisionSourceIdentifier create(final String moduleName, final String revision) {
+ return new RevisionSourceIdentifier(moduleName, revision);
+ }
+
+ /**
+ *
+ * Creates new YANG Schema revision source identifier for sources without
+ * revision. {@link SourceIdentifier#NOT_PRESENT_FORMATTED_REVISION} as
+ * default revision.
+ *
+ * @param moduleName
+ * Name of schema
+ */
+ public static RevisionSourceIdentifier create(final String moduleName) {
+ return new RevisionSourceIdentifier(moduleName);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Objects.hashCode(getName());
+ result = prime * result + Objects.hashCode(getRevision());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof RevisionSourceIdentifier)) {
+ return false;
+ }
+ final RevisionSourceIdentifier other = (RevisionSourceIdentifier) obj;
+ return Objects.equals(getName(), other.getName()) && Objects.equals(getRevision(), other.getRevision());
+ }
+
+ @Override
+ public String toString() {
+ return "RevisionSourceIdentifier [name=" + getName() + "@" + getRevision() + "]";
+ }
+}
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
/**
- * An asynchronous factory for building {@link SchemaContext} instances
- * based on a specification of what {@link SourceIdentifier}s are required
- * and dynamic recursive resolution.
+ * An asynchronous factory for building {@link SchemaContext} instances based on
+ * a specification of what {@link SourceIdentifier}s are required and dynamic
+ * recursive resolution.
*/
@Beta
public interface SchemaContextFactory {
/**
- * Create a new schema context containing specified sources, pulling in
- * any dependencies they may have.
+ * Create a new schema context containing specified sources, pulling in any
+ * dependencies they may have.
*
- * @param requiredSources a collection of sources which are required to
- * be present
- * @return A checked future, which will produce a schema context, or
- * fail with an explanation why the creation of the schema context
+ * @param requiredSources
+ * a collection of sources which are required to be present
+ * @return A checked future, which will produce a schema context, or fail
+ * with an explanation why the creation of the schema context
* failed.
*/
default CheckedFuture<SchemaContext, SchemaResolutionException> createSchemaContext(
@Nonnull Collection<SourceIdentifier> requiredSources) {
- return createSchemaContext(requiredSources, t -> true);
+ return createSchemaContext(requiredSources, StatementParserMode.DEFAULT_MODE, t -> true);
}
/**
- * Create a new schema context containing specified sources, pulling in
- * any dependencies they may have.
+ * Create a new schema context containing specified sources, pulling in any
+ * dependencies they may have.
*
- * @param requiredSources a collection of sources which are required to
- * be present
- * @param isFeatureSupported a predicate based on which all if-feature statements in the parsed yang
- * models are resolved
- * @return A checked future, which will produce a schema context, or
- * fail with an explanation why the creation of the schema context
+ * @param requiredSources
+ * a collection of sources which are required to be present
+ * @param statementParserMode
+ * mode of statement parser
+ * @return A checked future, which will produce a schema context, or fail
+ * with an explanation why the creation of the schema context
+ * failed.
+ */
+ default CheckedFuture<SchemaContext, SchemaResolutionException> createSchemaContext(
+ Collection<SourceIdentifier> requiredSources, StatementParserMode statementParserMode) {
+ return createSchemaContext(requiredSources, statementParserMode, t -> true);
+ }
+
+ /**
+ * Create a new schema context containing specified sources, pulling in any
+ * dependencies they may have.
+ *
+ * @param requiredSources
+ * a collection of sources which are required to be present
+ * @param isFeatureSupported
+ * a predicate based on which all if-feature statements in the
+ * parsed yang models are resolved
+ * @return A checked future, which will produce a schema context, or fail
+ * with an explanation why the creation of the schema context
+ * failed.
+ */
+ default CheckedFuture<SchemaContext, SchemaResolutionException> createSchemaContext(
+ @Nonnull Collection<SourceIdentifier> requiredSources, Predicate<QName> isFeatureSupported) {
+ return createSchemaContext(requiredSources, StatementParserMode.DEFAULT_MODE, isFeatureSupported);
+ }
+
+ /**
+ * Create a new schema context containing specified sources, pulling in any
+ * dependencies they may have.
+ *
+ * @param requiredSources
+ * a collection of sources which are required to be present
+ * @param statementParserMode
+ * mode of statement parser
+ * @param isFeatureSupported
+ * a predicate based on which all if-feature statements in the
+ * parsed yang models are resolved
+ * @return A checked future, which will produce a schema context, or fail
+ * with an explanation why the creation of the schema context
* failed.
*/
CheckedFuture<SchemaContext, SchemaResolutionException> createSchemaContext(
- @Nonnull Collection<SourceIdentifier> requiredSources, Predicate<QName> isFeatureSupported);
+ Collection<SourceIdentifier> requiredSources, StatementParserMode statementParserMode,
+ Predicate<QName> isFeatureSupported);
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.model.repo.api;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import java.util.Objects;
+import org.opendaylight.yangtools.concepts.SemVer;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+/**
+ * YANG Schema source identifier with specified semantic version
+ *
+ * Simple transfer object represents identifier of source for YANG schema
+ * (module or submodule), which consists of
+ * <ul>
+ * <li>YANG schema name {@link #getName()}
+ * <li>Semantic version of yang schema {@link #getSemanticVersion()}
+ * <li>(Optional) Module revision ({link {@link #getRevision()}
+ * </ul>
+ *
+ * Source identifier is designated to be carry only necessary information to
+ * look-up YANG model source and to be used by various SchemaSourceProviders.
+ *
+ * <b>Note:</b>On source retrieval layer it is impossible to distinguish between
+ * YANG module and/or submodule unless source is present.
+ *
+ * <p>
+ * (For further reference see: http://tools.ietf.org/html/rfc6020#section-5.2
+ * and http://tools.ietf.org/html/rfc6022#section-3.1 ).
+ */
+@Beta
+public final class SemVerSourceIdentifier extends SourceIdentifier {
+ private static final long serialVersionUID = 1L;
+ private final SemVer semVer;
+
+ /**
+ * Creates new YANG Schema semVer source identifier.
+ *
+ * @param name
+ * Name of schema
+ * @param formattedRevision
+ * Optional of source revision in format YYYY-mm-dd. If not
+ * present, default value will be used.
+ * @param semVer
+ * semantic version of source
+ */
+ SemVerSourceIdentifier(final String name, final Optional<String> formattedRevision, final SemVer semVer) {
+ this(name, formattedRevision.or(NOT_PRESENT_FORMATTED_REVISION), semVer);
+ }
+
+ /**
+ * Creates new YANG Schema semVer source identifier.
+ *
+ * @param name
+ * Name of schema
+ * @param semVer
+ * semantic version of source
+ */
+ SemVerSourceIdentifier(final String name, final SemVer semVer) {
+ this(name, Optional.absent(), semVer);
+ }
+
+ /**
+ * Creates new YANG Schema semVer source identifier.
+ *
+ * @param name
+ * Name of schema
+ * @param formattedRevision
+ * Revision of source in format YYYY-mm-dd
+ * @param semVer
+ * semantic version of source
+ */
+ SemVerSourceIdentifier(final String name, final String formattedRevision, final SemVer semVer) {
+ super(name, formattedRevision);
+ this.semVer = semVer == null ? Module.DEFAULT_SEMANTIC_VERSION : semVer;
+ }
+
+ /**
+ * Returns semantic version of source or
+ * {@link Module#DEFAULT_SEMANTIC_VERSION} if semantic version was not
+ * supplied.
+ *
+ * @return revision of source or {@link Module#DEFAULT_SEMANTIC_VERSION} if
+ * revision was not supplied.
+ */
+ public SemVer getSemanticVersion() {
+ return semVer;
+ }
+
+ /**
+ * Creates new YANG Schema semVer source identifier.
+ *
+ * @param moduleName
+ * Name of schema
+ * @param semVer
+ * semantic version of source
+ */
+ public static SemVerSourceIdentifier create(final String moduleName, final SemVer semVer) {
+ return new SemVerSourceIdentifier(moduleName, semVer);
+ }
+
+ /**
+ * Creates new YANG Schema semVer source identifier.
+ *
+ * @param moduleName
+ * Name of schema
+ * @param revision
+ * Revision of source in format YYYY-mm-dd
+ * @param semVer
+ * semantic version of source
+ */
+ public static SemVerSourceIdentifier create(final String moduleName, final String revision,
+ final SemVer semVer) {
+ return new SemVerSourceIdentifier(moduleName, revision, semVer);
+ }
+
+ /**
+ * Creates new YANG Schema semVer source identifier.
+ *
+ * @param moduleName
+ * Name of schema
+ * @param revision
+ * Optional of source revision in format YYYY-mm-dd. If not
+ * present, default value will be used.
+ * @param semVer
+ * semantic version of source
+ */
+ public static SemVerSourceIdentifier create(final String moduleName,
+ final Optional<String> revision, final SemVer semVer) {
+ return new SemVerSourceIdentifier(moduleName, revision, semVer);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Objects.hashCode(getName());
+ result = prime * result + Objects.hashCode(semVer);
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SemVerSourceIdentifier)) {
+ return false;
+ }
+ final SemVerSourceIdentifier other = (SemVerSourceIdentifier) obj;
+ return Objects.equals(getName(), other.getName()) && Objects.equals(semVer, other.semVer);
+ }
+
+ @Override
+ public String toString() {
+ return "SemVerSourceIdentifier [name=" + getName() + "(" + semVer + ")" + "@" + getRevision() + "]";
+ }
+}
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import java.util.Objects;
+import com.google.common.collect.Interner;
+import com.google.common.collect.Interners;
import java.util.regex.Pattern;
import org.opendaylight.yangtools.concepts.Identifier;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
/**
- * YANG Schema source identifier
+ * Base class of YANG Schema source identifiers.
*
- * Simple transfer object represents identifier of source for YANG schema (module or submodule),
- * which consists of
- * <ul>
- * <li>YANG schema name ({@link #getName()}
- * <li>Module revision (optional) ({link {@link #getRevision()})
- * </ul>
+ * Source identifiers are designated to be carry only necessary information to
+ * look-up YANG model source and to be used by various SchemaSourceProviders.
*
- * Source identifier is designated to be carry only necessary information
- * to look-up YANG model source and to be used by various SchemaSourceProviders.
- *
- * <b>Note:</b>On source retrieval layer it is impossible to distinguish
- * between YANG module and/or submodule unless source is present.
- *
- * <p>
- * (For further reference see: http://tools.ietf.org/html/rfc6020#section-5.2 and
- * http://tools.ietf.org/html/rfc6022#section-3.1 ).
+ * (For further reference see: http://tools.ietf.org/html/rfc6020#section-5.2
+ * and http://tools.ietf.org/html/rfc6022#section-3.1 ).
*/
@Beta
-public final class SourceIdentifier implements Identifier, Immutable {
+public abstract class SourceIdentifier implements Identifier, Immutable {
/**
- * Default revision for sources without specified revision.
- * Marks the source as oldest.
+ * Default revision for sources without specified revision. Marks the source
+ * as oldest.
*/
public static final String NOT_PRESENT_FORMATTED_REVISION = "0000-00-00";
* Simplified compiled revision pattern in format YYYY-mm-dd, which checks
* only distribution of number elements.
* <p>
- * For checking if supplied string is real date, use {@link SimpleDateFormatUtil}
- * instead.
+ * For checking if supplied string is real date, use
+ * {@link SimpleDateFormatUtil} instead.
*
*/
public static final Pattern REVISION_PATTERN = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\d");
private static final ObjectCache CACHE = ObjectCacheFactory.getObjectCache(SourceIdentifier.class);
+ private static final Interner<SourceIdentifier> INTERNER = Interners.newWeakInterner();
+
private static final long serialVersionUID = 1L;
private final String revision;
private final String name;
/**
*
* Creates new YANG Schema source identifier for sources without revision.
- * {@link SourceIdentifier#NOT_PRESENT_FORMATTED_REVISION} as default revision.
+ * {@link SourceIdentifier#NOT_PRESENT_FORMATTED_REVISION} as default
+ * revision.
*
- * @param name Name of schema
+ * @param name
+ * Name of schema
*/
- public SourceIdentifier(final String name) {
+ SourceIdentifier(final String name) {
this(name, NOT_PRESENT_FORMATTED_REVISION);
}
/**
* Creates new YANG Schema source identifier.
*
- * @param name Name of schema
- * @param formattedRevision Revision of source in format YYYY-mm-dd
+ * @param name
+ * Name of schema
+ * @param formattedRevision
+ * Revision of source in format YYYY-mm-dd
*/
- public SourceIdentifier(final String name, final String formattedRevision) {
+ SourceIdentifier(final String name, final String formattedRevision) {
this.name = Preconditions.checkNotNull(name);
this.revision = Preconditions.checkNotNull(formattedRevision);
}
*
* Creates new YANG Schema source identifier.
*
- * @param name Name of schema
- * @param formattedRevision Revision of source in format YYYY-mm-dd. If not present, default value will be used.
+ * @param name
+ * Name of schema
+ * @param formattedRevision
+ * Revision of source in format YYYY-mm-dd. If not present,
+ * default value will be used.
*/
- public SourceIdentifier(final String name, final Optional<String> formattedRevision) {
+ SourceIdentifier(final String name, final Optional<String> formattedRevision) {
this(name, formattedRevision.or(NOT_PRESENT_FORMATTED_REVISION));
}
*
* @return A potentially shared reference, not guaranteed to be unique.
*/
+ @Deprecated
public SourceIdentifier cachedReference() {
return CACHE.getReference(this);
}
+ /**
+ * Return an interned reference to a equivalent SemVerSourceIdentifier.
+ *
+ * @return Interned reference, or this object if it was interned.
+ */
+ public SourceIdentifier intern() {
+ return INTERNER.intern(this);
+ }
+
/**
* Returns model name
*
return revision;
}
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + Objects.hashCode(name);
- result = prime * result + Objects.hashCode(revision);
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- SourceIdentifier other = (SourceIdentifier) obj;
- return Objects.equals(name, other.name) && Objects.equals(revision, other.revision);
- }
-
+ @Deprecated
public static SourceIdentifier create(final String moduleName, final Optional<String> revision) {
- return new SourceIdentifier(moduleName, revision);
+ return new RevisionSourceIdentifier(moduleName, revision);
}
/**
* Returns filename for this YANG module as specified in RFC 6020.
*
- * Returns filename in format
- * <code>name ['@' revision] '.yang'</code>
+ * Returns filename in format <code>name ['@' revision] '.yang'</code>
* <p>
- * Where revision is date in format YYYY-mm-dd.
+ * Where revision is date in format YYYY-mm-dd.
* <p>
*
* @see <a href="http://tools.ietf.org/html/rfc6020#section-5.2">RFC6020</a>
return toYangFileName(name, Optional.fromNullable(revision));
}
- @Override
- public String toString() {
- return "SourceIdentifier [name=" + name + "@" + revision + "]";
- }
-
/**
* Returns filename for this YANG module as specified in RFC 6020.
*
- * Returns filename in format
- * <code>moduleName ['@' revision] '.yang'</code>
+ * Returns filename in format <code>moduleName ['@' revision] '.yang'</code>
*
* Where Where revision-date is in format YYYY-mm-dd.
*
* <p>
- * See
- * http://tools.ietf.org/html/rfc6020#section-5.2
+ * See http://tools.ietf.org/html/rfc6020#section-5.2
*
* @return Filename for this source identifier.
*/
filename.append(".yang");
return filename.toString();
}
-
}
*/
package org.opendaylight.yangtools.yang.model.repo.util;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
if (matcher.matches()) {
final String moduleName = matcher.group("moduleName");
final String revision = matcher.group("revision");
- return Optional.of(new SourceIdentifier(moduleName, Optional.fromNullable(revision)));
+ return Optional.of(RevisionSourceIdentifier.create(moduleName, Optional.fromNullable(revision)));
}
return Optional.absent();
}
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
@Test
public void sourceIdToFileEmptyRevWithEmptyDir() {
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test", "");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test", "");
final File sourceIdToFile = FilesystemSchemaSourceCache.sourceIdToFile(sourceIdentifier, this.storageDir);
final FilesystemSchemaSourceCache<YangTextSchemaSource> cache = new FilesystemSchemaSourceCache<>(this.registry,
YangTextSchemaSource.class, sourceIdToFile);
final YangTextSchemaSource source = new TestingYangSource("test", "2013-12-12", content);
cache.offer(source);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test", "");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test", "");
final File sourceIdToFile = FilesystemSchemaSourceCache.sourceIdToFile(sourceIdentifier,
this.storageDir);
Assert.assertNotNull(sourceIdToFile);
cache.offer(source);
cache.offer(source2);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test", "");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test", "");
final File sourceIdToFile = FilesystemSchemaSourceCache.sourceIdToFile(sourceIdentifier, this.storageDir);
Assert.assertNotNull(sourceIdToFile);
final List<File> storedFiles = Arrays.asList(this.storageDir.listFiles());
final String content = "content1";
final YangTextSchemaSource source = new TestingYangSource("test", "2013-12-12", content);
cache.offer(source);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test", "2013-12-12");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test", "2013-12-12");
final CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> checked = cache
.getSource(sourceIdentifier);
Assert.assertNotNull(checked);
final String content = "content1";
final YangTextSchemaSource source = new TestingYangSource("test", "2013-12-12", content);
cache.offer(source);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test1", "2012-12-12");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test1", "2012-12-12");
final CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> checked = cache
.getSource(sourceIdentifier);
Assert.assertNotNull(checked);
private final String content;
protected TestingYangSource(final String name, final String revision, final String content) {
- super(new SourceIdentifier(name, Optional.fromNullable(revision)));
+ super(RevisionSourceIdentifier.create(name, Optional.fromNullable(revision)));
this.content = content;
}
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
+
import com.google.common.base.Charsets;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
final String content = "content";
final YangTextSchemaSource source = new TestingYangSource("test", "2012-12-12", content);
inMemorySchemaSourceCache.offer(source);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test", "2012-12-12");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test", "2012-12-12");
final CheckedFuture<? extends YangSchemaSourceRepresentation, SchemaSourceException> checkedSource = inMemorySchemaSourceCache
.getSource(sourceIdentifier);
Assert.assertNotNull(checkedSource);
public void inMemorySchemaSourceCacheNullGetSourcestest() throws Exception {
final InMemorySchemaSourceCache<YangSchemaSourceRepresentation> inMemorySchemaSourceCache = InMemorySchemaSourceCache
.createSoftCache(this.registry, InMemorySchemaSourceCacheTest.representation);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test", "2012-12-12");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test", "2012-12-12");
final CheckedFuture<? extends YangSchemaSourceRepresentation, SchemaSourceException> checkedSource = inMemorySchemaSourceCache
.getSource(sourceIdentifier);
Assert.assertNotNull(checkedSource);
inMemorySchemaSourceCache.offer(source);
inMemorySchemaSourceCache2.offer(source);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("test", "2012-12-12");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("test", "2012-12-12");
final CheckedFuture<? extends YangSchemaSourceRepresentation, SchemaSourceException> checkedSource = inMemorySchemaSourceCache
.getSource(sourceIdentifier);
final CheckedFuture<? extends SchemaSourceRepresentation, SchemaSourceException> checkedSource2 = inMemorySchemaSourceCache2
private final String content;
protected TestingYangSource(final String name, final String revision, final String content) {
- super(new SourceIdentifier(name, Optional.fromNullable(revision)));
+ super(RevisionSourceIdentifier.create(name, Optional.fromNullable(revision)));
this.content = content;
}
*/
package org.opendaylight.yangtools.yang.model.repo.util;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.CheckedFuture;
import java.util.Arrays;
public void schemaSourceTransformerGetSourceTest() throws Exception {
final Provider p = new Provider();
final Registrator reg = new Registrator(p, SchemaSourceTransformerTest.SRC_CLASS, PotentialSchemaSource.Costs.IMMEDIATE);
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("source");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("source");
reg.register(sourceIdentifier);
this.schema = new SchemaSourceTransformer<>(p,
SchemaSourceTransformerTest.SRC_CLASS, this.consumer, SchemaSourceTransformerTest.DST_CLASS,
@Test
public void schemaSourceRegAndUnregSchemaSourceTest() throws Exception {
- final SourceIdentifier sourceIdentifier = new SourceIdentifier("source");
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("source");
final Foo<YangSchemaSourceRepresentation> foo = new Foo<>(sourceIdentifier,
SchemaSourceTransformerTest.SRC_CLASS,
PotentialSchemaSource.Costs.COMPUTATION);
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import java.io.InputStream;
import java.util.Date;
import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
import org.opendaylight.yangtools.yang.parser.impl.ParserListenerUtils;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.SupportedExtensionsMapping;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
private final String name;
private final String formattedRevision;
private final Date revision;
+ private final Optional<SemVer> semVer;
private final ImmutableSet<ModuleImport> submoduleIncludes;
private final ImmutableSet<ModuleImport> moduleImports;
private final ImmutableSet<ModuleImport> dependencies;
YangModelDependencyInfo(final String name, final String formattedRevision,
final ImmutableSet<ModuleImport> imports,
final ImmutableSet<ModuleImport> includes) {
+ this(name, formattedRevision, imports, includes, Optional.absent());
+ }
+
+ YangModelDependencyInfo(final String name, final String formattedRevision,
+ final ImmutableSet<ModuleImport> imports,
+ final ImmutableSet<ModuleImport> includes,
+ final Optional<SemVer> semVer) {
this.name = name;
this.formattedRevision = formattedRevision;
this.revision = formattedRevision == null ? null : QName
this.submoduleIncludes = includes;
this.dependencies = ImmutableSet.<ModuleImport> builder()
.addAll(moduleImports).addAll(submoduleIncludes).build();
+ this.semVer = semVer;
}
/**
return revision;
}
+ /**
+ * Returns semantic version of module
+ *
+ * @return semantic version
+ */
+ public Optional<SemVer> getSemanticVersion() {
+ return semVer;
+ }
+
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Objects.hashCode(formattedRevision);
result = prime * result + Objects.hashCode(name);
+ result = prime * result + Objects.hashCode(semVer);
return result;
}
if (!(obj instanceof YangModelDependencyInfo)) {
return false;
}
- YangModelDependencyInfo other = (YangModelDependencyInfo) obj;
+ final YangModelDependencyInfo other = (YangModelDependencyInfo) obj;
if (formattedRevision == null) {
if (other.formattedRevision != null) {
return false;
} else if (!name.equals(other.name)) {
return false;
}
+ if(!Objects.equals(semVer, other.semVer)) {
+ return false;
+ }
+
return true;
}
final ParserRuleContext tree) throws YangSyntaxErrorException {
if (tree instanceof YangStatementParser.StatementContext) {
- YangStatementParser.StatementContext rootStatement = (YangStatementParser.StatementContext) tree;
+ final YangStatementParser.StatementContext rootStatement = (YangStatementParser.StatementContext) tree;
return parseAST(rootStatement);
}
}
private static YangModelDependencyInfo parseAST(
- YangStatementParser.StatementContext rootStatement) {
+ final YangStatementParser.StatementContext rootStatement) {
if (rootStatement
.keyword()
.getText()
*/
public static YangModelDependencyInfo fromInputStream(
final InputStream yangStream) {
- StatementContext yangAST = new YangStatementSourceImpl(yangStream)
+ final StatementContext yangAST = new YangStatementSourceImpl(yangStream)
.getYangAST();
return parseAST(yangAST);
}
private static YangModelDependencyInfo parseModuleContext(
final Module_stmtContext module) {
- String name = getArgumentString(module);
- String latestRevision = getLatestRevision(module.revision_stmts());
- ImmutableSet<ModuleImport> imports = parseImports(module
+ final String name = getArgumentString(module);
+ final String latestRevision = getLatestRevision(module.revision_stmts());
+ final ImmutableSet<ModuleImport> imports = parseImports(module
.linkage_stmts().import_stmt());
- ImmutableSet<ModuleImport> includes = parseIncludes(module
+ final ImmutableSet<ModuleImport> includes = parseIncludes(module
.linkage_stmts().include_stmt());
return new ModuleDependencyInfo(name, latestRevision, imports, includes);
private static YangModelDependencyInfo parseModuleContext(
final YangStatementParser.StatementContext module) {
- String name = Utils.stringFromStringContext(module.argument());
- String latestRevision = getLatestRevision(module);
- ImmutableSet<ModuleImport> imports = parseImports(module);
- ImmutableSet<ModuleImport> includes = parseIncludes(module);
+ final String name = Utils.stringFromStringContext(module.argument());
+ final String latestRevision = getLatestRevision(module);
+ final Optional<SemVer> semVer = Optional.fromNullable(getSemanticVersion(module));
+ final ImmutableSet<ModuleImport> imports = parseImports(module);
+ final ImmutableSet<ModuleImport> includes = parseIncludes(module);
- return new ModuleDependencyInfo(name, latestRevision, imports, includes);
+ return new ModuleDependencyInfo(name, latestRevision, imports, includes, semVer);
}
private static ImmutableSet<ModuleImport> parseImports(
final YangStatementParser.StatementContext module) {
- Set<ModuleImport> result = new HashSet<>();
- List<StatementContext> subStatements = module.statement();
- for (StatementContext subStatementContext : subStatements) {
+ final Set<ModuleImport> result = new HashSet<>();
+ final List<StatementContext> subStatements = module.statement();
+ for (final StatementContext subStatementContext : subStatements) {
if (subStatementContext
.keyword()
.getText()
.equals(Rfc6020Mapping.IMPORT.getStatementName()
.getLocalName())) {
- String revisionDateStr = getRevisionDateString(subStatementContext);
- String importedModuleName = Utils
+ final String revisionDateStr = getRevisionDateString(subStatementContext);
+ final String importedModuleName = Utils
.stringFromStringContext(subStatementContext.argument());
- Date revisionDate = (revisionDateStr == null) ? null : QName
+ final Date revisionDate = (revisionDateStr == null) ? null : QName
.parseRevision(revisionDateStr);
+ final Optional<SemVer> importSemVer = Optional.fromNullable(getSemanticVersion(subStatementContext));
result.add(new ModuleImportImpl(importedModuleName,
- revisionDate));
+ revisionDate, importSemVer));
}
}
return ImmutableSet.copyOf(result);
}
+ private static SemVer getSemanticVersion(final StatementContext statement) {
+ final List<StatementContext> subStatements = statement.statement();
+ String semVerString = null;
+ final String semVerStmtName = SupportedExtensionsMapping.SEMANTIC_VERSION.getStatementName().getLocalName();
+ for (final StatementContext subStatement : subStatements) {
+ final String subStatementName = Utils.trimPrefix(subStatement.keyword().getText());
+ if (semVerStmtName.equals(subStatementName)) {
+ semVerString = Utils.stringFromStringContext(subStatement.argument());
+ break;
+ }
+ }
+
+ if (Strings.isNullOrEmpty(semVerString)) {
+ return null;
+ }
+
+ return SemVer.valueOf(semVerString);
+ }
+
private static ImmutableSet<ModuleImport> parseIncludes(
final YangStatementParser.StatementContext module) {
- Set<ModuleImport> result = new HashSet<>();
- List<StatementContext> subStatements = module.statement();
- for (StatementContext subStatementContext : subStatements) {
+ final Set<ModuleImport> result = new HashSet<>();
+ final List<StatementContext> subStatements = module.statement();
+ for (final StatementContext subStatementContext : subStatements) {
if (subStatementContext
.keyword()
.getText()
.equals(Rfc6020Mapping.INCLUDE.getStatementName()
.getLocalName())) {
- String revisionDateStr = getRevisionDateString(subStatementContext);
- String IncludeModuleName = Utils
+ final String revisionDateStr = getRevisionDateString(subStatementContext);
+ final String IncludeModuleName = Utils
.stringFromStringContext(subStatementContext.argument());
- Date revisionDate = (revisionDateStr == null) ? null : QName
+ final Date revisionDate = (revisionDateStr == null) ? null : QName
.parseRevision(revisionDateStr);
result.add(new ModuleImportImpl(IncludeModuleName, revisionDate));
}
return ImmutableSet.copyOf(result);
}
- private static String getRevisionDateString(StatementContext importStatement) {
- List<StatementContext> importSubStatements = importStatement
+ private static String getRevisionDateString(final StatementContext importStatement) {
+ final List<StatementContext> importSubStatements = importStatement
.statement();
String revisionDateStr = null;
- for (StatementContext importSubStatement : importSubStatements) {
+ for (final StatementContext importSubStatement : importSubStatements) {
if (importSubStatement
.keyword()
.getText()
private static ImmutableSet<ModuleImport> parseImports(
final List<Import_stmtContext> importStatements) {
- ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
- for (Import_stmtContext importStmt : importStatements) {
- String moduleName = getArgumentString(importStmt);
- Date revision = getRevision(importStmt.revision_date_stmt());
+ final ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
+ for (final Import_stmtContext importStmt : importStatements) {
+ final String moduleName = getArgumentString(importStmt);
+ final Date revision = getRevision(importStmt.revision_date_stmt());
builder.add(new ModuleImportImpl(moduleName, revision));
}
return builder.build();
public static String getLatestRevision(
final YangStatementParser.StatementContext module) {
- List<StatementContext> subStatements = module.statement();
+ final List<StatementContext> subStatements = module.statement();
String latestRevision = null;
- for (StatementContext subStatementContext : subStatements) {
+ for (final StatementContext subStatementContext : subStatements) {
if (subStatementContext
.keyword()
.getText()
.equals(Rfc6020Mapping.REVISION.getStatementName()
.getLocalName())) {
- String currentRevision = Utils
+ final String currentRevision = Utils
.stringFromStringContext(subStatementContext.argument());
if (latestRevision == null
|| latestRevision.compareTo(currentRevision) == -1) {
public static String getLatestRevision(
final Revision_stmtsContext revisionStmts) {
- List<Revision_stmtContext> revisions = revisionStmts
+ final List<Revision_stmtContext> revisions = revisionStmts
.getRuleContexts(Revision_stmtContext.class);
String latestRevision = null;
- for (Revision_stmtContext revisionStmt : revisions) {
- String currentRevision = getArgumentString(revisionStmt);
+ for (final Revision_stmtContext revisionStmt : revisions) {
+ final String currentRevision = getArgumentString(revisionStmt);
if (latestRevision == null
|| latestRevision.compareTo(currentRevision) == -1) {
latestRevision = currentRevision;
private static YangModelDependencyInfo parseSubmoduleContext(
final YangStatementParser.StatementContext submodule) {
- String name = Utils.stringFromStringContext(submodule.argument());
- String belongsTo = parseBelongsTo(submodule);
+ final String name = Utils.stringFromStringContext(submodule.argument());
+ final String belongsTo = parseBelongsTo(submodule);
- String latestRevision = getLatestRevision(submodule);
- ImmutableSet<ModuleImport> imports = parseImports(submodule);
- ImmutableSet<ModuleImport> includes = parseIncludes(submodule);
+ final String latestRevision = getLatestRevision(submodule);
+ final ImmutableSet<ModuleImport> imports = parseImports(submodule);
+ final ImmutableSet<ModuleImport> includes = parseIncludes(submodule);
return new SubmoduleDependencyInfo(name, latestRevision, belongsTo,
imports, includes);
}
- private static String parseBelongsTo(StatementContext submodule) {
- List<StatementContext> subStatements = submodule.statement();
- for (StatementContext subStatementContext : subStatements) {
+ private static String parseBelongsTo(final StatementContext submodule) {
+ final List<StatementContext> subStatements = submodule.statement();
+ for (final StatementContext subStatementContext : subStatements) {
if (subStatementContext
.keyword()
.getText()
private static YangModelDependencyInfo parseSubmoduleContext(
final Submodule_stmtContext submodule) {
- String name = getArgumentString(submodule);
- Belongs_to_stmtContext belongsToStmt = submodule
+ final String name = getArgumentString(submodule);
+ final Belongs_to_stmtContext belongsToStmt = submodule
.submodule_header_stmts().belongs_to_stmt(0);
- String belongsTo = getArgumentString(belongsToStmt);
+ final String belongsTo = getArgumentString(belongsToStmt);
- String latestRevision = getLatestRevision(submodule.revision_stmts());
- ImmutableSet<ModuleImport> imports = parseImports(submodule
+ final String latestRevision = getLatestRevision(submodule.revision_stmts());
+ final ImmutableSet<ModuleImport> imports = parseImports(submodule
.linkage_stmts().import_stmt());
- ImmutableSet<ModuleImport> includes = parseIncludes(submodule
+ final ImmutableSet<ModuleImport> includes = parseIncludes(submodule
.linkage_stmts().include_stmt());
return new SubmoduleDependencyInfo(name, latestRevision, belongsTo,
private static ImmutableSet<ModuleImport> parseIncludes(
final List<Include_stmtContext> importStatements) {
- ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
- for (Include_stmtContext importStmt : importStatements) {
- String moduleName = getArgumentString(importStmt);
- Date revision = getRevision(importStmt.revision_date_stmt());
+ final ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
+ for (final Include_stmtContext importStmt : importStatements) {
+ final String moduleName = getArgumentString(importStmt);
+ final Date revision = getRevision(importStmt.revision_date_stmt());
builder.add(new ModuleImportImpl(moduleName, revision));
}
return builder.build();
if (revisionDateStmt == null) {
return null;
}
- String formatedDate = getArgumentString(revisionDateStmt);
+ final String formatedDate = getArgumentString(revisionDateStmt);
return QName.parseRevision(formatedDate);
}
* Dependency information for YANG module.
*
*/
- public static final class ModuleDependencyInfo extends
+ public static class ModuleDependencyInfo extends
YangModelDependencyInfo {
private ModuleDependencyInfo(final String name,
super(name, latestRevision, imports, includes);
}
+ private ModuleDependencyInfo(final String name,
+ final String latestRevision,
+ final ImmutableSet<ModuleImport> imports,
+ final ImmutableSet<ModuleImport> includes,
+ final Optional<SemVer> semVer) {
+ super(name, latestRevision, imports, includes, semVer);
+ }
+
@Override
public String toString() {
- return "Module [name=" + getName() + ", revision=" + getRevision()
- + ", dependencies=" + getDependencies() + "]";
+ return "Module [name=" + getName() + ", revision=" + getRevision() + ", semanticVersion="
+ + getSemanticVersion().or(Module.DEFAULT_SEMANTIC_VERSION) + ", dependencies=" + getDependencies()
+ + "]";
}
}
private final String name;
public ModuleImportImpl(final String moduleName, final Date revision) {
- this(moduleName, revision, Module.DEFAULT_SEMANTIC_VERSION);
+ this(moduleName, revision, Optional.absent());
}
- public ModuleImportImpl(final String moduleName, final Date revision, final SemVer semVer) {
+ public ModuleImportImpl(final String moduleName, final Date revision, final Optional<SemVer> semVer) {
this.name = Preconditions.checkNotNull(moduleName, "Module name must not be null.");
this.revision = revision;
- this.semVer = Preconditions.checkNotNull(semVer, "Semantic version of module must not be null.");
+ this.semVer = semVer.or(Module.DEFAULT_SEMANTIC_VERSION);
}
@Override
if (getClass() != obj.getClass()) {
return false;
}
- ModuleImportImpl other = (ModuleImportImpl) obj;
+ final ModuleImportImpl other = (ModuleImportImpl) obj;
if (name == null) {
if (other.name != null) {
return false;
@Override
public String toString() {
return "ModuleImportImpl [name=" + name + ", revision="
- + QName.formattedRevision(revision) + "]";
+ + QName.formattedRevision(revision) + ", semanticVersion=" + getSemanticVersion() + "]";
}
}
}
package org.opendaylight.yangtools.yang.parser.repo;
import com.google.common.base.MoreObjects;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.opendaylight.yangtools.concepts.SemVer;
-import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ModuleImport;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
* That information will allow us to track "damage" to dependency resolution
* as new models are added to a schema context.
*/
-final class DependencyResolver {
+abstract class DependencyResolver {
private static final Logger LOG = LoggerFactory.getLogger(DependencyResolver.class);
private final Collection<SourceIdentifier> resolvedSources;
private final Collection<SourceIdentifier> unresolvedSources;
private final Multimap<SourceIdentifier, ModuleImport> unsatisfiedImports;
- public DependencyResolver(final Collection<SourceIdentifier> resolvedSources,
- final Collection<SourceIdentifier> unresolvedSources, final Multimap<SourceIdentifier, ModuleImport> unsatisfiedImports) {
- this.resolvedSources = Preconditions.checkNotNull(resolvedSources);
- this.unresolvedSources = Preconditions.checkNotNull(unresolvedSources);
- this.unsatisfiedImports = Preconditions.checkNotNull(unsatisfiedImports);
- }
-
- private static SourceIdentifier findWildcard(final Iterable<SourceIdentifier> haystack, final String needle) {
- for (final SourceIdentifier r : haystack) {
- if (r.getName().equals(needle)) {
- return r;
- }
- }
-
- return null;
- }
-
- private static boolean isKnown(final Collection<SourceIdentifier> haystack, final ModuleImport mi) {
- final String rev = mi.getRevision() != null ? QName.formattedRevision(mi.getRevision()) : null;
- final SourceIdentifier msi = SourceIdentifier.create(mi.getModuleName(), Optional.fromNullable(rev));
-
- // Quick lookup
- if (haystack.contains(msi)) {
- return true;
- }
-
- // Slow revision-less walk
- return rev == null && findWildcard(haystack, mi.getModuleName()) != null;
- }
-
-
-
- public static DependencyResolver create(final Map<SourceIdentifier, YangModelDependencyInfo> depInfo) {
+ protected DependencyResolver(final Map<SourceIdentifier, YangModelDependencyInfo> depInfo) {
final Collection<SourceIdentifier> resolved = new ArrayList<>(depInfo.size());
final Collection<SourceIdentifier> pending = new ArrayList<>(depInfo.keySet());
final Map<SourceIdentifier, BelongsToDependency> submodules = Maps.newHashMap();
}
}
- if (!pending.isEmpty()) {
- final Multimap<SourceIdentifier, ModuleImport> imports = ArrayListMultimap.create();
- for (final SourceIdentifier id : pending) {
- final YangModelDependencyInfo dep = depInfo.get(id);
- for (final ModuleImport mi : dep.getDependencies()) {
- if (!isKnown(pending, mi) && !isKnown(resolved, mi)) {
- imports.put(id, mi);
- }
+ final Multimap<SourceIdentifier, ModuleImport> imports = ArrayListMultimap.create();
+ for (final SourceIdentifier id : pending) {
+ final YangModelDependencyInfo dep = depInfo.get(id);
+ for (final ModuleImport mi : dep.getDependencies()) {
+ if (!isKnown(pending, mi) && !isKnown(resolved, mi)) {
+ imports.put(id, mi);
}
}
-
- return new DependencyResolver(resolved, pending, imports);
- } else {
- return new DependencyResolver(resolved, Collections.emptyList(), ImmutableMultimap.of());
}
+
+ this.resolvedSources = ImmutableList.copyOf(resolved);
+ this.unresolvedSources = ImmutableList.copyOf(pending);
+ this.unsatisfiedImports = ImmutableMultimap.copyOf(imports);
}
+ abstract protected boolean isKnown(final Collection<SourceIdentifier> haystack, final ModuleImport mi);
+
/**
* Collection of sources which have been resolved.
*
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.repo;
+
+import com.google.common.base.Optional;
+import java.util.Collection;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
+
+final class RevisionDependencyResolver extends DependencyResolver {
+
+ protected RevisionDependencyResolver(final Map<SourceIdentifier, YangModelDependencyInfo> depInfo) {
+ super(depInfo);
+ }
+
+ protected static SourceIdentifier findWildcard(final Iterable<SourceIdentifier> haystack, final String needle) {
+ for (final SourceIdentifier r : haystack) {
+ if (needle.equals(r.getName())) {
+ return r;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected boolean isKnown(final Collection<SourceIdentifier> haystack, final ModuleImport mi) {
+ final String rev = mi.getRevision() != null ? QName.formattedRevision(mi.getRevision()) : null;
+ final SourceIdentifier msi = SourceIdentifier.create(mi.getModuleName(), Optional.fromNullable(rev));
+
+ // Quick lookup
+ if (haystack.contains(msi)) {
+ return true;
+ }
+
+ // Slow revision-less walk
+ return rev == null && findWildcard(haystack, mi.getModuleName()) != null;
+ }
+
+ public static RevisionDependencyResolver create(final Map<SourceIdentifier, YangModelDependencyInfo> depInfo) {
+ return new RevisionDependencyResolver(depInfo);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.repo;
+
+import com.google.common.base.Optional;
+import java.util.Collection;
+import java.util.Map;
+import org.opendaylight.yangtools.concepts.SemVer;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
+
+final class SemVerDependencyResolver extends DependencyResolver {
+
+ protected SemVerDependencyResolver(final Map<SourceIdentifier, YangModelDependencyInfo> depInfo) {
+ super(depInfo);
+ }
+
+ protected static SourceIdentifier findCompatibleVersion(final Iterable<SourceIdentifier> haystack, final ModuleImport mi) {
+ final String requestedModuleName = mi.getModuleName();
+ for (SourceIdentifier r : haystack) {
+ if (requestedModuleName.equals(r.getName())
+ && isCompatible(((SemVerSourceIdentifier) r).getSemanticVersion(), mi.getSemanticVersion())) {
+ return r;
+ }
+ }
+
+ return null;
+ }
+
+ private static boolean isCompatible(final SemVer moduleSemVer, final SemVer importSemVer) {
+ return moduleSemVer.getMajor() == importSemVer.getMajor() && moduleSemVer.compareTo(importSemVer) >= 0;
+ }
+
+ @Override
+ protected boolean isKnown(final Collection<SourceIdentifier> haystack, final ModuleImport mi) {
+ final String rev = mi.getRevision() != null ? QName.formattedRevision(mi.getRevision()) : null;
+ final SemVerSourceIdentifier msi = SemVerSourceIdentifier.create(mi.getModuleName(), Optional.fromNullable(rev), mi.getSemanticVersion());
+
+ // Quick lookup
+ if (haystack.contains(msi)) {
+ return true;
+ }
+
+ // Slow revision-less walk
+ return findCompatibleVersion(haystack, mi) != null;
+ }
+
+ public static SemVerDependencyResolver create(final Map<SourceIdentifier, YangModelDependencyInfo> depInfo) {
+ return new SemVerDependencyResolver(depInfo);
+ }
+}
\ No newline at end of file
import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
}
};
private final Cache<Collection<SourceIdentifier>, SchemaContext> cache = CacheBuilder.newBuilder().weakValues().build();
+ private final Cache<Collection<SourceIdentifier>, SchemaContext> semVerCache = CacheBuilder.newBuilder().weakValues().build();
private final SharedSchemaRepository repository;
// FIXME: ignored right now
private final SchemaSourceFilter filter;
@Override
public CheckedFuture<SchemaContext, SchemaResolutionException> createSchemaContext(
- final Collection<SourceIdentifier> requiredSources, java.util.function.Predicate<QName> isFeatureSupported) {
+ final Collection<SourceIdentifier> requiredSources, final StatementParserMode statementParserMode,
+ final java.util.function.Predicate<QName> isFeatureSupported) {
+ return createSchemaContext(requiredSources,
+ statementParserMode == StatementParserMode.SEMVER_MODE ? this.semVerCache : this.cache,
+ new AssembleSources(isFeatureSupported, statementParserMode));
+ }
+
+ private CheckedFuture<SchemaContext, SchemaResolutionException> createSchemaContext(final Collection<SourceIdentifier> requiredSources, final Cache<Collection<SourceIdentifier>, SchemaContext> cache, final AsyncFunction<List<ASTSchemaSource>, SchemaContext> assembleSources) {
// Make sources unique
final List<SourceIdentifier> uniqueSourceIdentifiers = deDuplicateSources(requiredSources);
sf = Futures.transform(sf, new SourceIdMismatchDetector(uniqueSourceIdentifiers));
// Assemble sources into a schema context
- final AssembleSources assembleSources = new AssembleSources(isFeatureSupported);
final ListenableFuture<SchemaContext> cf = Futures.transform(sf, assembleSources);
// Populate cache when successful
private static final class AssembleSources implements AsyncFunction<List<ASTSchemaSource>, SchemaContext> {
private final java.util.function.Predicate<QName> isFeatureSupported;
+ private final StatementParserMode statementParserMode;
+ private final Function<ASTSchemaSource, SourceIdentifier> getIdentifier;
- private AssembleSources(final java.util.function.Predicate<QName> isFeatureSupported) {
+ private AssembleSources(final java.util.function.Predicate<QName> isFeatureSupported,
+ final StatementParserMode statementParserMode) {
this.isFeatureSupported = Preconditions.checkNotNull(isFeatureSupported);
+ this.statementParserMode = Preconditions.checkNotNull(statementParserMode);
+ switch (statementParserMode) {
+ case SEMVER_MODE:
+ this.getIdentifier = ASTSchemaSource.GET_SEMVER_IDENTIFIER;
+ break;
+ default:
+ this.getIdentifier = ASTSchemaSource.GET_IDENTIFIER;
+ }
}
@Override
- public ListenableFuture<SchemaContext> apply(List<ASTSchemaSource> sources) throws SchemaResolutionException,
+ public ListenableFuture<SchemaContext> apply(final List<ASTSchemaSource> sources) throws SchemaResolutionException,
SourceException, ReactorException {
- final Map<SourceIdentifier, ASTSchemaSource> srcs =
- Maps.uniqueIndex(sources, ASTSchemaSource.GET_IDENTIFIER);
+ final Map<SourceIdentifier, ASTSchemaSource> srcs = Maps.uniqueIndex(sources, getIdentifier);
final Map<SourceIdentifier, YangModelDependencyInfo> deps =
Maps.transformValues(srcs, ASTSchemaSource.GET_DEPINFO);
LOG.debug("Resolving dependency reactor {}", deps);
- final DependencyResolver res = DependencyResolver.create(deps);
+ final DependencyResolver res = this.statementParserMode == StatementParserMode.SEMVER_MODE ? SemVerDependencyResolver
+ .create(deps) : RevisionDependencyResolver.create(deps);
if (!res.getUnresolvedSources().isEmpty()) {
LOG.debug("Omitting models {} due to unsatisfied imports {}", res.getUnresolvedSources(), res.getUnsatisfiedImports());
throw new SchemaResolutionException("Failed to resolve required models",
final Map<SourceIdentifier, ParserRuleContext> asts = Maps.transformValues(srcs, ASTSchemaSource.GET_AST);
final CrossSourceStatementReactor.BuildAction reactor =
- YangInferencePipeline.RFC6020_REACTOR.newBuild(isFeatureSupported);
+ YangInferencePipeline.RFC6020_REACTOR.newBuild(statementParserMode, isFeatureSupported);
for (final Entry<SourceIdentifier, ParserRuleContext> e : asts.entrySet()) {
final ParserRuleContext parserRuleCtx = e.getValue();
reactor.addSource(new YangStatementSourceImpl(e.getKey(), (StatementContext) parserRuleCtx));
}
- SchemaContext schemaContext = reactor.buildEffective();
+ final SchemaContext schemaContext = reactor.buildEffective();
return Futures.immediateCheckedFuture(schemaContext);
}
package org.opendaylight.yangtools.yang.parser.repo;
import static com.google.common.base.Preconditions.checkArgument;
+
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs;
public YangTextSchemaSourceRegistration registerSource(@Nonnull final URL url) throws SchemaSourceException, IOException, YangSyntaxErrorException {
checkArgument(url != null, "Supplied URL must not be null");
- final SourceIdentifier guessedId = new SourceIdentifier(url.getFile(), Optional.absent());
+ final SourceIdentifier guessedId = RevisionSourceIdentifier.create(url.getFile(), Optional.absent());
return registerSource(new YangTextSchemaSource(guessedId) {
@Override
public InputStream openStream() throws IOException {
* new schema context was successfully built.
*/
public Optional<SchemaContext> getSchemaContext() {
+ return getSchemaContext(StatementParserMode.DEFAULT_MODE);
+ }
+
+ /**
+ * Try to parse all currently available yang files and build new schema context
+ * in dependence on specified parsing mode.
+ *
+ * @param statementParserMode mode of statement parser
+ * @return new schema context iif there is at least 1 yang file registered and
+ * new schema context was successfully built.
+ */
+ public Optional<SchemaContext> getSchemaContext(StatementParserMode statementParserMode) {
final SchemaContextFactory factory = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
Optional<SchemaContext> sc;
Object v;
} while (v != version);
while (true) {
- final CheckedFuture<SchemaContext, SchemaResolutionException> f = factory.createSchemaContext(sources);
+ final CheckedFuture<SchemaContext, SchemaResolutionException> f = factory.createSchemaContext(sources, statementParserMode);
try {
sc = Optional.of(f.checkedGet());
break;
private static final CharMatcher QUESTION_MARK_MATCHER = CharMatcher.is('?');
private static final Splitter SLASH_SPLITTER = Splitter.on('/').omitEmptyStrings().trimResults();
private static final Splitter SPACE_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
+ private static final Splitter COLON_SPLITTER = Splitter.on(":").omitEmptyStrings().trimResults();
private static final Pattern PATH_ABS = Pattern.compile("/[^/].*");
private static final Pattern BETWEEN_CURLY_BRACES_PATTERN = Pattern.compile("\\{(.+?)\\}");
private static final Set<String> JAVA_UNICODE_BLOCKS = ImmutableSet.<String>builder()
return identifier;
}
+ public static String trimPrefix(final String identifier) {
+ List<String> namesParts = COLON_SPLITTER.splitToList(identifier);
+ if (namesParts.size() == 2) {
+ return namesParts.get(1);
+ }
+ return identifier;
+ }
+
/**
*
* Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
import com.google.common.base.Preconditions;
import javax.annotation.Nonnull;
import org.antlr.v4.runtime.ParserRuleContext;
+import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
return input.getIdentifier();
}
};
+ public static final Function<ASTSchemaSource, SourceIdentifier> GET_SEMVER_IDENTIFIER = new Function<ASTSchemaSource, SourceIdentifier>() {
+ @Override
+ public SemVerSourceIdentifier apply(@Nonnull final ASTSchemaSource input) {
+ Preconditions.checkNotNull(input);
+ return input.getSemVerIdentifier();
+ }
+ };
public static final Function<ASTSchemaSource, YangModelDependencyInfo> GET_DEPINFO = new Function<ASTSchemaSource, YangModelDependencyInfo>() {
@Override
public YangModelDependencyInfo apply(@Nonnull final ASTSchemaSource input) {
private final YangModelDependencyInfo depInfo;
private final ParserRuleContext tree;
private final SourceIdentifier id;
+ private final SemVerSourceIdentifier semVerId;
private final String text;
- private ASTSchemaSource(@Nonnull final SourceIdentifier id, @Nonnull final ParserRuleContext tree, @Nonnull final YangModelDependencyInfo depInfo, final String text) {
+ private ASTSchemaSource(@Nonnull final SourceIdentifier id, @Nonnull final SemVerSourceIdentifier semVerId, @Nonnull final ParserRuleContext tree, @Nonnull final YangModelDependencyInfo depInfo, final String text) {
this.depInfo = Preconditions.checkNotNull(depInfo);
this.tree = Preconditions.checkNotNull(tree);
this.id = Preconditions.checkNotNull(id);
+ this.semVerId = Preconditions.checkNotNull(semVerId);
this.text = text;
}
public static ASTSchemaSource create(@Nonnull final String name, @Nonnull final ParserRuleContext tree) throws YangSyntaxErrorException {
final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(name, tree);
final SourceIdentifier id = getSourceId(depInfo);
- return new ASTSchemaSource(id, tree, depInfo, null);
+ final SemVerSourceIdentifier semVerId = getSemVerSourceId(depInfo);
+ return new ASTSchemaSource(id, semVerId, tree, depInfo, null);
}
private static SourceIdentifier getSourceId(final YangModelDependencyInfo depInfo) {
final String name = depInfo.getName();
return depInfo.getFormattedRevision() == null
- ? new SourceIdentifier(name)
- : new SourceIdentifier(name, depInfo.getFormattedRevision());
+ ? RevisionSourceIdentifier.create(name)
+ : RevisionSourceIdentifier.create(name, depInfo.getFormattedRevision());
+ }
+
+ private static SemVerSourceIdentifier getSemVerSourceId(final YangModelDependencyInfo depInfo) {
+ return depInfo.getFormattedRevision() == null ? SemVerSourceIdentifier.create(depInfo.getName(), depInfo
+ .getSemanticVersion().or(Module.DEFAULT_SEMANTIC_VERSION)) : SemVerSourceIdentifier.create(
+ depInfo.getName(), depInfo.getFormattedRevision(),
+ depInfo.getSemanticVersion().or(Module.DEFAULT_SEMANTIC_VERSION));
}
/**
public static ASTSchemaSource create(@Nonnull final String name, @Nonnull final ParserRuleContext tree, final String text) throws YangSyntaxErrorException {
final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(name, tree);
final SourceIdentifier id = getSourceId(depInfo);
- return new ASTSchemaSource(id, tree, depInfo, text);
+ final SemVerSourceIdentifier semVerId = getSemVerSourceId(depInfo);
+ return new ASTSchemaSource(id, semVerId, tree, depInfo, text);
}
+ /**
+ * Create a new instance of AST representation for a abstract syntax tree,
+ * performing minimal semantic analysis to acquire dependency information.
+ *
+ * @param identifier
+ * SourceIdentifier of yang schema source.
+ * @param tree
+ * ANTLR abstract syntax tree
+ * @param text
+ * YANG text source
+ * @return A new representation instance.
+ * @throws YangSyntaxErrorException
+ * if we fail to extract dependency information.
+ *
+ */
+ public static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier,
+ @Nonnull final ParserRuleContext tree, final String text) throws YangSyntaxErrorException {
+ final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(identifier.getName(), tree);
+ final SourceIdentifier id = getSourceId(depInfo);
+
+ final SemVerSourceIdentifier semVerId;
+ if (identifier instanceof SemVerSourceIdentifier && !depInfo.getSemanticVersion().isPresent()) {
+ semVerId = (SemVerSourceIdentifier) identifier;
+ } else {
+ semVerId = getSemVerSourceId(depInfo);
+ }
+
+ return new ASTSchemaSource(id, semVerId, tree, depInfo, text);
+ }
@Override
public SourceIdentifier getIdentifier() {
return id;
}
+ public SemVerSourceIdentifier getSemVerIdentifier() {
+ return semVerId;
+ }
+
@Override
public Class<? extends SchemaSourceRepresentation> getType() {
return ASTSchemaSource.class;
package org.opendaylight.yangtools.yang.parser.util;
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
import com.google.common.annotations.Beta;
import com.google.common.base.Charsets;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import java.io.IOException;
import java.io.InputStream;
+import org.antlr.v4.runtime.ParserRuleContext;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
import org.opendaylight.yangtools.yang.model.repo.util.SchemaSourceTransformer;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// Backwards compatibility
final String text = input.asCharSource(Charsets.UTF_8).read();
- return Futures.immediateCheckedFuture(ASTSchemaSource.create(input.getIdentifier().getName(), ctx, text));
+ return Futures.immediateCheckedFuture(ASTSchemaSource.create(input.getIdentifier(), ctx, text));
}
}
}
package org.opendaylight.yangtools.yang.parser.repo;
import static org.junit.Assert.assertEquals;
+
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+
import com.google.common.base.Optional;
import java.util.HashMap;
import java.util.Map;
addToMap(map, YangModelDependencyInfo.ModuleDependencyInfo.fromInputStream(getClass().getResourceAsStream("/no-revision/imported@2012-12-12.yang")));
addToMap(map, YangModelDependencyInfo.ModuleDependencyInfo.fromInputStream(getClass().getResourceAsStream("/no-revision/top@2012-10-10.yang")));
- final DependencyResolver resolved = DependencyResolver.create(map);
+ final DependencyResolver resolved = RevisionDependencyResolver.create(map);
assertEquals(0, resolved.getUnresolvedSources().size());
assertEquals(0, resolved.getUnsatisfiedImports().size());
addToMap(map, YangModelDependencyInfo.ModuleDependencyInfo.fromInputStream(getClass().getResourceAsStream("/model/bar.yang")));
addToMap(map, YangModelDependencyInfo.ModuleDependencyInfo.fromInputStream(getClass().getResourceAsStream("/model/baz.yang")));
- final DependencyResolver resolved = DependencyResolver.create(map);
+ final DependencyResolver resolved = RevisionDependencyResolver.create(map);
assertEquals(2, resolved.getResolvedSources().size());
assertEquals(1, resolved.getUnresolvedSources().size());
addToMap(map, YangModelDependencyInfo.ModuleDependencyInfo.fromInputStream(getClass().getResourceAsStream("/model/bar.yang")));
addToMap(map, YangModelDependencyInfo.ModuleDependencyInfo.fromInputStream(getClass().getResourceAsStream("/model/baz.yang")));
- final DependencyResolver resolved = DependencyResolver.create(map);
+ final DependencyResolver resolved = RevisionDependencyResolver.create(map);
assertEquals(4, resolved.getResolvedSources().size());
assertEquals(0, resolved.getUnresolvedSources().size());
private static SourceIdentifier getSourceId(final YangModelDependencyInfo depInfo) {
final String name = depInfo.getName();
- return new SourceIdentifier(name, Optional.fromNullable(depInfo.getFormattedRevision()));
+ return RevisionSourceIdentifier.create(name, Optional.fromNullable(depInfo.getFormattedRevision()));
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yangtools.yang.parser.repo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
+import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
+import org.opendaylight.yangtools.yang.parser.util.ASTSchemaSource;
+import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
+
+public class SemVerSharedSchemaRepositoryTest {
+
+ @Test
+ public void testSemVerSharedSchemaRepository() throws Exception {
+ final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
+ "sem-ver-shared-schema-repo-test");
+
+ final SettableSchemaProvider<ASTSchemaSource> bar = getImmediateYangSourceProviderFromResource("/semantic-version/semver-shared-schema-repository/bar@2016-01-01.yang");
+ bar.register(sharedSchemaRepository);
+ bar.setResult();
+ final SettableSchemaProvider<ASTSchemaSource> foo = getImmediateYangSourceProviderFromResource("/semantic-version/semver-shared-schema-repository/foo.yang");
+ foo.register(sharedSchemaRepository);
+ foo.setResult();
+ final SettableSchemaProvider<ASTSchemaSource> semVer = getImmediateYangSourceProviderFromResource("/semantic-version/semver-shared-schema-repository/semantic-version.yang");
+ semVer.register(sharedSchemaRepository);
+ semVer.setResult();
+
+ final SchemaContextFactory fact = sharedSchemaRepository
+ .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
+
+ final CheckedFuture<SchemaContext, SchemaResolutionException> inetAndTopologySchemaContextFuture = fact
+ .createSchemaContext(Lists.newArrayList(bar.getId(), foo.getId(), semVer.getId()), StatementParserMode.SEMVER_MODE);
+ assertTrue(inetAndTopologySchemaContextFuture.isDone());
+ assertSchemaContext(inetAndTopologySchemaContextFuture.checkedGet(), 3);
+
+ final CheckedFuture<SchemaContext, SchemaResolutionException> barSchemaContextFuture = fact
+ .createSchemaContext(Lists.newArrayList(bar.getId(), semVer.getId()), StatementParserMode.SEMVER_MODE);
+ assertTrue(barSchemaContextFuture.isDone());
+ assertSchemaContext(barSchemaContextFuture.checkedGet(), 2);
+ }
+
+ @Test
+ public void testSharedSchemaRepository() throws Exception {
+ final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository("shared-schema-repo-test");
+
+ final SettableSchemaProvider<ASTSchemaSource> bar = getImmediateYangSourceProviderFromResource("/semantic-version/shared-schema-repository/bar@2016-01-01.yang");
+ bar.register(sharedSchemaRepository);
+ bar.setResult();
+ final SettableSchemaProvider<ASTSchemaSource> foo = getImmediateYangSourceProviderFromResource("/semantic-version/shared-schema-repository/foo.yang");
+ foo.register(sharedSchemaRepository);
+ foo.setResult();
+ final SettableSchemaProvider<ASTSchemaSource> semVer = getImmediateYangSourceProviderFromResource("/semantic-version/shared-schema-repository/semantic-version.yang");
+ semVer.register(sharedSchemaRepository);
+ semVer.setResult();
+
+ final SchemaContextFactory fact = sharedSchemaRepository
+ .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
+
+ final CheckedFuture<SchemaContext, SchemaResolutionException> inetAndTopologySchemaContextFuture = fact
+ .createSchemaContext(Lists.newArrayList(bar.getId(), foo.getId(), semVer.getId()));
+ assertTrue(inetAndTopologySchemaContextFuture.isDone());
+ assertSchemaContext(inetAndTopologySchemaContextFuture.checkedGet(), 3);
+
+ final CheckedFuture<SchemaContext, SchemaResolutionException> barSchemaContextFuture = fact
+ .createSchemaContext(Lists.newArrayList(bar.getId(), semVer.getId()));
+ assertTrue(barSchemaContextFuture.isDone());
+ assertSchemaContext(barSchemaContextFuture.checkedGet(), 2);
+ }
+
+ private static void assertSchemaContext(final SchemaContext schemaContext, final int moduleSize) {
+ assertNotNull(schemaContext);
+ assertEquals(moduleSize, schemaContext.getModules().size());
+ }
+
+ static SettableSchemaProvider<ASTSchemaSource> getImmediateYangSourceProviderFromResource(final String resourceName)
+ throws Exception {
+ final ResourceYangSource yangSource = new ResourceYangSource(resourceName);
+ final CheckedFuture<ASTSchemaSource, SchemaSourceException> aSTSchemaSource = TextToASTTransformer.TRANSFORMATION
+ .apply(yangSource);
+ return SettableSchemaProvider.createImmediate(aSTSchemaSource.get(), ASTSchemaSource.class);
+ }
+}
import static org.junit.Assert.assertNotNull;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
final ResourceYangSource source1 = new ResourceYangSource("/ietf/ietf-inet-types@2010-09-24.yang");
final ResourceYangSource source2 = new ResourceYangSource("/ietf/iana-timezones@2012-07-09.yang");
- s1 = new SourceIdentifier("ietf-inet-types", "2010-09-24");
- s2 = new SourceIdentifier("iana-timezones", "2012-07-09");
+ s1 = RevisionSourceIdentifier.create("ietf-inet-types", "2010-09-24");
+ s2 = RevisionSourceIdentifier.create("iana-timezones", "2012-07-09");
final TextToASTTransformer transformer = TextToASTTransformer.create(repository, repository);
repository.registerSchemaSourceListener(transformer);
provider.register(repository);
// Register the same provider under source id without revision
- final SourceIdentifier sIdWithoutRevision = new SourceIdentifier(provider.getId().getName());
+ final SourceIdentifier sIdWithoutRevision = RevisionSourceIdentifier.create(provider.getId().getName());
repository.registerSchemaSource(provider, PotentialSchemaSource.create(
sIdWithoutRevision, ASTSchemaSource.class, PotentialSchemaSource.Costs.IMMEDIATE.getValue()));
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
}
};
assertThat(Collections2.transform(listener.registeredSources, potSourceToSID),
- both(hasItem(new SourceIdentifier("test", Optional.absent())))
- .and(hasItem(new SourceIdentifier("test", Optional.of("2012-12-12"))))
- .and(hasItem(new SourceIdentifier("test", Optional.of("2013-12-12"))))
- .and(hasItem(new SourceIdentifier("module", Optional.of("2010-12-12"))))
+ both(hasItem(RevisionSourceIdentifier.create("test", Optional.absent())))
+ .and(hasItem(RevisionSourceIdentifier.create("test", Optional.of("2012-12-12"))))
+ .and(hasItem(RevisionSourceIdentifier.create("test", Optional.of("2013-12-12"))))
+ .and(hasItem(RevisionSourceIdentifier.create("module", Optional.of("2010-12-12"))))
);
}
final FilesystemSchemaSourceCache<YangTextSchemaSource> cache = new FilesystemSchemaSourceCache<>(sharedSchemaRepository, YangTextSchemaSource.class, storageDir);
sharedSchemaRepository.registerSchemaSourceListener(cache);
- final SourceIdentifier runningId = new SourceIdentifier("running", Optional.of("2012-12-12"));
+ final SourceIdentifier runningId = RevisionSourceIdentifier.create("running", Optional.of("2012-12-12"));
sharedSchemaRepository.registerSchemaSource(new SchemaSourceProvider<YangTextSchemaSource>() {
@Override
--- /dev/null
+module bar {
+ namespace "bar";
+ prefix bar;
+ yang-version 1;
+
+ import semantic-version { prefix sv; revision-date 2016-02-02; sv:semantic-version "0.0.1"; }
+
+ revision "2016-01-01" {
+ description "Initial version";
+ }
+ sv:semantic-version "0.1.2";
+
+ container root {
+ }
+}
--- /dev/null
+module foo {
+ namespace "foo";
+ prefix foo;
+ yang-version 1;
+
+ import semantic-version { prefix sv; revision-date 2016-02-02; sv:semantic-version "0.0.1"; }
+ import bar { prefix bar; revision-date 2016-01-31; sv:semantic-version "0.1.2";}
+
+ revision "2016-02-01" {
+ description "Initial version";
+ }
+ sv:semantic-version "0.1.1";
+
+ container root {
+ }
+}
--- /dev/null
+module semantic-version {
+ namespace "urn:opendaylight:yang:extension:semantic-version";
+ prefix sv;
+ yang-version 1;
+
+ revision 2016-02-02 {
+ description "Initial verison";
+ }
+ sv:semantic-version "0.0.1";
+
+ extension semantic-version {
+ argument "semantic-version" {
+ yin-element false;
+ }
+ description
+ "The OpenConfig version number for the module. This is
+ expressed as a semantic version number of the form:
+ x.y.z
+ where:
+ * x corresponds to the major version,
+ * y corresponds to a minor version,
+ * z corresponds to a patch version.
+ This version corresponds to the model file within which it is
+ defined, and does not cover the whole set of OpenConfig models.
+ Where several modules are used to build up a single block of
+ functionality, the same module version is specified across each
+ file that makes up the module.
+
+ A major version number of 0 indicates that this model is still
+ in development (whether within OpenConfig or with industry
+ partners), and is potentially subject to change.
+
+ Following a release of major version 1, all modules will
+ increment major revision number where backwards incompatible
+ changes to the model are made.
+
+ The minor version is changed when features are added to the
+ model that do not impact current clients use of the model.
+
+ The patch-level version is incremented when non-feature changes
+ (such as bugfixes or clarifications to human-readable
+ descriptions that do not impact model functionality) are made
+ that maintain backwards compatibility.
+
+ The version number is stored in the module meta-data.";
+ }
+}
--- /dev/null
+module bar {
+ namespace "bar";
+ prefix bar;
+ yang-version 1;
+
+ import semantic-version { prefix sv; revision-date 2016-02-02; sv:semantic-version "0.0.1"; }
+
+ revision "2016-01-01" {
+ description "Initial version";
+ }
+ sv:semantic-version "0.1.2";
+
+ container root {
+ }
+}
--- /dev/null
+module foo {
+ namespace "foo";
+ prefix foo;
+ yang-version 1;
+
+ import semantic-version { prefix sv; revision-date 2016-02-02; sv:semantic-version "0.0.1"; }
+ import bar { prefix bar; revision-date 2016-01-01; sv:semantic-version "0.1.2";}
+
+ revision "2016-02-01" {
+ description "Initial version";
+ }
+ sv:semantic-version "0.1.1";
+
+ container root {
+ }
+}
--- /dev/null
+module semantic-version {
+ namespace "urn:opendaylight:yang:extension:semantic-version";
+ prefix sv;
+ yang-version 1;
+
+ revision 2016-02-02 {
+ description "Initial verison";
+ }
+ sv:semantic-version "0.0.1";
+
+ extension semantic-version {
+ argument "semantic-version" {
+ yin-element false;
+ }
+ description
+ "The OpenConfig version number for the module. This is
+ expressed as a semantic version number of the form:
+ x.y.z
+ where:
+ * x corresponds to the major version,
+ * y corresponds to a minor version,
+ * z corresponds to a patch version.
+ This version corresponds to the model file within which it is
+ defined, and does not cover the whole set of OpenConfig models.
+ Where several modules are used to build up a single block of
+ functionality, the same module version is specified across each
+ file that makes up the module.
+
+ A major version number of 0 indicates that this model is still
+ in development (whether within OpenConfig or with industry
+ partners), and is potentially subject to change.
+
+ Following a release of major version 1, all modules will
+ increment major revision number where backwards incompatible
+ changes to the model are made.
+
+ The minor version is changed when features are added to the
+ model that do not impact current clients use of the model.
+
+ The patch-level version is incremented when non-feature changes
+ (such as bugfixes or clarifications to human-readable
+ descriptions that do not impact model functionality) are made
+ that maintain backwards compatibility.
+
+ The version number is stored in the module meta-data.";
+ }
+}