X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Frfc6020%2FAugmentStatementImpl.java;h=6a2d471f1ccad4f49e7d93c9a938b0065097b23f;hb=04fa25a4fe8957f6492618aa9a1e9a4f9af39df4;hp=54dd02353de6eef7e5ca57ee4dede45965284a56;hpb=bcb500b00c6b24089ef8a949625ad477c34f91ae;p=yangtools.git 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 54dd02353d..6a2d471f1c 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 @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the @@ -7,55 +7,83 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; -import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EFFECTIVE_MODEL; - +import static org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator.MAX; +import com.google.common.base.Preconditions; import java.util.Collection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.regex.Pattern; import javax.annotation.Nonnull; - import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; 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.SchemaNodeIdentifier; +import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder; +import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; 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.source.SourceException; +import org.opendaylight.yangtools.yang.parser.spi.source.StmtOrderingNamespace; import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AugmentEffectiveStatementImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class AugmentStatementImpl extends AbstractDeclaredStatement implements AugmentStatement { - private static final Logger LOG = LoggerFactory.getLogger(AugmentStatementImpl.class); - - protected AugmentStatementImpl(StmtContext context) { + 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) + .add(Rfc6020Mapping.ANYXML, 0, MAX) + .add(Rfc6020Mapping.CASE, 0, MAX) + .add(Rfc6020Mapping.CHOICE, 0, MAX) + .add(Rfc6020Mapping.CONTAINER, 0, MAX) + .add(Rfc6020Mapping.DESCRIPTION, 0, 1) + .add(Rfc6020Mapping.IF_FEATURE, 0, MAX) + .add(Rfc6020Mapping.LEAF, 0, MAX) + .add(Rfc6020Mapping.LEAF_LIST, 0, MAX) + .add(Rfc6020Mapping.LIST, 0, MAX) + .add(Rfc6020Mapping.REFERENCE, 0, 1) + .add(Rfc6020Mapping.STATUS, 0, 1) + .add(Rfc6020Mapping.USES, 0, MAX) + .add(Rfc6020Mapping.WHEN, 0, 1) + .build(); + + protected AugmentStatementImpl(final StmtContext context) { super(context); } - public static class Definition extends AbstractStatementSupport> { + public static class Definition extends + AbstractStatementSupport> { public Definition() { super(Rfc6020Mapping.AUGMENT); } @Override - public SchemaNodeIdentifier parseArgumentValue(StmtContext ctx, String value) throws SourceException { - return SchemaNodeIdentifier.create(AugmentUtils.parseAugmentPath(ctx, value), Utils.isXPathAbsolute(value)); + 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"); + + return Utils.nodeIdentifierFromPath(ctx, value); } @Override - public AugmentStatement createDeclared(StmtContext ctx) { + public AugmentStatement createDeclared( + final StmtContext ctx) { return new AugmentStatementImpl(ctx); } @Override public EffectiveStatement createEffective( - StmtContext> ctx) { + final StmtContext> ctx) { return new AugmentEffectiveStatementImpl(ctx); } @@ -63,35 +91,70 @@ public class AugmentStatementImpl extends AbstractDeclaredStatement> augmentNode) throws SourceException { - - final ModelActionBuilder augmentAction = augmentNode.newInferenceAction(EFFECTIVE_MODEL); - final ModelActionBuilder.Prerequisite>> sourceCtxPrereq = augmentAction - .requiresCtx(augmentNode, ModelProcessingPhase.FULL_DECLARATION); - + SUBSTATEMENT_VALIDATOR.validate(augmentNode); + + if (StmtContextUtils.isInExtensionBody(augmentNode)) { + return; + } + + final ModelActionBuilder augmentAction = augmentNode.newInferenceAction( + ModelProcessingPhase.EFFECTIVE_MODEL); + final ModelActionBuilder.Prerequisite>> sourceCtxPrereq = + augmentAction.requiresCtx(augmentNode, ModelProcessingPhase.EFFECTIVE_MODEL); + final Prerequisite>> target = + augmentAction.mutatesEffectiveCtx(getSearchRoot(augmentNode), SchemaNodeIdentifierBuildNamespace.class, augmentNode.getStatementArgument()); augmentAction.apply(new ModelActionBuilder.InferenceAction() { @Override - public void apply() throws InferenceException { - - final StatementContextBase augmentTargetCtx = AugmentUtils.getAugmentTargetCtx(augmentNode); - final StatementContextBase augmentSourceCtx = (StatementContextBase) sourceCtxPrereq.get(); + public void apply() { + final StatementContextBase augmentTargetCtx = (StatementContextBase) target.get(); + if (!AugmentUtils.isSupportedAugmentTarget(augmentTargetCtx) || StmtContextUtils.isInExtensionBody(augmentTargetCtx)) { + augmentNode.setIsSupportedToBuildEffective(false); + return; + } + // FIXME: this is a workaround for models which augment a node which is added via an extension + // which we do not handle. This needs to be reworked in terms of unknown schema nodes. + final StatementContextBase augmentSourceCtx = (StatementContextBase) augmentNode; try { AugmentUtils.copyFromSourceToTarget(augmentSourceCtx, augmentTargetCtx); + augmentTargetCtx.addEffectiveSubstatement(augmentSourceCtx); + updateAugmentOrder(augmentSourceCtx); } catch (SourceException e) { - LOG.warn(e.getMessage(), e); + LOG.warn("Failed to add augmentation %s defined at {}", + augmentSourceCtx.getStatementSourceReference(), e); } } - @Override - public void prerequisiteFailed(final Collection> failed) - throws InferenceException { - if (failed.contains(augmentAction)) { - throw new InferenceException("Augment action failed", augmentNode.getStatementSourceReference()); + private void updateAugmentOrder(final StatementContextBase augmentSourceCtx) { + Integer currentOrder = augmentSourceCtx.getFromNamespace(StmtOrderingNamespace.class, + Rfc6020Mapping.AUGMENT); + if (currentOrder == null) { + currentOrder = 1; + } else { + currentOrder++; } + + augmentSourceCtx.setOrder(currentOrder); + augmentSourceCtx.addToNs(StmtOrderingNamespace.class, Rfc6020Mapping.AUGMENT, currentOrder); + } + + @Override + public void prerequisiteFailed(final Collection> failed) { + throw new InferenceException(augmentNode.getStatementSourceReference(), + "Augment target '%s' not found", augmentNode.getStatementArgument()); } }); } + + private static Mutable getSearchRoot(final Mutable augmentContext) { + Mutable parent = augmentContext.getParentContext(); + // Augment is in uses - we need to augment instantiated nodes in parent. + if (Rfc6020Mapping.USES.equals(parent.getPublicDefinition())) { + return parent.getParentContext(); + } + return parent; + } } @Nonnull