* with an explanation why the creation of the schema context
* failed.
*/
- default ListenableFuture<SchemaContext> createSchemaContext(
- @Nonnull final Collection<SourceIdentifier> requiredSources) {
- return createSchemaContext(requiredSources, StatementParserMode.DEFAULT_MODE);
- }
+ ListenableFuture<SchemaContext> createSchemaContext(@Nonnull Collection<SourceIdentifier> requiredSources);
/**
* Create a new schema context containing specified sources, pulling in any
* @return A checked future, which will produce a schema context, or fail
* with an explanation why the creation of the schema context
* failed.
+ * @deprecated Use SchemaContextFactoryConfiguration instead.
*/
- default ListenableFuture<SchemaContext> createSchemaContext(
- final Collection<SourceIdentifier> requiredSources, final StatementParserMode statementParserMode) {
+ @Deprecated
+ default ListenableFuture<SchemaContext> createSchemaContext(final Collection<SourceIdentifier> requiredSources,
+ final StatementParserMode statementParserMode) {
return createSchemaContext(requiredSources, statementParserMode, null);
}
* @param requiredSources
* a collection of sources which are required to be present
* @param supportedFeatures
- * set of supported features based on which all if-feature statements in the
- * parsed yang models are resolved
+ * set of supported features 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.
+ * @deprecated Use SchemaContextFactoryConfiguration instead.
*/
+ @Deprecated
default ListenableFuture<SchemaContext> createSchemaContext(
@Nonnull final Collection<SourceIdentifier> requiredSources, final Set<QName> supportedFeatures) {
return createSchemaContext(requiredSources, StatementParserMode.DEFAULT_MODE, supportedFeatures);
* @param statementParserMode
* mode of statement parser
* @param supportedFeatures
- * set of supported features based on which all if-feature statements in the
- * parsed yang models are resolved
+ * set of supported features 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.
+ * @deprecated Use SchemaContextFactoryConfiguration instead.
*/
+ @Deprecated
ListenableFuture<SchemaContext> createSchemaContext(Collection<SourceIdentifier> requiredSources,
StatementParserMode statementParserMode, Set<QName> supportedFeatures);
}
--- /dev/null
+/*
+ * Copyright (c) 2017 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 static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+
+/**
+ * SchemaContextFactory configuration class.
+ *
+ * <p>
+ * SchemaContextFactoryConfiguration supports currently the following options to
+ * be set:
+ * <ul>
+ * <li>schema source filter</li>
+ * <li>statement parser mode</li>
+ * <li>supported features</li>
+ * <li>supported deviations</li>
+ * </ul>
+ */
+@Beta
+public final class SchemaContextFactoryConfiguration implements Immutable {
+ private static final SchemaContextFactoryConfiguration DEFAULT_CONFIGURATION = new Builder().build();
+
+ private final SchemaSourceFilter filter;
+ private final StatementParserMode statementParserMode;
+ private final Set<QName> supportedFeatures;
+ private final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules;
+
+ private SchemaContextFactoryConfiguration(final SchemaSourceFilter filter,
+ final StatementParserMode statementParserMode, final Set<QName> supportedFeatures,
+ final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
+ this.filter = requireNonNull(filter);
+ this.statementParserMode = requireNonNull(statementParserMode);
+ this.supportedFeatures = supportedFeatures;
+ this.modulesDeviatedByModules = modulesDeviatedByModules;
+ }
+
+ public SchemaSourceFilter getSchemaSourceFilter() {
+ return filter;
+ }
+
+ public StatementParserMode getStatementParserMode() {
+ return statementParserMode;
+ }
+
+ public Optional<Set<QName>> getSupportedFeatures() {
+ return Optional.ofNullable(supportedFeatures);
+ }
+
+ public Optional<SetMultimap<QNameModule, QNameModule>> getModulesDeviatedByModules() {
+ return Optional.ofNullable(modulesDeviatedByModules);
+ }
+
+ public static SchemaContextFactoryConfiguration getDefault() {
+ return DEFAULT_CONFIGURATION;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(filter, statementParserMode, supportedFeatures, modulesDeviatedByModules);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SchemaContextFactoryConfiguration)) {
+ return false;
+ }
+ final SchemaContextFactoryConfiguration other = (SchemaContextFactoryConfiguration) obj;
+ return filter.equals(other.filter) && statementParserMode.equals(other.statementParserMode)
+ && Objects.equals(supportedFeatures, other.supportedFeatures)
+ && Objects.equals(modulesDeviatedByModules, other.modulesDeviatedByModules);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).omitNullValues().add("schemaSourceFilter", filter)
+ .add("statementParserMode", statementParserMode).add("supportedFeatures", supportedFeatures)
+ .add("modulesDeviatedByModules", modulesDeviatedByModules).toString();
+ }
+
+ public static class Builder
+ implements org.opendaylight.yangtools.concepts.Builder<SchemaContextFactoryConfiguration> {
+ private SchemaSourceFilter filter = SchemaSourceFilter.ALWAYS_ACCEPT;
+ private StatementParserMode statementParserMode = StatementParserMode.DEFAULT_MODE;
+ private SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules;
+ private Set<QName> supportedFeatures;
+
+ /**
+ * Set schema source filter which will filter available schema sources
+ * using the provided filter.
+ *
+ * @param filter
+ * schema source filter which acts as the gating function
+ * before a schema source is considered by the factory for
+ * inclusion in the SchemaContext it produces.
+ * @return this builder
+ */
+ public Builder setFilter(@Nonnull final SchemaSourceFilter filter) {
+ this.filter = requireNonNull(filter);
+ return this;
+ }
+
+ /**
+ * Set yang statement parser mode.
+ *
+ * @param statementParserMode
+ * mode of yang statement parser
+ * @return this builder
+ */
+ public Builder setStatementParserMode(@Nonnull final StatementParserMode statementParserMode) {
+ this.statementParserMode = requireNonNull(statementParserMode);
+ return this;
+ }
+
+ /**
+ * Set supported features based on which all if-feature statements in
+ * the parsed YANG modules will be resolved.
+ *
+ * @param supportedFeatures
+ * Set of supported features in the final SchemaContext. If
+ * the set is empty, no features encountered will be
+ * supported.
+ * @return this builder
+ */
+ public Builder setSupportedFeatures(final Set<QName> supportedFeatures) {
+ this.supportedFeatures = supportedFeatures != null ? ImmutableSet.copyOf(supportedFeatures) : null;
+ return this;
+ }
+
+ /**
+ * Set YANG modules which can be deviated by specified modules during
+ * the parsing process. Map key (QNameModule) denotes a module which can
+ * be deviated by the modules in the Map value.
+ *
+ * @param modulesDeviatedByModules
+ * Map of YANG modules (Map key) which can be deviated by
+ * specified modules (Map values) in the final SchemaContext.
+ * If the map is empty, no deviations encountered will be
+ * supported. If the map is null, all deviations will be applied.
+ * @return this builder
+ */
+ public Builder setModulesDeviatedByModules(
+ final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
+ this.modulesDeviatedByModules = modulesDeviatedByModules != null
+ ? ImmutableSetMultimap.copyOf(modulesDeviatedByModules) : null;
+ return this;
+ }
+
+ @Override
+ public SchemaContextFactoryConfiguration build() {
+ return new SchemaContextFactoryConfiguration(filter, statementParserMode, supportedFeatures,
+ modulesDeviatedByModules);
+ }
+ }
+}
\ No newline at end of file
@Beta
public interface SchemaRepository {
/**
- * Instantiate a new {@link SchemaContextFactory}, which will filter available schema
- * sources using the provided filter.
+ * Instantiate a new {@link SchemaContextFactory}, which will filter
+ * available schema sources using the provided filter.
*
- * @param filter Filter which acts as the gating function before a schema source is
- * considered by the factory for inclusion in the {@link SchemaContext}
- * it produces.
+ * @param filter
+ * Filter which acts as the gating function before a schema
+ * source is considered by the factory for inclusion in the
+ * {@link SchemaContext} it produces.
* @return A new schema context factory.
+ * @deprecated Use
+ * {@link #createSchemaContextFactory(SchemaContextFactoryConfiguration)}
+ * instead.
*/
+ @Deprecated
SchemaContextFactory createSchemaContextFactory(@Nonnull SchemaSourceFilter filter);
+ /**
+ * Returns {@link SchemaContextFactory} with supplied configuration.
+ *
+ * @param config
+ * configuration of schema context factory.
+ * @return schema context factory.
+ */
+ SchemaContextFactory createSchemaContextFactory(@Nonnull SchemaContextFactoryConfiguration config);
+
<T extends SchemaSourceRepresentation> ListenableFuture<T> getSchemaSource(@Nonnull SourceIdentifier id,
@Nonnull Class<T> represetation);
}
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
}
private class Provider extends AbstractSchemaRepository {
-
+ @Deprecated
@Override
public SchemaContextFactory createSchemaContextFactory(@Nonnull final SchemaSourceFilter filter) {
return null;
}
+ @Override
+ public SchemaContextFactory createSchemaContextFactory(
+ @Nonnull final SchemaContextFactoryConfiguration config) {
+ return null;
+ }
+
}
private class Consumer extends AbstractSchemaRepository {
-
+ @Deprecated
@Override
public SchemaContextFactory createSchemaContextFactory(@Nonnull final SchemaSourceFilter filter) {
return null;
}
+ @Override
+ public SchemaContextFactory createSchemaContextFactory(
+ @Nonnull final SchemaContextFactoryConfiguration config) {
+ return null;
+ }
}
}
package org.opendaylight.yangtools.yang.model.parser.api;
import com.google.common.annotations.Beta;
+import com.google.common.collect.SetMultimap;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
* SchemaContext. If the map is empty, no deviations encountered will be supported.
*/
YangParser setModulesWithSupportedDeviations(
- @Nonnull Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules);
+ @Nonnull SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules);
/**
* Build the declared view of a combined view of declared statements.
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.SetMultimap;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import javax.xml.transform.TransformerException;
import org.opendaylight.yangtools.yang.common.QName;
@Override
public YangParser setModulesWithSupportedDeviations(
- final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules) {
+ final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
buildAction.setModulesWithSupportedDeviations(modulesDeviatedByModules);
return this;
}
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Optional;
import java.util.Set;
import javax.annotation.Nonnull;
import org.antlr.v4.runtime.ParserRuleContext;
import org.opendaylight.yangtools.yang.common.QName;
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.SchemaContextFactoryConfiguration;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
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;
.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;
+ private final SchemaRepository repository;
+ private final SchemaContextFactoryConfiguration config;
// FIXME SchemaRepository should be the type for repository parameter instead of SharedSchemaRepository
// (final implementation)
+ @Deprecated
SharedSchemaContextFactory(final SharedSchemaRepository repository, final SchemaSourceFilter filter) {
this.repository = Preconditions.checkNotNull(repository);
- this.filter = Preconditions.checkNotNull(filter);
+ this.config = SchemaContextFactoryConfiguration.builder().setFilter(filter).build();
+ }
+
+ SharedSchemaContextFactory(final SchemaRepository repository, final SchemaContextFactoryConfiguration config) {
+ this.repository = Preconditions.checkNotNull(repository);
+ this.config = Preconditions.checkNotNull(config);
}
@Override
+ @Deprecated
public ListenableFuture<SchemaContext> createSchemaContext(final Collection<SourceIdentifier> requiredSources,
final StatementParserMode statementParserMode, final Set<QName> supportedFeatures) {
return createSchemaContext(requiredSources,
- statementParserMode == StatementParserMode.SEMVER_MODE ? this.semVerCache : this.revisionCache,
- new AssembleSources(Optional.ofNullable(supportedFeatures), statementParserMode));
+ statementParserMode == StatementParserMode.SEMVER_MODE ? semVerCache : revisionCache,
+ new AssembleSources(SchemaContextFactoryConfiguration.builder()
+ .setFilter(config.getSchemaSourceFilter()).setStatementParserMode(statementParserMode)
+ .setSupportedFeatures(supportedFeatures).build()));
+ }
+
+ @Override
+ public ListenableFuture<SchemaContext> createSchemaContext(final Collection<SourceIdentifier> requiredSources) {
+ return createSchemaContext(requiredSources,
+ config.getStatementParserMode() == StatementParserMode.SEMVER_MODE ? semVerCache : revisionCache,
+ new AssembleSources(config));
}
private ListenableFuture<SchemaContext> createSchemaContext(final Collection<SourceIdentifier> requiredSources,
private static final class AssembleSources implements AsyncFunction<List<ASTSchemaSource>, SchemaContext> {
- private final Optional<Set<QName>> supportedFeatures;
- private final StatementParserMode statementParserMode;
+ private final SchemaContextFactoryConfiguration config;
private final Function<ASTSchemaSource, SourceIdentifier> getIdentifier;
- private AssembleSources(final Optional<Set<QName>> supportedFeatures,
- final StatementParserMode statementParserMode) {
- this.supportedFeatures = supportedFeatures;
- this.statementParserMode = Preconditions.checkNotNull(statementParserMode);
- switch (statementParserMode) {
+ private AssembleSources(@Nonnull final SchemaContextFactoryConfiguration config) {
+ this.config = config;
+ switch (config.getStatementParserMode()) {
case SEMVER_MODE:
this.getIdentifier = ASTSchemaSource::getSemVerIdentifier;
break;
LOG.debug("Resolving dependency reactor {}", deps);
- final DependencyResolver res = this.statementParserMode == StatementParserMode.SEMVER_MODE
+ final StatementParserMode statementParserMode = config.getStatementParserMode();
+ final DependencyResolver res = statementParserMode == StatementParserMode.SEMVER_MODE
? SemVerDependencyResolver.create(deps) : RevisionDependencyResolver.create(deps);
if (!res.getUnresolvedSources().isEmpty()) {
LOG.debug("Omitting models {} due to unsatisfied imports {}", res.getUnresolvedSources(),
}
final BuildAction reactor = DefaultReactors.defaultReactor().newBuild(statementParserMode);
- if (supportedFeatures.isPresent()) {
- reactor.setSupportedFeatures(supportedFeatures.get());
- }
+ config.getSupportedFeatures().ifPresent(reactor::setSupportedFeatures);
+ config.getModulesDeviatedByModules().ifPresent(reactor::setModulesWithSupportedDeviations);
for (final Entry<SourceIdentifier, ASTSchemaSource> e : srcs.entrySet()) {
final ASTSchemaSource ast = e.getValue();
import org.opendaylight.yangtools.concepts.Identifiable;
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.SchemaContextFactoryConfiguration;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
@Beta
@MetaInfServices(value = SchemaRepository.class)
public final class SharedSchemaRepository extends AbstractSchemaRepository implements Identifiable<String> {
- private final LoadingCache<SchemaSourceFilter, SchemaContextFactory> cache =
- CacheBuilder.newBuilder().softValues().build(new CacheLoader<SchemaSourceFilter, SchemaContextFactory>() {
+ @Deprecated
+ private final LoadingCache<SchemaSourceFilter, SchemaContextFactory> cacheByFilter = CacheBuilder.newBuilder()
+ .softValues().build(new CacheLoader<SchemaSourceFilter, SchemaContextFactory>() {
@Override
public SchemaContextFactory load(@Nonnull final SchemaSourceFilter key) {
return new SharedSchemaContextFactory(SharedSchemaRepository.this, key);
}
});
+
+ private final LoadingCache<SchemaContextFactoryConfiguration, SchemaContextFactory> cacheByConfig = CacheBuilder
+ .newBuilder().softValues()
+ .build(new CacheLoader<SchemaContextFactoryConfiguration, SchemaContextFactory>() {
+ @Override
+ public SchemaContextFactory load(@Nonnull final SchemaContextFactoryConfiguration key) {
+ return new SharedSchemaContextFactory(SharedSchemaRepository.this, key);
+ }
+ });
+
private final String id;
public SharedSchemaRepository(final String id) {
}
@Override
+ @Deprecated
public SchemaContextFactory createSchemaContextFactory(@Nonnull final SchemaSourceFilter filter) {
- return cache.getUnchecked(filter);
+ return cacheByFilter.getUnchecked(filter);
+ }
+
+ @Override
+ public SchemaContextFactory createSchemaContextFactory(@Nonnull final SchemaContextFactoryConfiguration config) {
+ return cacheByConfig.getUnchecked(config);
}
@Override
private static SourceIdentifier guessSourceIdentifier(final String fileName) {
try {
return YangTextSchemaSource.identifierFromFilename(fileName);
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
LOG.warn("Invalid file name format in '{}'", fileName, e);
return RevisionSourceIdentifier.create(fileName);
}
try {
sc = Optional.of(f.get());
break;
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
throw new RuntimeException("Interrupted while assembling schema context", e);
- } catch (ExecutionException e) {
+ } catch (final ExecutionException e) {
LOG.info("Failed to fully assemble schema context for {}", sources, e);
final Throwable cause = e.getCause();
Verify.verify(cause instanceof SchemaResolutionException);
try {
return future.get();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
throw new RuntimeException("Interrupted while waiting for SchemaContext assembly", e);
- } catch (ExecutionException e) {
+ } catch (final ExecutionException e) {
final Throwable cause = e.getCause();
if (cause instanceof SchemaResolutionException) {
throw (SchemaResolutionException) cause;
--- /dev/null
+/*
+ * Copyright (c) 2017 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.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.net.URI;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+
+public class SchemaContextFactoryDeviationsTest {
+ private static final String FOO = "/bug9195/foo.yang";
+ private static final String BAR = "/bug9195/bar.yang";
+ private static final String BAZ = "/bug9195/baz.yang";
+ private static final String FOOBAR = "/bug9195/foobar.yang";
+ private static final String BAR_INVALID = "/bug9195/bar-invalid.yang";
+ private static final String BAZ_INVALID = "/bug9195/baz-invalid.yang";
+ private static final URI FOO_NS = URI.create("foo-ns");
+ private static final URI BAR_NS = URI.create("bar-ns");
+ private static final URI BAZ_NS = URI.create("baz-ns");
+ private static Revision revision;
+ private static QNameModule foo;
+ private static QName myFooContA;
+ private static QName myFooContB;
+ private static QName myFooContC;
+ private static QNameModule bar;
+ private static QName myBarContA;
+ private static QName myBarContB;
+ private static QNameModule baz;
+
+ @BeforeClass
+ public static void setup() throws ParseException {
+ revision = Revision.of("2017-05-16");
+ foo = QNameModule.create(FOO_NS, revision);
+ myFooContA = QName.create(foo, "my-foo-cont-a");
+ myFooContB = QName.create(foo, "my-foo-cont-b");
+ myFooContC = QName.create(foo, "my-foo-cont-c");
+ bar = QNameModule.create(BAR_NS, revision);
+ myBarContA = QName.create(bar, "my-bar-cont-a");
+ myBarContB = QName.create(bar, "my-bar-cont-b");
+ baz = QNameModule.create(BAZ_NS, revision);
+ }
+
+ @Test
+ public void testDeviationsSupportedInSomeModules() throws Exception {
+ final SetMultimap<QNameModule, QNameModule> modulesWithSupportedDeviations =
+ ImmutableSetMultimap.<QNameModule, QNameModule>builder()
+ .put(foo, bar)
+ .put(foo, baz)
+ .put(bar, baz)
+ .build();
+
+ final ListenableFuture<SchemaContext> lf = createSchemaContext(modulesWithSupportedDeviations, FOO, BAR, BAZ,
+ FOOBAR);
+ assertTrue(lf.isDone());
+ final SchemaContext schemaContext = lf.get();
+ assertNotNull(schemaContext);
+
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContA)));
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContB)));
+ assertNotNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContC)));
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myBarContA)));
+ assertNotNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myBarContB)));
+ }
+
+ @Test
+ public void testDeviationsSupportedInAllModules() throws Exception {
+ final ListenableFuture<SchemaContext> lf = createSchemaContext(null, FOO, BAR, BAZ, FOOBAR);
+ assertTrue(lf.isDone());
+ final SchemaContext schemaContext = lf.get();
+ assertNotNull(schemaContext);
+
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContA)));
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContB)));
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContC)));
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myBarContA)));
+ assertNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myBarContB)));
+ }
+
+ @Test
+ public void testDeviationsSupportedInNoModule() throws Exception {
+ final ListenableFuture<SchemaContext> lf = createSchemaContext(ImmutableSetMultimap.of(), FOO, BAR, BAZ,
+ FOOBAR);
+ assertTrue(lf.isDone());
+ final SchemaContext schemaContext = lf.get();
+ assertNotNull(schemaContext);
+
+ assertNotNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContA)));
+ assertNotNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContB)));
+ assertNotNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myFooContC)));
+ assertNotNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myBarContA)));
+ assertNotNull(SchemaContextUtil.findDataSchemaNode(schemaContext, SchemaPath.create(true, myBarContB)));
+ }
+
+ @Test
+ public void shouldFailOnAttemptToDeviateTheSameModule2() throws Exception {
+ final ListenableFuture<SchemaContext> lf = createSchemaContext(null, BAR_INVALID, BAZ_INVALID);
+ assertTrue(lf.isDone());
+ try {
+ lf.get();
+ fail("Deviation that targets the same module as the one it is defined is forbidden.");
+ } catch (final ExecutionException ex) {
+ final Throwable cause = ex.getCause().getCause().getCause();
+ assertTrue(cause instanceof InferenceException);
+ assertTrue(cause.getMessage()
+ .startsWith("Deviation must not target the same module as the one it is defined in"));
+ }
+ }
+
+ private static SettableSchemaProvider<ASTSchemaSource> getImmediateYangSourceProviderFromResource(
+ final String resourceName) throws Exception {
+ final YangTextSchemaSource yangSource = YangTextSchemaSource.forResource(resourceName);
+ return SettableSchemaProvider.createImmediate(TextToASTTransformer.transformText(yangSource),
+ ASTSchemaSource.class);
+ }
+
+ private static ListenableFuture<SchemaContext> createSchemaContext(
+ final SetMultimap<QNameModule, QNameModule> modulesWithSupportedDeviations, final String... resources)
+ throws Exception {
+ final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
+ "shared-schema-repo-with-deviations-test");
+
+ final Collection<SourceIdentifier> requiredSources = new ArrayList<>();
+ for (final String resource : resources) {
+ final SettableSchemaProvider<ASTSchemaSource> yangSource = getImmediateYangSourceProviderFromResource(
+ resource);
+ yangSource.register(sharedSchemaRepository);
+ yangSource.setResult();
+ requiredSources.add(yangSource.getId());
+ }
+
+ final SchemaContextFactoryConfiguration config = SchemaContextFactoryConfiguration.builder()
+ .setModulesDeviatedByModules(modulesWithSupportedDeviations).build();
+ final SchemaContextFactory fact = sharedSchemaRepository.createSchemaContextFactory(config);
+
+ return fact.createSchemaContext(ImmutableList.copyOf(requiredSources));
+ }
+}
--- /dev/null
+module bar {
+ namespace bar-ns;
+ prefix bar;
+
+ import baz {
+ prefix baz;
+ revision-date 2017-05-16;
+ }
+
+ revision 2017-05-16;
+
+ deviation "/baz:my-baz-cont/bar:my-aug-cont" {
+ deviate not-supported;
+ }
+
+ augment "/baz:my-baz-cont" {
+ container my-aug-cont {}
+ }
+}
\ No newline at end of file
--- /dev/null
+module bar {
+ namespace bar-ns;
+ prefix bar-prefix;
+
+ import foo {
+ prefix foo;
+ revision-date 2017-05-16;
+ }
+
+ revision 2017-05-16;
+
+ deviation "/foo:my-foo-cont-a" {
+ deviate not-supported;
+ }
+
+ container my-bar-cont-a {}
+
+ container my-bar-cont-b {}
+}
\ No newline at end of file
--- /dev/null
+module baz {
+ namespace baz-ns;
+ prefix baz;
+
+ revision 2017-05-16;
+
+ container my-baz-cont {}
+}
\ No newline at end of file
--- /dev/null
+module baz {
+ namespace baz-ns;
+ prefix baz-prefix;
+
+ import foo {
+ prefix foo;
+ revision-date 2017-05-16;
+ }
+
+ import bar {
+ prefix bar;
+ revision-date 2017-05-16;
+ }
+
+ revision 2017-05-16;
+
+ deviation "/foo:my-foo-cont-b" {
+ deviate not-supported;
+ }
+
+ deviation "/bar:my-bar-cont-a" {
+ deviate not-supported;
+ }
+
+ container my-baz-cont {}
+}
\ No newline at end of file
--- /dev/null
+module foo {
+ namespace foo-ns;
+ prefix foo;
+
+ revision 2017-05-16;
+
+ deviation "/my-foo-cont" {
+ deviate not-supported;
+ }
+
+ container my-foo-cont {}
+}
\ No newline at end of file
--- /dev/null
+module foo {
+ namespace foo-ns;
+ prefix foo-prefix;
+
+ revision 2017-05-16;
+
+ container my-foo-cont-a {}
+
+ container my-foo-cont-b {}
+
+ container my-foo-cont-c {}
+}
\ No newline at end of file
--- /dev/null
+module foobar {
+ namespace foobar-ns;
+ prefix foobar-prefix;
+
+ import foo {
+ prefix foo;
+ revision-date 2017-05-16;
+ }
+
+ import bar {
+ prefix bar;
+ revision-date 2017-05-16;
+ }
+
+ revision 2017-05-16;
+
+ deviation "/foo:my-foo-cont-c" {
+ deviate not-supported;
+ }
+
+ deviation "/bar:my-bar-cont-b" {
+ deviate not-supported;
+ }
+}
\ No newline at end of file
import com.google.common.base.Verify;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import java.util.ArrayList;
ImmutableSet.copyOf(supportedFeatures));
}
- void setModulesDeviatedByModules(final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules) {
+ void setModulesDeviatedByModules(final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
addToNs(ModulesDeviatedByModules.class, SupportedModules.SUPPORTED_MODULES,
- ImmutableMap.copyOf(modulesDeviatedByModules));
+ ImmutableSetMultimap.copyOf(modulesDeviatedByModules));
}
@Override
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.SetMultimap;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
* @return This build action, for fluent use.
*/
public BuildAction setModulesWithSupportedDeviations(
- @Nonnull final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules) {
+ @Nonnull final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
checkState(!modulesDeviatedByModulesSet, "Modules with supported deviations should be set only once.");
context.setModulesDeviatedByModules(requireNonNull(modulesDeviatedByModules));
modulesDeviatedByModulesSet = true;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.SetMultimap;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
private static boolean isDeviationSupported(final Mutable<DeviateKind, DeviateStatement,
EffectiveStatement<DeviateKind, DeviateStatement>> deviateStmtCtx,
final SchemaNodeIdentifier deviationTarget) {
- final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules = deviateStmtCtx.getFromNamespace(
+ final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules = deviateStmtCtx.getFromNamespace(
ModulesDeviatedByModules.class, SupportedModules.SUPPORTED_MODULES);
if (modulesDeviatedByModules == null) {
return true;
import static org.junit.Assert.fail;
import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
import java.net.URI;
-import java.util.Map;
-import java.util.Set;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
@Test
public void testDeviationsSupportedInSomeModules() throws Exception {
- final Map<QNameModule, Set<QNameModule>> modulesWithSupportedDeviations = ImmutableMap.of(
- foo, ImmutableSet.of(bar, baz), bar, ImmutableSet.of(baz));
+ final SetMultimap<QNameModule, QNameModule> modulesWithSupportedDeviations =
+ ImmutableSetMultimap.<QNameModule, QNameModule>builder()
+ .put(foo, bar)
+ .put(foo, baz)
+ .put(bar, baz)
+ .build();
final SchemaContext schemaContext = RFC7950Reactors.defaultReactor().newBuild()
.addSources(FOO_MODULE, BAR_MODULE, BAZ_MODULE, FOOBAR_MODULE)
public void testDeviationsSupportedInNoModule() throws Exception {
final SchemaContext schemaContext = RFC7950Reactors.defaultReactor().newBuild()
.addSources(FOO_MODULE, BAR_MODULE, BAZ_MODULE, FOOBAR_MODULE)
- .setModulesWithSupportedDeviations(ImmutableMap.of())
+ .setModulesWithSupportedDeviations(ImmutableSetMultimap.of())
.buildEffective();
assertNotNull(schemaContext);
package org.opendaylight.yangtools.yang.parser.spi.source;
import com.google.common.annotations.Beta;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.collect.SetMultimap;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
*/
@Beta
public interface ModulesDeviatedByModules
- extends IdentifierNamespace<ModulesDeviatedByModules.SupportedModules, Map<QNameModule, Set<QNameModule>>> {
- NamespaceBehaviour<SupportedModules, Map<QNameModule, Set<QNameModule>>, @NonNull ModulesDeviatedByModules>
+ extends IdentifierNamespace<ModulesDeviatedByModules.SupportedModules, SetMultimap<QNameModule, QNameModule>> {
+ NamespaceBehaviour<SupportedModules, SetMultimap<QNameModule, QNameModule>, @NonNull ModulesDeviatedByModules>
BEHAVIOUR = NamespaceBehaviour.global(ModulesDeviatedByModules.class);
enum SupportedModules {