package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
import com.google.common.base.Verify;
-import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ActionStatement;
import org.opendaylight.yangtools.yang.parser.spi.source.StmtOrderingNamespace;
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.RootStatementContext;
import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AugmentEffectiveStatementImpl;
import org.slf4j.Logger;
@Override
public void onFullDefinitionDeclared(
- final StmtContext.Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
- if (!StmtContextUtils.areFeaturesSupported(augmentNode)) {
+ final Mutable<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> augmentNode) {
+ if (!augmentNode.isSupportedByFeatures()) {
return;
}
augmentAction.apply(new ModelActionBuilder.InferenceAction() {
@Override
- public void apply() {
- final StatementContextBase<?, ?, ?> augmentTargetCtx = (StatementContextBase<?, ?, ?>) target.get();
+ public void apply(final ModelActionBuilder.InferenceContext ctx) {
+ final StatementContextBase<?, ?, ?> augmentTargetCtx =
+ (StatementContextBase<?, ?, ?>) target.resolve(ctx);
if (!isSupportedAugmentTarget(augmentTargetCtx)
|| StmtContextUtils.isInExtensionBody(augmentTargetCtx)) {
augmentNode.setIsSupportedToBuildEffective(false);
augmentTargetCtx.addEffectiveSubstatement(augmentSourceCtx);
updateAugmentOrder(augmentSourceCtx);
} catch (final SourceException e) {
- LOG.debug("Failed to add augmentation {} defined at {}",
+ LOG.warn("Failed to add augmentation {} defined at {}",
augmentTargetCtx.getStatementSourceReference(),
augmentSourceCtx.getStatementSourceReference(), e);
}
final CopyType typeOfCopy = UsesStatement.class.equals(sourceCtx.getParentContext().getPublicDefinition()
.getDeclaredRepresentationClass()) ? CopyType.ADDED_BY_USES_AUGMENTATION
: CopyType.ADDED_BY_AUGMENTATION;
+ /*
+ * Since Yang 1.1, if an augmentation is made conditional with a
+ * "when" statement, it is allowed to add mandatory nodes.
+ */
+ final boolean skipCheckOfMandatoryNodes = YangVersion.VERSION_1_1.equals(sourceCtx.getRootVersion())
+ && isConditionalAugmentStmt(sourceCtx);
- final Collection<StatementContextBase<?, ?, ?>> declared = sourceCtx.declaredSubstatements();
- final Collection<StatementContextBase<?, ?, ?>> effective = sourceCtx.effectiveSubstatements();
- final Collection<StatementContextBase<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
+ final Collection<? extends Mutable<?, ?, ?>> declared = sourceCtx.mutableDeclaredSubstatements();
+ final Collection<? extends Mutable<?, ?, ?>> effective = sourceCtx.mutableEffectiveSubstatements();
+ final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
- for (final StatementContextBase<?, ?, ?> originalStmtCtx : declared) {
- if (StmtContextUtils.areFeaturesSupported(originalStmtCtx)) {
- copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer);
+ for (final Mutable<?, ?, ?> originalStmtCtx : declared) {
+ if (originalStmtCtx.isSupportedByFeatures()) {
+ copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer, skipCheckOfMandatoryNodes);
}
}
- for (final StatementContextBase<?, ?, ?> originalStmtCtx : effective) {
- copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer);
+ for (final Mutable<?, ?, ?> originalStmtCtx : effective) {
+ copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer, skipCheckOfMandatoryNodes);
}
targetCtx.addEffectiveSubstatements(buffer);
}
- private static void copyStatement(final StatementContextBase<?, ?, ?> original,
- final StatementContextBase<?, ?, ?> target, final CopyType typeOfCopy,
- final Collection<StatementContextBase<?, ?, ?>> buffer) {
+ /**
+ * Checks whether supplied statement context is conditional augment
+ * statement.
+ *
+ * @param ctx
+ * statement context to be checked
+ *
+ * @return true if supplied statement context is conditional augment
+ * statement, otherwise false
+ */
+ private static boolean isConditionalAugmentStmt(final StmtContext<?, ?, ?> ctx) {
+ return ctx.getPublicDefinition() == YangStmtMapping.AUGMENT
+ && StmtContextUtils.findFirstSubstatement(ctx, WhenStatement.class) != null;
+ }
+
+ private static void copyStatement(final Mutable<?, ?, ?> original, final StatementContextBase<?, ?, ?> target,
+ final CopyType typeOfCopy, final Collection<Mutable<?, ?, ?>> buffer,
+ final boolean skipCheckOfMandatoryNodes) {
if (needToCopyByAugment(original)) {
- validateNodeCanBeCopiedByAugment(original, target, typeOfCopy);
+ validateNodeCanBeCopiedByAugment(original, target, typeOfCopy, skipCheckOfMandatoryNodes);
- final StatementContextBase<?, ?, ?> copy = original.createCopy(target, typeOfCopy);
+ final Mutable<?, ?, ?> copy = original.createCopy(target, typeOfCopy);
buffer.add(copy);
} else if (isReusedByAugment(original)) {
buffer.add(original);
}
}
- private static void validateNodeCanBeCopiedByAugment(final StatementContextBase<?, ?, ?> sourceCtx,
- final StatementContextBase<?, ?, ?> targetCtx, final CopyType typeOfCopy) {
+ private static void validateNodeCanBeCopiedByAugment(final StmtContext<?, ?, ?> sourceCtx,
+ final StatementContextBase<?, ?, ?> targetCtx, final CopyType typeOfCopy,
+ final boolean skipCheckOfMandatoryNodes) {
if (WhenStatement.class.equals(sourceCtx.getPublicDefinition().getDeclaredRepresentationClass())) {
return;
}
- if (typeOfCopy == CopyType.ADDED_BY_AUGMENTATION && reguiredCheckOfMandatoryNodes(sourceCtx, targetCtx)) {
+ if (!skipCheckOfMandatoryNodes && typeOfCopy == CopyType.ADDED_BY_AUGMENTATION
+ && reguiredCheckOfMandatoryNodes(sourceCtx, targetCtx)) {
checkForMandatoryNodes(sourceCtx);
}
- final List<StatementContextBase<?, ?, ?>> targetSubStatements = new Builder<StatementContextBase<?, ?, ?>>()
- .addAll(targetCtx.declaredSubstatements()).addAll(targetCtx.effectiveSubstatements()).build();
-
- for (final StatementContextBase<?, ?, ?> subStatement : targetSubStatements) {
+ final List<Mutable<?, ?, ?>> targetSubStatements = ImmutableList.<Mutable<?, ?, ?>>builder()
+ .addAll(targetCtx.mutableDeclaredSubstatements()).addAll(targetCtx.mutableEffectiveSubstatements())
+ .build();
+ for (final Mutable<?, ?, ?> subStatement : targetSubStatements) {
final boolean sourceIsDataNode = DataDefinitionStatement.class.isAssignableFrom(sourceCtx
.getPublicDefinition().getDeclaredRepresentationClass());
final boolean targetIsDataNode = DataDefinitionStatement.class.isAssignableFrom(subStatement
}
}
- private static void checkForMandatoryNodes(final StatementContextBase<?, ?, ?> sourceCtx) {
+ private static void checkForMandatoryNodes(final StmtContext<?, ?, ?> sourceCtx) {
if (StmtContextUtils.isNonPresenceContainer(sourceCtx)) {
/*
* We need to iterate over both declared and effective sub-statements,
sourceCtx.rawStatementArgument());
}
- private static boolean reguiredCheckOfMandatoryNodes(final StatementContextBase<?, ?, ?> sourceCtx,
- StatementContextBase<?, ?, ?> targetCtx) {
+ private static boolean reguiredCheckOfMandatoryNodes(final StmtContext<?, ?, ?> sourceCtx,
+ Mutable<?, ?, ?> targetCtx) {
/*
* If the statement argument is not QName, it cannot be mandatory
* statement, therefore return false and skip mandatory nodes validation
}
final QName sourceStmtQName = (QName) sourceCtx.getStatementArgument();
- final RootStatementContext<?, ?, ?> root = targetCtx.getRoot();
+ // RootStatementContext, for example
+ final Mutable<?, ?, ?> root = targetCtx.getRoot();
do {
Verify.verify(targetCtx.getStatementArgument() instanceof QName,
"Argument of augment target statement must be QName.");
}
/*
- * If target or one of its parent is a presence container from
- * the same module, return false and skip mandatory nodes
- * validation
+ * If target or one of the target's ancestors from the same namespace
+ * is a presence container
+ * or is non-mandatory choice
+ * or is non-mandatory list
+ * return false and skip mandatory nodes validation, because these nodes
+ * are not mandatory node containers according to RFC 6020 section 3.1.
*/
- if (StmtContextUtils.isPresenceContainer(targetCtx)) {
+ if (StmtContextUtils.isPresenceContainer(targetCtx)
+ || StmtContextUtils.isNotMandatoryNodeOfType(targetCtx, YangStmtMapping.CHOICE)
+ || StmtContextUtils.isNotMandatoryNodeOfType(targetCtx, YangStmtMapping.LIST)) {
return false;
}
} while ((targetCtx = targetCtx.getParentContext()) != root);
return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
}
- static boolean isSupportedAugmentTarget(final StatementContextBase<?, ?, ?> substatementCtx) {
-
+ static boolean isSupportedAugmentTarget(final StmtContext<?, ?, ?> substatementCtx) {
/*
* :TODO Substatement must be allowed augment target type e.g.
* Container, etc... and must not be for example grouping, identity etc.
* the same QName. We must find the Container and the Grouping must be
* ignored as disallowed augment target.
*/
-
- final Collection<?> allowedAugmentTargets = substatementCtx.getFromNamespace(ValidationBundlesNamespace.class,
- ValidationBundleType.SUPPORTED_AUGMENT_TARGETS);
+ final Collection<?> allowedAugmentTargets = substatementCtx.getFromNamespace(
+ ValidationBundlesNamespace.class, ValidationBundleType.SUPPORTED_AUGMENT_TARGETS);
// if no allowed target is returned we consider all targets allowed
return allowedAugmentTargets == null || allowedAugmentTargets.isEmpty()
protected SubstatementValidator getSubstatementValidator() {
return SUBSTATEMENT_VALIDATOR;
}
-
}
@Nonnull