From c11896bd11b0549ab5bf0a493b299a6660b0481f Mon Sep 17 00:00:00 2001 From: Igor Foltin Date: Fri, 13 May 2016 11:42:06 +0200 Subject: [PATCH] Bug 4506: Honor if-feature during SchemaContext assembly If-feature statements in yang modules are now resolved during SchemaContext assembly based on a java.util.function.Predicate provided by user. This functionality is also introduced into SchemaContextFactory Change-Id: I2a74e36c9433a0b89c97c19407c988b538c236bc Signed-off-by: Igor Foltin Signed-off-by: Robert Varga Signed-off-by: Igor Foltin --- .../model/repo/api/SchemaContextFactory.java | 22 +- .../repo/SharedSchemaContextFactory.java | 83 ++-- .../parser/spi/meta/StmtContextUtils.java | 32 ++ .../source/SupportedFeaturesNamespace.java | 21 + .../stmt/reactor/BuildGlobalContext.java | 14 +- .../reactor/CrossSourceStatementReactor.java | 16 +- .../stmt/rfc6020/AugmentStatementImpl.java | 7 +- .../stmt/rfc6020/UsesStatementImpl.java | 6 +- .../stmt/rfc6020/YangInferencePipeline.java | 2 + .../effective/EffectiveStatementBase.java | 11 + ...haredSchemaRepositoryWithFeaturesTest.java | 171 +++++++++ .../yang/stmt/IfFeatureResolutionTest.java | 362 ++++++++++++++++++ .../if-feature-resolution-test/bar.yang | 10 + .../if-feature-resolution-test/foo.yang | 125 ++++++ .../shared-schema-repository/foobar.yang | 26 ++ 15 files changed, 865 insertions(+), 43 deletions(-) create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/SupportedFeaturesNamespace.java create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaRepositoryWithFeaturesTest.java create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/IfFeatureResolutionTest.java create mode 100644 yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/bar.yang create mode 100644 yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/foo.yang create mode 100644 yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/shared-schema-repository/foobar.yang diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/repo/api/SchemaContextFactory.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/repo/api/SchemaContextFactory.java index 11782fe2ac..9b338a742b 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/repo/api/SchemaContextFactory.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/repo/api/SchemaContextFactory.java @@ -10,7 +10,9 @@ package org.opendaylight.yangtools.yang.model.repo.api; import com.google.common.annotations.Beta; import com.google.common.util.concurrent.CheckedFuture; import java.util.Collection; +import java.util.function.Predicate; import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.SchemaContext; /** @@ -30,5 +32,23 @@ public interface SchemaContextFactory { * fail with an explanation why the creation of the schema context * failed. */ - CheckedFuture createSchemaContext(@Nonnull Collection requiredSources); + default CheckedFuture createSchemaContext( + @Nonnull Collection requiredSources) { + return createSchemaContext(requiredSources, 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. + */ + CheckedFuture createSchemaContext( + @Nonnull Collection requiredSources, Predicate isFeatureSupported); } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaContextFactory.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaContextFactory.java index ab146fcfc6..1594fd4212 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaContextFactory.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaContextFactory.java @@ -33,6 +33,7 @@ import org.antlr.v4.runtime.ParserRuleContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext; import org.opendaylight.yangtools.util.concurrent.ExceptionMapper; import org.opendaylight.yangtools.util.concurrent.ReflectiveExceptionMapper; +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.SchemaResolutionException; @@ -59,41 +60,6 @@ final class SharedSchemaContextFactory implements SchemaContextFactory { } }; private final Cache, SchemaContext> cache = CacheBuilder.newBuilder().weakValues().build(); - - private final AsyncFunction, SchemaContext> assembleSources = new AsyncFunction, SchemaContext>() { - @Override - public ListenableFuture apply(final List sources) throws SchemaResolutionException, SourceException, ReactorException { - final Map srcs = - Maps.uniqueIndex(sources, ASTSchemaSource.GET_IDENTIFIER); - final Map deps = - Maps.transformValues(srcs, ASTSchemaSource.GET_DEPINFO); - - LOG.debug("Resolving dependency reactor {}", deps); - - final DependencyResolver res = DependencyResolver.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", - res.getResolvedSources(), res.getUnsatisfiedImports()); - } - - final Map asts = Maps.transformValues(srcs, ASTSchemaSource.GET_AST); - final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(); - - for (final Entry e : asts.entrySet()) { - final ParserRuleContext parserRuleCtx = e.getValue(); - Preconditions.checkArgument(parserRuleCtx instanceof StatementContext, - "Unsupported context class %s for source %s", parserRuleCtx.getClass(), e.getKey()); - - reactor.addSource(new YangStatementSourceImpl(e.getKey(), (StatementContext) parserRuleCtx)); - } - - SchemaContext schemaContext = reactor.buildEffective(); - - return Futures.immediateCheckedFuture(schemaContext); - } - }; - private final SharedSchemaRepository repository; // FIXME: ignored right now private final SchemaSourceFilter filter; @@ -105,7 +71,8 @@ final class SharedSchemaContextFactory implements SchemaContextFactory { } @Override - public CheckedFuture createSchemaContext(final Collection requiredSources) { + public CheckedFuture createSchemaContext( + final Collection requiredSources, java.util.function.Predicate isFeatureSupported) { // Make sources unique final List uniqueSourceIdentifiers = deDuplicateSources(requiredSources); @@ -124,6 +91,7 @@ final class SharedSchemaContextFactory implements SchemaContextFactory { sf = Futures.transform(sf, new SourceIdMismatchDetector(uniqueSourceIdentifiers)); // Assemble sources into a schema context + final AssembleSources assembleSources = new AssembleSources(isFeatureSupported); final ListenableFuture cf = Futures.transform(sf, assembleSources); // Populate cache when successful @@ -194,4 +162,47 @@ final class SharedSchemaContextFactory implements SchemaContextFactory { return ImmutableList.copyOf(filtered.values()); } } + + private static final class AssembleSources implements AsyncFunction, SchemaContext> { + + private final java.util.function.Predicate isFeatureSupported; + + private AssembleSources(final java.util.function.Predicate isFeatureSupported) { + this.isFeatureSupported = Preconditions.checkNotNull(isFeatureSupported); + } + + @Override + public ListenableFuture apply(List sources) throws SchemaResolutionException, + SourceException, ReactorException { + final Map srcs = + Maps.uniqueIndex(sources, ASTSchemaSource.GET_IDENTIFIER); + final Map deps = + Maps.transformValues(srcs, ASTSchemaSource.GET_DEPINFO); + + LOG.debug("Resolving dependency reactor {}", deps); + + final DependencyResolver res = DependencyResolver.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", + res.getResolvedSources(), res.getUnsatisfiedImports()); + } + + final Map asts = Maps.transformValues(srcs, ASTSchemaSource.GET_AST); + final CrossSourceStatementReactor.BuildAction reactor = + YangInferencePipeline.RFC6020_REACTOR.newBuild(isFeatureSupported); + + for (final Entry e : asts.entrySet()) { + final ParserRuleContext parserRuleCtx = e.getValue(); + Preconditions.checkArgument(parserRuleCtx instanceof StatementContext, + "Unsupported context class %s for source %s", parserRuleCtx.getClass(), e.getKey()); + + reactor.addSource(new YangStatementSourceImpl(e.getKey(), (StatementContext) parserRuleCtx)); + } + + SchemaContext schemaContext = reactor.buildEffective(); + + return Futures.immediateCheckedFuture(schemaContext); + } + } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java index 05b7f67c33..fd15851a2f 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java @@ -12,13 +12,21 @@ import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; +import java.util.ArrayList; import java.util.Collection; +import java.util.Set; +import java.util.function.Predicate; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.KeyStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; +import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace; +import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnknownStatementImpl; public final class StmtContextUtils { @@ -223,4 +231,28 @@ public final class StmtContextUtils { // This makes sure we reuse the collection when a grouping is instantiated in the same module return replaced ? builder.build() : keyStmtCtx.getStatementArgument(); } + + public static boolean areFeaturesSupported(final StmtContext stmtContext) { + Predicate isFeatureSupported = stmtContext.getFromNamespace(SupportedFeaturesNamespace.class, + SupportedFeatures.SUPPORTED_FEATURES); + Collection> substatements = new ArrayList<>(); + substatements.addAll(stmtContext.declaredSubstatements()); + substatements.addAll(stmtContext.effectiveSubstatements()); + + boolean isSupported = false; + boolean containsIfFeature = false; + for (StatementContextBase stmt: substatements) { + if (stmt.getPublicDefinition().equals(Rfc6020Mapping.IF_FEATURE)) { + containsIfFeature = true; + if (isFeatureSupported.test((QName) stmt.getStatementArgument())) { + isSupported = true; + } else { + isSupported = false; + break; + } + } + } + + return !containsIfFeature || isSupported; + } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/SupportedFeaturesNamespace.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/SupportedFeaturesNamespace.java new file mode 100644 index 0000000000..ac2632c11d --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/SupportedFeaturesNamespace.java @@ -0,0 +1,21 @@ +/* + * 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.spi.source; + +import java.util.function.Predicate; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; + +public interface SupportedFeaturesNamespace + extends IdentifierNamespace> { + + enum SupportedFeatures { + SUPPORTED_FEATURES + } +} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java index 66c29cd328..4ab08c5cdf 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; +import java.util.function.Predicate; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; @@ -39,6 +40,8 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource; +import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace; +import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType; import org.opendaylight.yangtools.yang.parser.stmt.reactor.SourceSpecificContext.PhaseCompletionProgress; @@ -66,18 +69,25 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh private ModelProcessingPhase currentPhase = ModelProcessingPhase.INIT; private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT; - public BuildGlobalContext(final Map supports) { + public BuildGlobalContext(final Map supports, + final Predicate isFeatureSupported) { super(); this.supports = Preconditions.checkNotNull(supports, "BuildGlobalContext#supports cannot be null"); + + addToNs(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES, isFeatureSupported); } - public BuildGlobalContext(final Map supports, final Map> supportedValidation) { + public BuildGlobalContext(final Map supports, + final Map> supportedValidation, + final Predicate isFeatureSupported) { super(); this.supports = Preconditions.checkNotNull(supports, "BuildGlobalContext#supports cannot be null"); for (Entry> validationBundle : supportedValidation.entrySet()) { addToNs(ValidationBundlesNamespace.class, validationBundle.getKey(), validationBundle.getValue()); } + + addToNs(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES, isFeatureSupported); } public StatementSupportBundle getSupportsForPhase(final ModelProcessingPhase currentPhase) { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/CrossSourceStatementReactor.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/CrossSourceStatementReactor.java index e037ae534b..9873466b30 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/CrossSourceStatementReactor.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/CrossSourceStatementReactor.java @@ -7,6 +7,7 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.reactor; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteSource; import java.io.File; @@ -20,6 +21,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Predicate; +import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; @@ -51,7 +54,11 @@ public class CrossSourceStatementReactor { } public final BuildAction newBuild() { - return new BuildAction(); + return newBuild(t -> true); + } + + public final BuildAction newBuild(final Predicate isFeatureSupported) { + return new BuildAction(isFeatureSupported); } public static class Builder implements org.opendaylight.yangtools.concepts.Builder{ @@ -80,7 +87,12 @@ public class CrossSourceStatementReactor { private final BuildGlobalContext context; public BuildAction() { - this.context = new BuildGlobalContext(supportedTerminology, supportedValidation); + this(t -> true); + } + + public BuildAction(Predicate isFeatureSupported) { + Preconditions.checkNotNull(isFeatureSupported); + this.context = new BuildGlobalContext(supportedTerminology, supportedValidation, isFeatureSupported); } public void addSource(final StatementStreamSource source) { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java index 0638d31abd..97edbf247d 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AugmentStatementImpl.java @@ -90,6 +90,10 @@ public class AugmentStatementImpl extends AbstractDeclaredStatement> augmentNode) { + if (!StmtContextUtils.areFeaturesSupported(augmentNode)) { + return; + } + SUBSTATEMENT_VALIDATOR.validate(augmentNode); if (StmtContextUtils.isInExtensionBody(augmentNode)) { @@ -107,7 +111,8 @@ public class AugmentStatementImpl extends AbstractDeclaredStatement augmentTargetCtx = (StatementContextBase) target.get(); - if (!AugmentUtils.isSupportedAugmentTarget(augmentTargetCtx) || StmtContextUtils.isInExtensionBody(augmentTargetCtx)) { + if (!AugmentUtils.isSupportedAugmentTarget(augmentTargetCtx) + || StmtContextUtils.isInExtensionBody(augmentTargetCtx)) { augmentNode.setIsSupportedToBuildEffective(false); return; } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java index f7979c4f01..92083c435e 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/UsesStatementImpl.java @@ -71,6 +71,10 @@ public class UsesStatementImpl extends AbstractDeclaredStatement implemen @Override public void onFullDefinitionDeclared( final StmtContext.Mutable> usesNode) { + if (!StmtContextUtils.areFeaturesSupported(usesNode)) { + return; + } + SUBSTATEMENT_VALIDATOR.validate(usesNode); if (StmtContextUtils.isInExtensionBody(usesNode)) { @@ -104,7 +108,7 @@ public class UsesStatementImpl extends AbstractDeclaredStatement implemen @Override public void prerequisiteFailed(final Collection> failed) { InferenceException.throwIf(failed.contains(sourceGroupingPre), - usesNode.getStatementSourceReference(), "Grouping '%s' was not resolved.", groupingName); + usesNode.getStatementSourceReference(), "Grouping '%s' was not resolved.", groupingName); throw new InferenceException("Unknown error occurred.", usesNode.getStatementSourceReference()); } }); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java index 7255a7165a..bbb52f6e9a 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java @@ -41,6 +41,7 @@ import org.opendaylight.yangtools.yang.parser.spi.source.ModuleQNameToModuleName import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition; import org.opendaylight.yangtools.yang.parser.spi.source.StmtOrderingNamespace; +import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType; import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; @@ -49,6 +50,7 @@ public final class YangInferencePipeline { public static final StatementSupportBundle INIT_BUNDLE = StatementSupportBundle .builder().addSupport(global(ValidationBundlesNamespace.class)) + .addSupport(global(SupportedFeaturesNamespace.class)) .build(); public static final StatementSupportBundle PRE_LINKAGE_BUNDLE = StatementSupportBundle diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/EffectiveStatementBase.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/EffectiveStatementBase.java index 8b94095781..15888ae590 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/EffectiveStatementBase.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/EffectiveStatementBase.java @@ -45,6 +45,15 @@ public abstract class EffectiveStatementBase> } }; + private static final Predicate> ARE_FEATURES_SUPPORTED = + new Predicate>() { + + @Override + public boolean apply(StmtContext input) { + return StmtContextUtils.areFeaturesSupported(input); + } + }; + private final List> substatements; private final List> unknownSubstatementsToBuild; @@ -92,6 +101,8 @@ public abstract class EffectiveStatementBase> this.unknownSubstatementsToBuild = ImmutableList.of(); } + substatementsToBuild = Collections2.filter(substatementsToBuild, ARE_FEATURES_SUPPORTED); + Function>, EffectiveStatement> buildEffective = StmtContextUtils.buildEffective(); this.substatements = ImmutableList.copyOf(Collections2.transform(substatementsToBuild, buildEffective)); } diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaRepositoryWithFeaturesTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaRepositoryWithFeaturesTest.java new file mode 100644 index 0000000000..18b6fa72cf --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaRepositoryWithFeaturesTest.java @@ -0,0 +1,171 @@ +/* + * 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.assertNull; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.CheckedFuture; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +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.parser.util.ASTSchemaSource; +import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer; + +public class SharedSchemaRepositoryWithFeaturesTest { + + @Test + public void testSharedSchemaRepositoryWithSomeFeaturesSupported() throws Exception { + Predicate isFeatureSupported = qName -> { + Set supportedFeatures = new HashSet<>(); + supportedFeatures.add(QName.create("foobar-namespace", "1970-01-01", "test-feature-1")); + + return supportedFeatures.contains(qName); + }; + + final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository( + "shared-schema-repo-with-features-test"); + + final SettableSchemaProvider foobar = getImmediateYangSourceProviderFromResource + ("/if-feature-resolution-test/shared-schema-repository/foobar.yang"); + foobar.register(sharedSchemaRepository); + foobar.setResult(); + + final SchemaContextFactory fact = sharedSchemaRepository + .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + + final CheckedFuture testSchemaContextFuture = + fact.createSchemaContext(Lists.newArrayList(foobar.getId()), isFeatureSupported); + assertTrue(testSchemaContextFuture.isDone()); + assertSchemaContext(testSchemaContextFuture.checkedGet(), 1); + + Module module = testSchemaContextFuture.checkedGet().findModuleByName("foobar", null); + assertNotNull(module); + assertEquals(2, module.getChildNodes().size()); + + ContainerSchemaNode testContainerA = (ContainerSchemaNode) module.getDataChildByName( + QName.create(module.getQNameModule(), "test-container-a")); + assertNotNull(testContainerA); + LeafSchemaNode testLeafA = (LeafSchemaNode) testContainerA.getDataChildByName( + QName.create(module.getQNameModule(), "test-leaf-a")); + assertNotNull(testLeafA); + + ContainerSchemaNode testContainerB = (ContainerSchemaNode) module.getDataChildByName( + QName.create(module.getQNameModule(), "test-container-b")); + assertNull(testContainerB); + + ContainerSchemaNode testContainerC = (ContainerSchemaNode) module.getDataChildByName( + QName.create(module.getQNameModule(), "test-container-c")); + assertNotNull(testContainerC); + LeafSchemaNode testLeafC = (LeafSchemaNode) testContainerC.getDataChildByName( + QName.create(module.getQNameModule(), "test-leaf-c")); + assertNotNull(testLeafC); + } + + @Test + public void testSharedSchemaRepositoryWithAllFeaturesSupported() throws Exception { + final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository( + "shared-schema-repo-with-features-test"); + + final SettableSchemaProvider foobar = getImmediateYangSourceProviderFromResource + ("/if-feature-resolution-test/shared-schema-repository/foobar.yang"); + foobar.register(sharedSchemaRepository); + foobar.setResult(); + + final SchemaContextFactory fact = sharedSchemaRepository + .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + + final CheckedFuture testSchemaContextFuture = fact + .createSchemaContext(Lists.newArrayList(foobar.getId())); + assertTrue(testSchemaContextFuture.isDone()); + assertSchemaContext(testSchemaContextFuture.checkedGet(), 1); + + Module module = testSchemaContextFuture.checkedGet().findModuleByName("foobar", null); + assertNotNull(module); + assertEquals(3, module.getChildNodes().size()); + + ContainerSchemaNode testContainerA = (ContainerSchemaNode) module.getDataChildByName( + QName.create(module.getQNameModule(), "test-container-a")); + assertNotNull(testContainerA); + LeafSchemaNode testLeafA = (LeafSchemaNode) testContainerA.getDataChildByName( + QName.create(module.getQNameModule(), "test-leaf-a")); + assertNotNull(testLeafA); + + ContainerSchemaNode testContainerB = (ContainerSchemaNode) module.getDataChildByName( + QName.create(module.getQNameModule(), "test-container-b")); + assertNotNull(testContainerB); + LeafSchemaNode testLeafB = (LeafSchemaNode) testContainerB.getDataChildByName( + QName.create(module.getQNameModule(), "test-leaf-b")); + assertNotNull(testLeafB); + + ContainerSchemaNode testContainerC = (ContainerSchemaNode) module.getDataChildByName( + QName.create(module.getQNameModule(), "test-container-c")); + assertNotNull(testContainerC); + LeafSchemaNode testLeafC = (LeafSchemaNode) testContainerC.getDataChildByName( + QName.create(module.getQNameModule(), "test-leaf-c")); + assertNotNull(testLeafC); + } + + @Test + public void testSharedSchemaRepositoryWithNoFeaturesSupported() throws Exception { + Predicate isFeatureSupported = qName -> false; + + final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository( + "shared-schema-repo-with-features-test"); + + final SettableSchemaProvider foobar = getImmediateYangSourceProviderFromResource + ("/if-feature-resolution-test/shared-schema-repository/foobar.yang"); + foobar.register(sharedSchemaRepository); + foobar.setResult(); + + final SchemaContextFactory fact = sharedSchemaRepository + .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + + final CheckedFuture testSchemaContextFuture = fact + .createSchemaContext(Lists.newArrayList(foobar.getId()), isFeatureSupported); + assertTrue(testSchemaContextFuture.isDone()); + assertSchemaContext(testSchemaContextFuture.checkedGet(), 1); + + Module module = testSchemaContextFuture.checkedGet().findModuleByName("foobar", null); + assertNotNull(module); + assertEquals(1, module.getChildNodes().size()); + + ContainerSchemaNode testContainerC = (ContainerSchemaNode) module.getDataChildByName( + QName.create(module.getQNameModule(), "test-container-c")); + assertNotNull(testContainerC); + LeafSchemaNode testLeafC = (LeafSchemaNode) testContainerC.getDataChildByName( + QName.create(module.getQNameModule(), "test-leaf-c")); + assertNotNull(testLeafC); + } + + private SettableSchemaProvider getImmediateYangSourceProviderFromResource( + final String resourceName) throws Exception { + final ResourceYangSource yangSource = new ResourceYangSource(resourceName); + final CheckedFuture aSTSchemaSource = TextToASTTransformer.TRANSFORMATION.apply(yangSource); + return SettableSchemaProvider.createImmediate(aSTSchemaSource.get(), ASTSchemaSource.class); + } + + private void assertSchemaContext(final SchemaContext schemaContext, final int moduleSize) { + assertNotNull(schemaContext); + assertEquals(moduleSize, schemaContext.getModules().size()); + } +} diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/IfFeatureResolutionTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/IfFeatureResolutionTest.java new file mode 100644 index 0000000000..c26cb5ab5a --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/IfFeatureResolutionTest.java @@ -0,0 +1,362 @@ +/* + * 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.stmt; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl; + +public class IfFeatureResolutionTest { + + private static final StatementStreamSource FOO_MODULE = + new YangStatementSourceImpl("/if-feature-resolution-test/foo.yang", false); + private static final StatementStreamSource BAR_MODULE = + new YangStatementSourceImpl("/if-feature-resolution-test/bar.yang", false); + + @Test + public void testSomeFeaturesSupported() throws ReactorException { + Predicate isFeatureSupported = qName -> { + Set supportedFeatures = new HashSet<>(); + supportedFeatures.add(QName.create("foo-namespace", "1970-01-01", "test-feature-1")); + supportedFeatures.add(QName.create("foo-namespace", "1970-01-01", "test-feature-2")); + supportedFeatures.add(QName.create("foo-namespace", "1970-01-01", "test-feature-3")); + supportedFeatures.add(QName.create("bar-namespace", "1970-01-01", "imp-feature")); + + return supportedFeatures.contains(qName); + }; + + CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(isFeatureSupported); + reactor.addSources(FOO_MODULE, BAR_MODULE); + + SchemaContext schemaContext = reactor.buildEffective(); + assertNotNull(schemaContext); + + Module testModule = schemaContext.findModuleByName("foo", null); + assertNotNull(testModule); + + assertEquals(9, testModule.getChildNodes().size()); + + ContainerSchemaNode testContainerA = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-a")); + assertNull(testContainerA); + + ContainerSchemaNode testContainerB = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-b")); + assertNotNull(testContainerB); + LeafSchemaNode testLeafB = (LeafSchemaNode) testContainerB.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-b")); + assertNotNull(testLeafB); + + ContainerSchemaNode testContainerC = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-c")); + assertNotNull(testContainerC); + LeafSchemaNode testLeafC = (LeafSchemaNode) testContainerC.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-c")); + assertNotNull(testLeafC); + + ContainerSchemaNode testContainerD = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-d")); + assertNull(testContainerD); + + ContainerSchemaNode testContainerE = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-e")); + assertNotNull(testContainerE); + ContainerSchemaNode testSubContainerE = (ContainerSchemaNode) testContainerE.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-subcontainer-e")); + assertNotNull(testSubContainerE); + LeafSchemaNode testLeafE = (LeafSchemaNode) testSubContainerE.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-e")); + assertNull(testLeafE); + + ContainerSchemaNode testContainerF = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-f")); + assertNotNull(testContainerF); + ContainerSchemaNode testSubContainerF = (ContainerSchemaNode) testContainerF.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-subcontainer-f")); + assertNull(testSubContainerF); + + ContainerSchemaNode testContainerG = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-g")); + assertNotNull(testContainerG); + assertEquals(1, testContainerG.getAvailableAugmentations().size()); + LeafSchemaNode testLeafG = (LeafSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-g")); + assertNotNull(testLeafG); + LeafSchemaNode augmentingTestLeafG = (LeafSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-leaf-g")); + assertNull(augmentingTestLeafG); + AnyXmlSchemaNode augmentingTestAnyxmlG = (AnyXmlSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-anyxml-g")); + assertNotNull(augmentingTestAnyxmlG); + + ContainerSchemaNode testContainerH = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-h")); + assertNotNull(testContainerH); + assertEquals(0, testContainerH.getChildNodes().size()); + assertEquals(0, testContainerH.getUses().size()); + + ContainerSchemaNode testContainerI = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-i")); + assertNotNull(testContainerI); + assertEquals(1, testContainerI.getUses().size()); + ContainerSchemaNode testGroupingSubContainer = (ContainerSchemaNode) testContainerI.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-subcontainer")); + assertNotNull(testGroupingSubContainer); + LeafSchemaNode testGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-leaf")); + assertNull(testGroupingLeaf); + + ContainerSchemaNode testContainerJ = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-j")); + assertNotNull(testContainerJ); + LeafSchemaNode testLeafJ = (LeafSchemaNode) testContainerJ.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-j")); + assertNotNull(testLeafJ); + + ContainerSchemaNode testContainerK = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-k")); + assertNotNull(testContainerK); + assertEquals(1, testContainerK.getUses().size()); + testGroupingSubContainer = (ContainerSchemaNode) testContainerK.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-subcontainer")); + assertNotNull(testGroupingSubContainer); + assertEquals(1, testGroupingSubContainer.getAvailableAugmentations().size()); + LeafSchemaNode augmentingTestGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-grouping-leaf")); + assertNotNull(augmentingTestGroupingLeaf); + LeafSchemaNode augmentingTestGroupingLeaf2 = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-grouping-leaf-2")); + assertNull(augmentingTestGroupingLeaf2); + } + + @Test + public void testAllFeaturesSupported() throws ReactorException { + CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(); + reactor.addSources(FOO_MODULE, BAR_MODULE); + + SchemaContext schemaContext = reactor.buildEffective(); + assertNotNull(schemaContext); + + Module testModule = schemaContext.findModuleByName("foo", null); + assertNotNull(testModule); + + assertEquals(11, testModule.getChildNodes().size()); + + ContainerSchemaNode testContainerA = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-a")); + assertNotNull(testContainerA); + LeafSchemaNode testLeafA = (LeafSchemaNode) testContainerA.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-a")); + assertNotNull(testLeafA); + + + ContainerSchemaNode testContainerB = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-b")); + assertNotNull(testContainerB); + LeafSchemaNode testLeafB = (LeafSchemaNode) testContainerB.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-b")); + assertNotNull(testLeafB); + + ContainerSchemaNode testContainerC = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-c")); + assertNotNull(testContainerC); + LeafSchemaNode testLeafC = (LeafSchemaNode) testContainerC.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-c")); + assertNotNull(testLeafC); + + ContainerSchemaNode testContainerD = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-d")); + assertNotNull(testContainerD); + LeafSchemaNode testLeafD = (LeafSchemaNode) testContainerD.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-d")); + assertNotNull(testLeafD); + + ContainerSchemaNode testContainerE = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-e")); + assertNotNull(testContainerE); + ContainerSchemaNode testSubContainerE = (ContainerSchemaNode) testContainerE.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-subcontainer-e")); + assertNotNull(testSubContainerE); + LeafSchemaNode testLeafE = (LeafSchemaNode) testSubContainerE.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-e")); + assertNotNull(testLeafE); + + ContainerSchemaNode testContainerF = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-f")); + assertNotNull(testContainerF); + ContainerSchemaNode testSubContainerF = (ContainerSchemaNode) testContainerF.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-subcontainer-f")); + assertNotNull(testSubContainerF); + ContainerSchemaNode testSubSubContainerF = (ContainerSchemaNode) testSubContainerF.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-subsubcontainer-f")); + assertNotNull(testSubSubContainerF); + LeafSchemaNode testLeafF = (LeafSchemaNode) testSubSubContainerF.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-f")); + assertNotNull(testLeafF); + + ContainerSchemaNode testContainerG = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-g")); + assertNotNull(testContainerG); + assertEquals(2, testContainerG.getAvailableAugmentations().size()); + LeafSchemaNode testLeafG = (LeafSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-g")); + assertNotNull(testLeafG); + LeafSchemaNode augmentingTestLeafG = (LeafSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-leaf-g")); + assertNotNull(augmentingTestLeafG); + AnyXmlSchemaNode augmentingTestAnyxmlG = (AnyXmlSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-anyxml-g")); + assertNotNull(augmentingTestAnyxmlG); + + ContainerSchemaNode testContainerH = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-h")); + assertNotNull(testContainerH); + assertEquals(1, testContainerH.getUses().size()); + ContainerSchemaNode testGroupingSubContainer = (ContainerSchemaNode) testContainerH.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-subcontainer")); + assertNotNull(testGroupingSubContainer); + LeafSchemaNode testGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-leaf")); + assertNotNull(testGroupingLeaf); + + ContainerSchemaNode testContainerI = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-i")); + assertNotNull(testContainerI); + assertEquals(1, testContainerI.getUses().size()); + testGroupingSubContainer = (ContainerSchemaNode) testContainerI.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-subcontainer")); + assertNotNull(testGroupingSubContainer); + testGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-leaf")); + assertNotNull(testGroupingLeaf); + + ContainerSchemaNode testContainerJ = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-j")); + assertNotNull(testContainerJ); + LeafSchemaNode testLeafJ = (LeafSchemaNode) testContainerJ.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-j")); + assertNotNull(testLeafJ); + + ContainerSchemaNode testContainerK = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-k")); + assertNotNull(testContainerK); + assertEquals(1, testContainerK.getUses().size()); + testGroupingSubContainer = (ContainerSchemaNode) testContainerK.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-subcontainer")); + assertNotNull(testGroupingSubContainer); + assertEquals(1, testGroupingSubContainer.getAvailableAugmentations().size()); + LeafSchemaNode augmentingTestGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-grouping-leaf")); + assertNotNull(augmentingTestGroupingLeaf); + LeafSchemaNode augmentingTestGroupingLeaf2 = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-grouping-leaf-2")); + assertNotNull(augmentingTestGroupingLeaf2); + testGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-leaf")); + assertNotNull(testGroupingLeaf); + } + + @Test + public void testNoFeaturesSupported() throws ReactorException { + Predicate isFeatureSupported = qName -> false; + + CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(isFeatureSupported); + reactor.addSources(FOO_MODULE, BAR_MODULE); + + SchemaContext schemaContext = reactor.buildEffective(); + assertNotNull(schemaContext); + + Module testModule = schemaContext.findModuleByName("foo", null); + assertNotNull(testModule); + + assertEquals(6, testModule.getChildNodes().size()); + + ContainerSchemaNode testContainerE = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-e")); + assertNotNull(testContainerE); + ContainerSchemaNode testSubContainerE = (ContainerSchemaNode) testContainerE.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-subcontainer-e")); + assertNotNull(testSubContainerE); + LeafSchemaNode testLeafE = (LeafSchemaNode) testSubContainerE.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-e")); + assertNull(testLeafE); + + ContainerSchemaNode testContainerF = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-f")); + assertNotNull(testContainerF); + ContainerSchemaNode testSubContainerF = (ContainerSchemaNode) testContainerF.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-subcontainer-f")); + assertNull(testSubContainerF); + + ContainerSchemaNode testContainerG = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-g")); + assertNotNull(testContainerG); + assertEquals(1, testContainerG.getAvailableAugmentations().size()); + LeafSchemaNode testLeafG = (LeafSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-leaf-g")); + assertNotNull(testLeafG); + LeafSchemaNode augmentingTestLeafG = (LeafSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-leaf-g")); + assertNull(augmentingTestLeafG); + AnyXmlSchemaNode augmentingTestAnyxmlG = (AnyXmlSchemaNode) testContainerG.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-anyxml-g")); + assertNotNull(augmentingTestAnyxmlG); + + ContainerSchemaNode testContainerH = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-h")); + assertNotNull(testContainerH); + assertEquals(0, testContainerH.getChildNodes().size()); + assertEquals(0, testContainerH.getUses().size()); + + ContainerSchemaNode testContainerI = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-i")); + assertNotNull(testContainerI); + assertEquals(1, testContainerI.getUses().size()); + ContainerSchemaNode testGroupingSubContainer = (ContainerSchemaNode) testContainerI.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-subcontainer")); + assertNotNull(testGroupingSubContainer); + LeafSchemaNode testGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-leaf")); + assertNull(testGroupingLeaf); + + ContainerSchemaNode testContainerK = (ContainerSchemaNode) testModule.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-container-k")); + assertNotNull(testContainerK); + assertEquals(1, testContainerK.getUses().size()); + testGroupingSubContainer = (ContainerSchemaNode) testContainerK.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-subcontainer")); + assertNotNull(testGroupingSubContainer); + assertEquals(1, testGroupingSubContainer.getAvailableAugmentations().size()); + LeafSchemaNode augmentingTestGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-grouping-leaf")); + assertNull(augmentingTestGroupingLeaf); + LeafSchemaNode augmentingTestGroupingLeaf2 = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "augmenting-test-grouping-leaf-2")); + assertNull(augmentingTestGroupingLeaf2); + testGroupingLeaf = (LeafSchemaNode) testGroupingSubContainer.getDataChildByName( + QName.create(testModule.getQNameModule(), "test-grouping-leaf")); + assertNull(testGroupingLeaf); + } +} diff --git a/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/bar.yang b/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/bar.yang new file mode 100644 index 0000000000..cbe1ab9e71 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/bar.yang @@ -0,0 +1,10 @@ +module bar { + namespace "bar-namespace"; + prefix "bar-prefix"; + + container bar-cont { + leaf bar-cont-leaf { + type string; + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/foo.yang b/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/foo.yang new file mode 100644 index 0000000000..1688a31d83 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/foo.yang @@ -0,0 +1,125 @@ +module foo { + namespace "foo-namespace"; + prefix "foo-prefix"; + + import bar { + prefix br; + } + + container test-container-a { + if-feature foo-feature; + + leaf test-leaf-a { + type string; + } + } + + container test-container-b { + if-feature test-feature-1; + + leaf test-leaf-b { + type string; + } + } + + container test-container-c { + if-feature test-feature-1; + if-feature test-feature-2; + if-feature test-feature-3; + + leaf test-leaf-c { + type string; + } + } + + container test-container-d { + if-feature test-feature-1; + if-feature test-feature-2; + if-feature foo-feature; + if-feature test-feature-3; + + leaf test-leaf-d { + type string; + } + } + + container test-container-e { + container test-subcontainer-e { + leaf test-leaf-e { + if-feature foo-feature; + type string; + } + } + } + + container test-container-f { + container test-subcontainer-f { + if-feature foo-feature; + container test-subsubcontainer-f { + leaf test-leaf-f { + type string; + } + } + } + } + + container test-container-g { + leaf test-leaf-g { + type string; + } + } + + container test-container-h { + uses test-grouping { + if-feature "foo-feature"; + } + } + + container test-container-i { + uses test-grouping; + } + + container test-container-j { + if-feature br:imp-feature; + + leaf test-leaf-j { + type string; + } + } + + container test-container-k { + uses test-grouping { + augment "test-grouping-subcontainer" { + leaf augmenting-test-grouping-leaf { + if-feature test-feature-1; + type string; + } + + leaf augmenting-test-grouping-leaf-2 { + if-feature foo-feature; + type string; + } + } + } + } + + augment "/test-container-g" { + if-feature foo-feature; + leaf augmenting-test-leaf-g { + type string; + } + } + + augment "/test-container-g" { + anyxml augmenting-test-anyxml-g; + } + + grouping test-grouping { + container test-grouping-subcontainer { + leaf test-grouping-leaf { + if-feature foo-feature; + type string; + } + } + } +} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/shared-schema-repository/foobar.yang b/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/shared-schema-repository/foobar.yang new file mode 100644 index 0000000000..d839150ab4 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/if-feature-resolution-test/shared-schema-repository/foobar.yang @@ -0,0 +1,26 @@ +module foobar { + namespace "foobar-namespace"; + prefix "foobar-prefix"; + + container test-container-a { + if-feature test-feature-1; + + leaf test-leaf-a { + type string; + } + } + + container test-container-b { + if-feature foobar-feature; + + leaf test-leaf-b { + type string; + } + } + + container test-container-c { + leaf test-leaf-c { + type string; + } + } +} \ No newline at end of file -- 2.36.6