*/
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import java.util.Collection;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.DeviateKind;
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.DeviateStatement;
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.CopyType;
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.InferenceAction;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
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.meta.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModulesDeviatedByModules;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModulesDeviatedByModules.SupportedModules;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.DeviateEffectiveStatementImpl;
import org.slf4j.Logger;
public static class Definition extends AbstractStatementSupport<DeviateKind, DeviateStatement,
EffectiveStatement<DeviateKind, DeviateStatement>> {
+ private static final Map<String, DeviateKind> KEYWORD_TO_DEVIATE_MAP;
+ static {
+ final Builder<String, DeviateKind> keywordToDeviateMapBuilder = ImmutableMap.builder();
+ for (final DeviateKind deviate : DeviateKind.values()) {
+ keywordToDeviateMapBuilder.put(deviate.getKeyword(), deviate);
+ }
+ KEYWORD_TO_DEVIATE_MAP = keywordToDeviateMapBuilder.build();
+ }
private static final Set<YangStmtMapping> SINGLETON_STATEMENTS = ImmutableSet.of(
YangStmtMapping.UNITS, YangStmtMapping.CONFIG, YangStmtMapping.MANDATORY,
super(YangStmtMapping.DEVIATE);
}
- @Override public DeviateKind parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
- return Utils.parseDeviateFromString(ctx, value);
+ @Override
+ public DeviateKind parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+ return SourceException.throwIfNull(KEYWORD_TO_DEVIATE_MAP.get(value),
+ ctx.getStatementSourceReference(), "String '%s' is not valid deviate argument", value);
}
- @Override public DeviateStatement createDeclared(final StmtContext<DeviateKind, DeviateStatement, ?> ctx) {
+ @Override
+ public DeviateStatement createDeclared(final StmtContext<DeviateKind, DeviateStatement, ?> ctx) {
return new DeviateStatementImpl(ctx);
}
- @Override public EffectiveStatement<DeviateKind, DeviateStatement> createEffective(
+ @Override
+ public EffectiveStatement<DeviateKind, DeviateStatement> createEffective(
final StmtContext<DeviateKind, DeviateStatement, EffectiveStatement<DeviateKind,
DeviateStatement>> ctx) {
return new DeviateEffectiveStatementImpl(ctx);
}
@Override
- public void onFullDefinitionDeclared(final StmtContext.Mutable<DeviateKind, DeviateStatement,
+ public void onFullDefinitionDeclared(final Mutable<DeviateKind, DeviateStatement,
EffectiveStatement<DeviateKind, DeviateStatement>> deviateStmtCtx) {
final DeviateKind deviateKind = deviateStmtCtx.getStatementArgument();
getSubstatementValidatorForDeviate(deviateKind).validate(deviateStmtCtx);
- final ModelActionBuilder deviateAction = deviateStmtCtx.newInferenceAction(
- ModelProcessingPhase.EFFECTIVE_MODEL);
-
final SchemaNodeIdentifier deviationTarget =
(SchemaNodeIdentifier) deviateStmtCtx.getParentContext().getStatementArgument();
+ if (!isDeviationSupported(deviateStmtCtx, deviationTarget)) {
+ return;
+ }
+
+ final ModelActionBuilder deviateAction = deviateStmtCtx.newInferenceAction(
+ ModelProcessingPhase.EFFECTIVE_MODEL);
+
final Prerequisite<StmtContext<DeviateKind, DeviateStatement, EffectiveStatement<DeviateKind,
DeviateStatement>>> sourceCtxPrerequisite =
deviateAction.requiresCtx(deviateStmtCtx, ModelProcessingPhase.EFFECTIVE_MODEL);
- final Prerequisite<StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>> targetCtxPrerequisite =
- (Prerequisite<StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>>) deviateAction
- .mutatesEffectiveCtx(deviateStmtCtx.getRoot(), SchemaNodeIdentifierBuildNamespace.class,
- deviationTarget);
-
- deviateAction.apply(new InferenceAction() {
- @Override
- public void apply() throws InferenceException {
- // FIXME once BUG-7760 gets fixed, there will be no need for these dirty casts
- final StatementContextBase<?, ?, ?> sourceNodeStmtCtx =
- (StatementContextBase<?, ?, ?>) sourceCtxPrerequisite.get();
- final StatementContextBase<?, ?, ?> targetNodeStmtCtx =
- (StatementContextBase<?, ?, ?>) targetCtxPrerequisite.get();
-
- switch (deviateKind) {
- case NOT_SUPPORTED:
- targetNodeStmtCtx.setIsSupportedToBuildEffective(false);
- break;
- case ADD:
- performDeviateAdd(sourceNodeStmtCtx, targetNodeStmtCtx);
- break;
- case REPLACE:
- performDeviateReplace(sourceNodeStmtCtx, targetNodeStmtCtx);
- break;
- case DELETE:
- performDeviateDelete(sourceNodeStmtCtx, targetNodeStmtCtx);
- }
- }
-
- @Override
- public void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed) {
- throw new InferenceException(deviateStmtCtx.getParentContext().getStatementSourceReference(),
- "Deviation target '%s' not found.", deviationTarget);
- }
- });
+ final Prerequisite<Mutable<?, ?, EffectiveStatement<?, ?>>> targetCtxPrerequisite =
+ deviateAction.mutatesEffectiveCtx(deviateStmtCtx.getRoot(),
+ SchemaNodeIdentifierBuildNamespace.class, deviationTarget);
+
+ deviateAction.apply(new InferenceAction() {
+ @Override
+ public void apply(final InferenceContext ctx) throws InferenceException {
+ // FIXME once BUG-7760 gets fixed, there will be no need for these dirty casts
+ final StatementContextBase<?, ?, ?> sourceNodeStmtCtx =
+ (StatementContextBase<?, ?, ?>) sourceCtxPrerequisite.resolve(ctx);
+ final StatementContextBase<?, ?, ?> targetNodeStmtCtx =
+ (StatementContextBase<?, ?, ?>) targetCtxPrerequisite.resolve(ctx);
+
+ switch (deviateKind) {
+ case NOT_SUPPORTED:
+ targetNodeStmtCtx.setIsSupportedToBuildEffective(false);
+ break;
+ case ADD:
+ performDeviateAdd(sourceNodeStmtCtx, targetNodeStmtCtx);
+ break;
+ case REPLACE:
+ performDeviateReplace(sourceNodeStmtCtx, targetNodeStmtCtx);
+ break;
+ case DELETE:
+ performDeviateDelete(sourceNodeStmtCtx, targetNodeStmtCtx);
+ }
+ }
+
+ @Override
+ public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
+ throw new InferenceException(deviateStmtCtx.getParentContext().getStatementSourceReference(),
+ "Deviation target '%s' not found.", deviationTarget);
+ }
+ });
+ }
+
+ private static boolean isDeviationSupported(final Mutable<DeviateKind, DeviateStatement,
+ EffectiveStatement<DeviateKind, DeviateStatement>> deviateStmtCtx,
+ final SchemaNodeIdentifier deviationTarget) {
+ final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules = deviateStmtCtx.getFromNamespace(
+ ModulesDeviatedByModules.class, SupportedModules.SUPPORTED_MODULES);
+ if (modulesDeviatedByModules == null) {
+ return true;
+ }
+
+ final QNameModule currentModule = deviateStmtCtx.getFromNamespace(ModuleCtxToModuleQName.class,
+ deviateStmtCtx.getRoot());
+ final QNameModule targetModule = deviationTarget.getLastComponent().getModule();
+
+ final Set<QNameModule> deviationModulesSupportedByTargetModule = modulesDeviatedByModules.get(targetModule);
+ if (deviationModulesSupportedByTargetModule != null) {
+ return deviationModulesSupportedByTargetModule.contains(currentModule);
+ }
+
+ return false;
}
private static void performDeviateAdd(final StatementContextBase<?, ?, ?> deviateStmtCtx,
final StatementContextBase<?, ?, ?> targetCtx) {
- for (StatementContextBase<?, ?, ?> originalStmtCtx : deviateStmtCtx.declaredSubstatements()) {
+ for (Mutable<?, ?, ?> originalStmtCtx : deviateStmtCtx.mutableDeclaredSubstatements()) {
validateDeviationTarget(originalStmtCtx, targetCtx);
addStatement(originalStmtCtx, targetCtx);
}
}
- private static void addStatement(final StatementContextBase<?, ?, ?> stmtCtxToBeAdded,
+ private static void addStatement(final Mutable<?, ?, ?> stmtCtxToBeAdded,
final StatementContextBase<?, ?, ?> targetCtx) {
- if (StmtContextUtils.isUnknownStatement(stmtCtxToBeAdded)) {
- targetCtx.addEffectiveSubstatement(stmtCtxToBeAdded.createCopy(targetCtx, CopyType.ORIGINAL));
- return;
- }
-
- final StatementDefinition stmtToBeAdded = stmtCtxToBeAdded.getPublicDefinition();
-
- if (SINGLETON_STATEMENTS.contains(stmtToBeAdded) || (YangStmtMapping.DEFAULT.equals(stmtToBeAdded)
- && YangStmtMapping.LEAF.equals(targetCtx.getPublicDefinition()))) {
- final Iterable<StatementContextBase<?, ?, ?>> targetCtxSubstatements = Iterables.concat(
- targetCtx.declaredSubstatements(), targetCtx.effectiveSubstatements());
-
- for (final StatementContextBase<?, ?, ?> targetCtxSubstatement : targetCtxSubstatements) {
- InferenceException.throwIf(stmtToBeAdded.equals(targetCtxSubstatement.getPublicDefinition()),
- stmtCtxToBeAdded.getStatementSourceReference(), "Deviation cannot add substatement %s " +
- "to target node %s because it is already defined in target and can appear only once.",
- stmtToBeAdded.getStatementName(), targetCtx.getStatementArgument());
+ if (!StmtContextUtils.isUnknownStatement(stmtCtxToBeAdded)) {
+ final StatementDefinition stmtToBeAdded = stmtCtxToBeAdded.getPublicDefinition();
+ if (SINGLETON_STATEMENTS.contains(stmtToBeAdded) || YangStmtMapping.DEFAULT.equals(stmtToBeAdded)
+ && YangStmtMapping.LEAF.equals(targetCtx.getPublicDefinition())) {
+ for (final StmtContext<?, ?, ?> targetCtxSubstatement : targetCtx.allSubstatements()) {
+ InferenceException.throwIf(stmtToBeAdded.equals(targetCtxSubstatement.getPublicDefinition()),
+ stmtCtxToBeAdded.getStatementSourceReference(), "Deviation cannot add substatement %s "
+ + "to target node %s because it is already defined in target and can appear only once.",
+ stmtToBeAdded.getStatementName(), targetCtx.getStatementArgument());
+ }
}
}
- targetCtx.addEffectiveSubstatement(stmtCtxToBeAdded.createCopy(targetCtx, CopyType.ORIGINAL));
+ targetCtx.addEffectiveSubstatement(targetCtx.childCopyOf(stmtCtxToBeAdded, CopyType.ORIGINAL));
}
private static void performDeviateReplace(final StatementContextBase<?, ?, ?> deviateStmtCtx,
final StatementContextBase<?, ?, ?> targetCtx) {
- for (StatementContextBase<?, ?, ?> originalStmtCtx : deviateStmtCtx.declaredSubstatements()) {
+ for (Mutable<?, ?, ?> originalStmtCtx : deviateStmtCtx.mutableDeclaredSubstatements()) {
validateDeviationTarget(originalStmtCtx, targetCtx);
replaceStatement(originalStmtCtx, targetCtx);
}
}
- private static void replaceStatement(final StatementContextBase<?, ?, ?> stmtCtxToBeReplaced,
+ private static void replaceStatement(final Mutable<?, ?, ?> stmtCtxToBeReplaced,
final StatementContextBase<?, ?, ?> targetCtx) {
final StatementDefinition stmtToBeReplaced = stmtCtxToBeReplaced.getPublicDefinition();
return;
}
- for (final StatementContextBase<?, ?, ?> targetCtxSubstatement : targetCtx.effectiveSubstatements()) {
+ for (final StmtContext<?, ?, ?> targetCtxSubstatement : targetCtx.effectiveSubstatements()) {
if (stmtToBeReplaced.equals(targetCtxSubstatement.getPublicDefinition())) {
targetCtx.removeStatementFromEffectiveSubstatements(stmtToBeReplaced);
- targetCtx.addEffectiveSubstatement(stmtCtxToBeReplaced.createCopy(targetCtx, CopyType.ORIGINAL));
+ targetCtx.addEffectiveSubstatement(targetCtx.childCopyOf(stmtCtxToBeReplaced, CopyType.ORIGINAL));
return;
}
}
- for (final StatementContextBase<?, ?, ?> targetCtxSubstatement : targetCtx.declaredSubstatements()) {
+ for (final Mutable<?, ?, ?> targetCtxSubstatement : targetCtx.mutableDeclaredSubstatements()) {
if (stmtToBeReplaced.equals(targetCtxSubstatement.getPublicDefinition())) {
targetCtxSubstatement.setIsSupportedToBuildEffective(false);
- targetCtx.addEffectiveSubstatement(stmtCtxToBeReplaced.createCopy(targetCtx, CopyType.ORIGINAL));
+ targetCtx.addEffectiveSubstatement(targetCtx.childCopyOf(stmtCtxToBeReplaced, CopyType.ORIGINAL));
return;
}
}
private static void performDeviateDelete(final StatementContextBase<?, ?, ?> deviateStmtCtx,
final StatementContextBase<?, ?, ?> targetCtx) {
- for (StatementContextBase<?, ?, ?> originalStmtCtx : deviateStmtCtx.declaredSubstatements()) {
+ for (Mutable<?, ?, ?> originalStmtCtx : deviateStmtCtx.mutableDeclaredSubstatements()) {
validateDeviationTarget(originalStmtCtx, targetCtx);
deleteStatement(originalStmtCtx, targetCtx);
}
}
- private static void deleteStatement(final StatementContextBase<?, ?, ?> stmtCtxToBeDeleted,
+ private static void deleteStatement(final StmtContext<?, ?, ?> stmtCtxToBeDeleted,
final StatementContextBase<?, ?, ?> targetCtx) {
final StatementDefinition stmtToBeDeleted = stmtCtxToBeDeleted.getPublicDefinition();
final String stmtArgument = stmtCtxToBeDeleted.rawStatementArgument();
- for (final StatementContextBase<?, ?, ?> targetCtxSubstatement : targetCtx.effectiveSubstatements()) {
+ for (final Mutable<?, ?, ?> targetCtxSubstatement : targetCtx.mutableEffectiveSubstatements()) {
if (statementsAreEqual(stmtToBeDeleted, stmtArgument, targetCtxSubstatement.getPublicDefinition(),
targetCtxSubstatement.rawStatementArgument())) {
targetCtx.removeStatementFromEffectiveSubstatements(stmtToBeDeleted, stmtArgument);
}
}
- for (final StatementContextBase<?, ?, ?> targetCtxSubstatement : targetCtx.declaredSubstatements()) {
+ for (final Mutable<?, ?, ?> targetCtxSubstatement : targetCtx.mutableDeclaredSubstatements()) {
if (statementsAreEqual(stmtToBeDeleted, stmtArgument, targetCtxSubstatement.getPublicDefinition(),
targetCtxSubstatement.rawStatementArgument())) {
targetCtxSubstatement.setIsSupportedToBuildEffective(false);
return firstStmtDef.equals(secondStmtDef) && Objects.equals(firstStmtArg, secondStmtArg);
}
- private static void validateDeviationTarget(final StatementContextBase<?, ?, ?> deviateSubStmtCtx,
- final StatementContextBase<?, ?, ?> targetCtx) {
+ private static void validateDeviationTarget(final StmtContext<?, ?, ?> deviateSubStmtCtx,
+ final StmtContext<?, ?, ?> targetCtx) {
InferenceException.throwIf(!isSupportedDeviationTarget(deviateSubStmtCtx, targetCtx,
targetCtx.getRootVersion()), deviateSubStmtCtx.getStatementSourceReference(),
"%s is not a valid deviation target for substatement %s.",
targetCtx.getStatementArgument(), deviateSubStmtCtx.getPublicDefinition().getStatementName());
}
- private static boolean isSupportedDeviationTarget(final StatementContextBase<?, ?, ?> deviateSubstatementCtx,
- final StatementContextBase<?, ?, ?> deviateTargetCtx, final YangVersion yangVersion) {
+ private static boolean isSupportedDeviationTarget(final StmtContext<?, ?, ?> deviateSubstatementCtx,
+ final StmtContext<?, ?, ?> deviateTargetCtx, final YangVersion yangVersion) {
Set<StatementDefinition> supportedDeviationTargets =
YangValidationBundles.SUPPORTED_DEVIATION_TARGETS.get(deviateTargetCtx.getRootVersion(),
deviateSubstatementCtx.getPublicDefinition());