*/
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
-import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+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.model.api.stmt.AugmentStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement;
private static final Pattern PATH_REL_PATTERN1 = Pattern.compile("\\.\\.?\\s*/(.+)");
private static final Pattern PATH_REL_PATTERN2 = Pattern.compile("//.*");
private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator
- .builder(Rfc6020Mapping.AUGMENT)
- .addAny(Rfc6020Mapping.ANYXML)
- .addAny(Rfc6020Mapping.CASE)
- .addAny(Rfc6020Mapping.CHOICE)
- .addAny(Rfc6020Mapping.CONTAINER)
- .addOptional(Rfc6020Mapping.DESCRIPTION)
- .addAny(Rfc6020Mapping.IF_FEATURE)
- .addAny(Rfc6020Mapping.LEAF)
- .addAny(Rfc6020Mapping.LEAF_LIST)
- .addAny(Rfc6020Mapping.LIST)
- .addOptional(Rfc6020Mapping.REFERENCE)
- .addOptional(Rfc6020Mapping.STATUS)
- .addAny(Rfc6020Mapping.USES)
- .addOptional(Rfc6020Mapping.WHEN)
+ .builder(YangStmtMapping.AUGMENT)
+ .addAny(YangStmtMapping.ANYXML)
+ .addAny(YangStmtMapping.CASE)
+ .addAny(YangStmtMapping.CHOICE)
+ .addAny(YangStmtMapping.CONTAINER)
+ .addOptional(YangStmtMapping.DESCRIPTION)
+ .addAny(YangStmtMapping.IF_FEATURE)
+ .addAny(YangStmtMapping.LEAF)
+ .addAny(YangStmtMapping.LEAF_LIST)
+ .addAny(YangStmtMapping.LIST)
+ .addOptional(YangStmtMapping.REFERENCE)
+ .addOptional(YangStmtMapping.STATUS)
+ .addAny(YangStmtMapping.USES)
+ .addOptional(YangStmtMapping.WHEN)
.build();
protected AugmentStatementImpl(final StmtContext<SchemaNodeIdentifier, AugmentStatement, ?> context) {
AbstractStatementSupport<SchemaNodeIdentifier, AugmentStatement, EffectiveStatement<SchemaNodeIdentifier, AugmentStatement>> {
public Definition() {
- super(Rfc6020Mapping.AUGMENT);
+ super(YangStmtMapping.AUGMENT);
}
@Override
public SchemaNodeIdentifier parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
- Preconditions.checkArgument(!PATH_REL_PATTERN1.matcher(value).matches()
- && !PATH_REL_PATTERN2.matcher(value).matches(),
- "An argument for augment can be only absolute path; or descendant if used in uses");
+ SourceException.throwIf(PATH_REL_PATTERN1.matcher(value).matches()
+ || PATH_REL_PATTERN2.matcher(value).matches(), ctx.getStatementSourceReference(),
+ "Augment argument \'%s\' is not valid, it can be only absolute path; or descendant if used in uses",
+ value);
return Utils.nodeIdentifierFromPath(ctx, value);
}
return;
}
- SUBSTATEMENT_VALIDATOR.validate(augmentNode);
+ super.onFullDefinitionDeclared(augmentNode);
if (StmtContextUtils.isInExtensionBody(augmentNode)) {
return;
/**
* Marks case short hand in augment
*/
- if (augmentTargetCtx.getPublicDefinition() == Rfc6020Mapping.CHOICE) {
- augmentNode.addToNs(AugmentToChoiceNamespace.class, augmentNode, true);
+ if (augmentTargetCtx.getPublicDefinition() == YangStmtMapping.CHOICE) {
+ augmentNode.addToNs(AugmentToChoiceNamespace.class, augmentNode, Boolean.TRUE);
}
// FIXME: this is a workaround for models which augment a node which is added via an extension
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);
}
private void updateAugmentOrder(final StatementContextBase<?, ?, ?> augmentSourceCtx) {
Integer currentOrder = augmentSourceCtx.getFromNamespace(StmtOrderingNamespace.class,
- Rfc6020Mapping.AUGMENT);
+ YangStmtMapping.AUGMENT);
if (currentOrder == null) {
currentOrder = 1;
} else {
}
augmentSourceCtx.setOrder(currentOrder);
- augmentSourceCtx.addToNs(StmtOrderingNamespace.class, Rfc6020Mapping.AUGMENT, currentOrder);
+ augmentSourceCtx.addToNs(StmtOrderingNamespace.class, YangStmtMapping.AUGMENT, currentOrder);
}
@Override
/*
* Do not fail, if it is an uses-augment to an unknown node.
*/
- if (Rfc6020Mapping.USES == augmentNode.getParentContext().getPublicDefinition()) {
+ if (YangStmtMapping.USES == augmentNode.getParentContext().getPublicDefinition()) {
final StatementContextBase<?, ?, ?> targetNode = Utils.findNode(getSearchRoot(augmentNode),
augmentNode.getStatementArgument());
if (Utils.isUnknownNode(targetNode)) {
private static Mutable<?, ?, ?> getSearchRoot(final Mutable<?, ?, ?> augmentContext) {
final Mutable<?, ?, ?> parent = augmentContext.getParentContext();
// Augment is in uses - we need to augment instantiated nodes in parent.
- if (Rfc6020Mapping.USES == parent.getPublicDefinition()) {
+ if (YangStmtMapping.USES == parent.getPublicDefinition()) {
return parent.getParentContext();
}
return parent;
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();
for (final StatementContextBase<?, ?, ?> originalStmtCtx : declared) {
if (StmtContextUtils.areFeaturesSupported(originalStmtCtx)) {
- copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer);
+ copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer, skipCheckOfMandatoryNodes);
}
}
for (final StatementContextBase<?, ?, ?> originalStmtCtx : effective) {
- copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer);
+ copyStatement(originalStmtCtx, targetCtx, typeOfCopy, buffer, skipCheckOfMandatoryNodes);
}
targetCtx.addEffectiveSubstatements(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 StatementContextBase<?, ?, ?> ctx) {
+ return ctx.getPublicDefinition() == YangStmtMapping.AUGMENT
+ && StmtContextUtils.findFirstSubstatement(ctx, WhenStatement.class) != null;
+ }
+
private static void copyStatement(final StatementContextBase<?, ?, ?> original,
final StatementContextBase<?, ?, ?> target, final CopyType typeOfCopy,
- final Collection<StatementContextBase<?, ?, ?>> buffer) {
+ final Collection<StatementContextBase<?, ?, ?>> buffer, final boolean skipCheckOfMandatoryNodes) {
if (needToCopyByAugment(original)) {
- validateNodeCanBeCopiedByAugment(original, target, typeOfCopy);
+ validateNodeCanBeCopiedByAugment(original, target, typeOfCopy, skipCheckOfMandatoryNodes);
final StatementContextBase<?, ?, ?> copy = original.createCopy(target, typeOfCopy);
buffer.add(copy);
}
private static void validateNodeCanBeCopiedByAugment(final StatementContextBase<?, ?, ?> sourceCtx,
- final StatementContextBase<?, ?, ?> targetCtx, final CopyType typeOfCopy) {
+ 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);
}
* b) added to augment body also via uses of a grouping and
* such sub-statements are stored in effective sub-statements collection.
*/
- for (final StatementContextBase<?, ?, ?> sourceSubStatement : Iterables.concat(
- sourceCtx.declaredSubstatements(), sourceCtx.declaredSubstatements())) {
- checkForMandatoryNodes(sourceSubStatement);
- }
+ sourceCtx.declaredSubstatements().forEach(Definition::checkForMandatoryNodes);
+ sourceCtx.effectiveSubstatements().forEach(Definition::checkForMandatoryNodes);
}
InferenceException.throwIf(StmtContextUtils.isMandatoryNode(sourceCtx),
*/
if (!Utils.belongsToTheSameModule(targetStmtQName, sourceStmtQName)) {
return true;
- } else {
- /*
- * If target or one of its parent is a presence container from
- * the same module, return false and skip mandatory nodes
- * validation
- */
- if (StmtContextUtils.isPresenceContainer(targetCtx)) {
- return false;
- }
+ }
+
+ /*
+ * 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)
+ || StmtContextUtils.isNotMandatoryNodeOfType(targetCtx, YangStmtMapping.CHOICE)
+ || StmtContextUtils.isNotMandatoryNodeOfType(targetCtx, YangStmtMapping.LIST)) {
+ return false;
}
} while ((targetCtx = targetCtx.getParentContext()) != root);
return false;
}
- private static final Set<Rfc6020Mapping> NOCOPY_DEF_SET = ImmutableSet.of(Rfc6020Mapping.USES, Rfc6020Mapping.WHEN,
- Rfc6020Mapping.DESCRIPTION, Rfc6020Mapping.REFERENCE, Rfc6020Mapping.STATUS);
+ private static final Set<YangStmtMapping> NOCOPY_DEF_SET = ImmutableSet.of(YangStmtMapping.USES, YangStmtMapping.WHEN,
+ YangStmtMapping.DESCRIPTION, YangStmtMapping.REFERENCE, YangStmtMapping.STATUS);
public static boolean needToCopyByAugment(final StmtContext<?, ?, ?> stmtContext) {
return !NOCOPY_DEF_SET.contains(stmtContext.getPublicDefinition());
}
- private static final Set<Rfc6020Mapping> REUSED_DEF_SET = ImmutableSet.of(Rfc6020Mapping.TYPEDEF);
+ private static final Set<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(YangStmtMapping.TYPEDEF);
public static boolean isReusedByAugment(final StmtContext<?, ?, ?> stmtContext) {
return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
|| allowedAugmentTargets.contains(substatementCtx.getPublicDefinition());
}
+ @Override
+ protected SubstatementValidator getSubstatementValidator() {
+ return SUBSTATEMENT_VALIDATOR;
+ }
+
}
@Nonnull
return argument();
}
+ @Nonnull
@Override
public Collection<? extends DataDefinitionStatement> getDataDefinitions() {
return allDeclared(DataDefinitionStatement.class);
}
+
+ @Nonnull
+ @Override
+ public Collection<? extends ActionStatement> getActions() {
+ return allDeclared(ActionStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends NotificationStatement> getNotifications() {
+ return allDeclared(NotificationStatement.class);
+ }
}