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 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.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;
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()) {
YangStmtMapping.UNITS, YangStmtMapping.CONFIG, YangStmtMapping.MANDATORY,
YangStmtMapping.MIN_ELEMENTS, YangStmtMapping.MAX_ELEMENTS);
+ private static final Set<YangStmtMapping> IMPLICIT_STATEMENTS = ImmutableSet.of(YangStmtMapping.CONFIG,
+ YangStmtMapping.MANDATORY, YangStmtMapping.MAX_ELEMENTS, YangStmtMapping.MIN_ELEMENTS);
+
public Definition() {
super(YangStmtMapping.DEVIATE);
}
break;
case DELETE:
performDeviateDelete(sourceNodeStmtCtx, targetNodeStmtCtx);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported deviate " + deviateKind);
}
}
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<StmtContext<?, ?, ?>> targetCtxSubstatements = Iterables.concat(
- targetCtx.declaredSubstatements(), targetCtx.effectiveSubstatements());
-
- for (final StmtContext<?, ?, ?> 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.",
+ 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,
if (YangStmtMapping.DEFAULT.equals(stmtToBeReplaced)
&& YangStmtMapping.LEAF_LIST.equals(targetCtx.getPublicDefinition())) {
- LOG.error("Deviation cannot replace substatement {} in target leaf-list {} because a leaf-list can " +
- "have multiple default statements. At line: {}", stmtToBeReplaced.getStatementName(),
+ LOG.error("Deviation cannot replace substatement {} in target leaf-list {} because a leaf-list can "
+ + "have multiple default statements. At line: {}", stmtToBeReplaced.getStatementName(),
targetCtx.getStatementArgument(), stmtCtxToBeReplaced.getStatementSourceReference());
return;
}
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 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;
}
}
- throw new InferenceException(stmtCtxToBeReplaced.getStatementSourceReference(), "Deviation cannot " +
- "replace substatement %s in target node %s because it does not exist in target node.",
+ // This is a special case when deviate replace of a config/mandatory/max/min-elements substatement targets
+ // a node which does not contain an explicitly declared config/mandatory/max/min-elements.
+ // However, according to RFC6020/RFC7950, these properties are always implicitly present.
+ if (IMPLICIT_STATEMENTS.contains(stmtToBeReplaced)) {
+ addStatement(stmtCtxToBeReplaced, targetCtx);
+ return;
+ }
+
+ throw new InferenceException(stmtCtxToBeReplaced.getStatementSourceReference(), "Deviation cannot replace "
+ + "substatement %s in target node %s because it does not exist in target node.",
stmtToBeReplaced.getStatementName(), targetCtx.getStatementArgument());
}
}
}
- LOG.error("Deviation cannot delete substatement {} with argument '{}' in target node {} because it does " +
- "not exist in the target node. At line: {}", stmtToBeDeleted.getStatementName(), stmtArgument,
+ LOG.error("Deviation cannot delete substatement {} with argument '{}' in target node {} because it does "
+ + "not exist in the target node. At line: {}", stmtToBeDeleted.getStatementName(), stmtArgument,
targetCtx.getStatementArgument(), stmtCtxToBeDeleted.getStatementSourceReference());
}
}
}
- @Nonnull @Override
+ @Nonnull
+ @Override
public DeviateKind getValue() {
return argument();
}