import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.common.Empty;
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.meta.StatementDefinition;
-import org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces;
import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
@Override
final boolean computeSupportedByFeatures() {
// If the set of supported features has not been provided, all features are supported by default.
- final var supportedFeatures = namespaceItem(ParserNamespaces.SUPPORTED_FEATURES, Empty.value());
- return supportedFeatures == null || StmtContextUtils.checkFeatureSupport(this, supportedFeatures);
+ return StmtContextUtils.evaluateIfFeatures(this);
}
@Override
import org.opendaylight.yangtools.yang.parser.spi.meta.BoundStmtCtx;
import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
@Beta
-public final class RefineStatementSupport
+public abstract sealed class RefineStatementSupport
extends AbstractStatementSupport<Descendant, RefineStatement, RefineEffectiveStatement> {
- private static final SubstatementValidator RFC6020_VALIDATOR = SubstatementValidator.builder(YangStmtMapping.REFINE)
- .addOptional(YangStmtMapping.DEFAULT)
- .addOptional(YangStmtMapping.DESCRIPTION)
- .addOptional(YangStmtMapping.REFERENCE)
- .addOptional(YangStmtMapping.CONFIG)
- .addOptional(YangStmtMapping.MANDATORY)
- .addOptional(YangStmtMapping.PRESENCE)
- .addAny(YangStmtMapping.MUST)
- .addOptional(YangStmtMapping.MIN_ELEMENTS)
- .addOptional(YangStmtMapping.MAX_ELEMENTS)
- .build();
- private static final SubstatementValidator RFC7950_VALIDATOR = SubstatementValidator.builder(YangStmtMapping.REFINE)
- .addOptional(YangStmtMapping.DEFAULT)
- .addOptional(YangStmtMapping.DESCRIPTION)
- .addOptional(YangStmtMapping.REFERENCE)
- .addOptional(YangStmtMapping.CONFIG)
- .addAny(YangStmtMapping.IF_FEATURE)
- .addOptional(YangStmtMapping.MANDATORY)
- .addOptional(YangStmtMapping.PRESENCE)
- .addAny(YangStmtMapping.MUST)
- .addOptional(YangStmtMapping.MIN_ELEMENTS)
- .addOptional(YangStmtMapping.MAX_ELEMENTS)
- .build();
+ private static final class Rfc6020 extends RefineStatementSupport {
+ private static final SubstatementValidator VALIDATOR = SubstatementValidator.builder(YangStmtMapping.REFINE)
+ .addOptional(YangStmtMapping.DEFAULT)
+ .addOptional(YangStmtMapping.DESCRIPTION)
+ .addOptional(YangStmtMapping.REFERENCE)
+ .addOptional(YangStmtMapping.CONFIG)
+ .addOptional(YangStmtMapping.MANDATORY)
+ .addOptional(YangStmtMapping.PRESENCE)
+ .addAny(YangStmtMapping.MUST)
+ .addOptional(YangStmtMapping.MIN_ELEMENTS)
+ .addOptional(YangStmtMapping.MAX_ELEMENTS)
+ .build();
+
+ Rfc6020(final YangParserConfiguration config) {
+ super(config, VALIDATOR);
+ }
+ }
+
+ private static final class Rfc7950 extends RefineStatementSupport {
+ private static final SubstatementValidator VALIDATOR = SubstatementValidator.builder(YangStmtMapping.REFINE)
+ .addOptional(YangStmtMapping.DEFAULT)
+ .addOptional(YangStmtMapping.DESCRIPTION)
+ .addOptional(YangStmtMapping.REFERENCE)
+ .addOptional(YangStmtMapping.CONFIG)
+ .addAny(YangStmtMapping.IF_FEATURE)
+ .addOptional(YangStmtMapping.MANDATORY)
+ .addOptional(YangStmtMapping.PRESENCE)
+ .addAny(YangStmtMapping.MUST)
+ .addOptional(YangStmtMapping.MIN_ELEMENTS)
+ .addOptional(YangStmtMapping.MAX_ELEMENTS)
+ .build();
+
+ Rfc7950(final YangParserConfiguration config) {
+ super(config, VALIDATOR);
+ }
+
+ @Override
+ public void onFullDefinitionDeclared(
+ final Mutable<Descendant, RefineStatement, RefineEffectiveStatement> stmt) {
+ super.onFullDefinitionDeclared(stmt);
+
+ if (!StmtContextUtils.evaluateIfFeatures(stmt)) {
+ stmt.setUnsupported();
+ }
+ }
+ }
private RefineStatementSupport(final YangParserConfiguration config, final SubstatementValidator validator) {
super(YangStmtMapping.REFINE, StatementPolicy.reject(), config, validator);
}
public static @NonNull RefineStatementSupport rfc6020Instance(final YangParserConfiguration config) {
- return new RefineStatementSupport(config, RFC6020_VALIDATOR);
+ return new Rfc6020(config);
}
public static @NonNull RefineStatementSupport rfc7950Instance(final YangParserConfiguration config) {
- return new RefineStatementSupport(config, RFC7950_VALIDATOR);
+ return new Rfc7950(config);
}
@Override
- public Descendant parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+ public final Descendant parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
return ArgumentUtils.parseDescendantSchemaNodeIdentifier(ctx, value);
}
@Override
- protected RefineStatement createDeclared(final BoundStmtCtx<Descendant> ctx,
+ protected final RefineStatement createDeclared(final BoundStmtCtx<Descendant> ctx,
final ImmutableList<DeclaredStatement<?>> substatements) {
return DeclaredStatements.createRefine(ctx.getRawArgument(), ctx.getArgument(), substatements);
}
@Override
- protected RefineStatement attachDeclarationReference(final RefineStatement stmt,
+ protected final RefineStatement attachDeclarationReference(final RefineStatement stmt,
final DeclarationReference reference) {
return DeclaredStatementDecorators.decorateRefine(stmt, reference);
}
@Override
- protected RefineEffectiveStatement createEffective(final Current<Descendant, RefineStatement> stmt,
+ protected final RefineEffectiveStatement createEffective(final Current<Descendant, RefineStatement> stmt,
final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
// Empty refine is exceedingly unlikely: let's be lazy and reuse the implementation
return new RefineEffectiveStatementImpl(stmt.declared(), substatements,
import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
+import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.RefineEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesEffectiveStatement;
copyFromSourceToTarget(sourceGrpStmtCtx, targetNodeStmtCtx, usesNode);
// Apply any refine statements
- for (var subStmtCtx : usesNode.mutableDeclaredSubstatements()) {
- if (subStmtCtx.producesDeclared(RefineStatement.class) && areFeaturesSupported(subStmtCtx)) {
- performRefine(subStmtCtx, targetNodeStmtCtx);
+ for (var subStmt : usesNode.mutableDeclaredSubstatements()) {
+ if (subStmt.producesDeclared(RefineStatement.class) && subStmt.isSupportedToBuildEffective()) {
+ performRefine(subStmt, targetNodeStmtCtx);
}
}
return null;
}
- private static boolean areFeaturesSupported(final StmtContext<?, ?, ?> subStmtCtx) {
- /*
- * In case of Yang 1.1, checks whether features are supported.
- */
- return !YangVersion.VERSION_1_1.equals(subStmtCtx.yangVersion()) || subStmtCtx.isSupportedByFeatures();
- }
-
- private static void performRefine(final Mutable<?, ?, ?> subStmtCtx, final StmtContext<?, ?, ?> usesParentCtx) {
- final Object refineArgument = subStmtCtx.argument();
- if (!(refineArgument instanceof SchemaNodeIdentifier refineTarget)) {
- throw new InferenceException(subStmtCtx,
+ private static void performRefine(final Mutable<?, ?, ?> refineStmtCtx, final StmtContext<?, ?, ?> usesParentCtx) {
+ final Object refineArgument = refineStmtCtx.argument();
+ if (!(refineArgument instanceof Descendant refineDescendant)) {
+ throw new InferenceException(refineStmtCtx,
"Invalid refine argument %s. It must be instance of SchemaNodeIdentifier.", refineArgument);
}
// FIXME: this really should be handled via separate inference, i.e. we first instantiate the template and when
// it appears, this refine will trigger on it. This reinforces the FIXME below.
- final var optRefineTargetCtx = ParserNamespaces.findSchemaTreeStatement(usesParentCtx, refineTarget);
- InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx, "Refine target node %s not found.",
- refineTarget);
+ final var optRefineTargetCtx = ParserNamespaces.findSchemaTreeStatement(usesParentCtx, refineDescendant);
+ InferenceException.throwIf(!optRefineTargetCtx.isPresent(), refineStmtCtx, "Refine target node %s not found.",
+ refineDescendant);
// FIXME: This communicates the looked-up target node to RefineStatementSupport.buildEffective(). We should do
// this trick through a shared namespace or similar reactor-agnostic meeting place. It really feels like
// an inference action RefineStatementSupport should be doing.
- final var refineTargetNodeCtx = optRefineTargetCtx.orElseThrow();
- if (StmtContextUtils.isUnknownStatement(refineTargetNodeCtx)) {
+ final var refineTargetCtx = optRefineTargetCtx.orElseThrow();
+ if (StmtContextUtils.isUnknownStatement(refineTargetCtx)) {
LOG.trace("Refine node '{}' in uses '{}' has target node unknown statement '{}'. "
- + "Refine has been skipped. At line: {}", subStmtCtx.argument(),
- subStmtCtx.coerceParentContext().argument(), refineTargetNodeCtx.argument(),
- subStmtCtx.sourceReference());
+ + "Refine has been skipped. At line: {}", refineStmtCtx.argument(),
+ refineStmtCtx.coerceParentContext().argument(), refineTargetCtx.argument(),
+ refineStmtCtx.sourceReference());
+ } else if (refineTargetCtx instanceof Mutable<?, ?, ?> refineTarget) {
+ for (var refineSubstatementCtx : refineStmtCtx.declaredSubstatements()) {
+ if (isSupportedRefineSubstatement(refineSubstatementCtx)) {
+ addOrReplaceNode(refineSubstatementCtx, refineTarget);
+ }
+ }
} else {
- verify(refineTargetNodeCtx instanceof Mutable, "Unexpected target %s", refineTargetNodeCtx);
- addOrReplaceNodes(subStmtCtx, (Mutable<?, ?, ?>) refineTargetNodeCtx);
+ throw new VerifyException("Unexpected target " + refineTargetCtx);
}
// Target is a prerequisite for the 'refine', hence if the target is not supported, the refine is not supported
// as well. Otherwise add a pointer to the target into refine's local namespace.
- if (refineTargetNodeCtx.isSupportedToBuildEffective() && refineTargetNodeCtx.isSupportedByFeatures()) {
- subStmtCtx.addToNs(RefineTargetNamespace.INSTANCE, Empty.value(), refineTargetNodeCtx);
+ if (refineTargetCtx.isSupportedToBuildEffective() && refineTargetCtx.isSupportedByFeatures()) {
+ refineStmtCtx.addToNs(RefineTargetNamespace.INSTANCE, Empty.value(), refineTargetCtx);
} else {
- subStmtCtx.setUnsupported();
- }
- }
-
- private static void addOrReplaceNodes(final StmtContext<?, ?, ?> subStmtCtx,
- final Mutable<?, ?, ?> refineTargetNodeCtx) {
- for (StmtContext<?, ?, ?> refineSubstatementCtx : subStmtCtx.declaredSubstatements()) {
- if (isSupportedRefineSubstatement(refineSubstatementCtx)) {
- addOrReplaceNode(refineSubstatementCtx, refineTargetNodeCtx);
- }
+ refineStmtCtx.setUnsupported();
}
}
import java.util.Optional;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.Revision;
return UnknownStatement.class.isAssignableFrom(stmtCtx.publicDefinition().getDeclaredRepresentationClass());
}
+ /**
+ * Evaluate {@code if-feature} substatement of a statement and indicate whether they result in the statement being
+ * supported.
+ *
+ * @param stmt Parent statement
+ * @return {@code true} if the statement is indicated to be supported under currently-supported features
+ */
+ public static boolean evaluateIfFeatures(final @NonNull StmtContext<?, ?, ?> stmt) {
+ final var supportedFeatures = stmt.namespaceItem(ParserNamespaces.SUPPORTED_FEATURES, Empty.value());
+ return supportedFeatures == null || checkFeatureSupport(stmt, supportedFeatures);
+ }
+
public static boolean checkFeatureSupport(final StmtContext<?, ?, ?> stmtContext,
final FeatureSet supportedFeatures) {
boolean isSupported = false;