BUG-4688: Switch BelongsToModuleContext to SourceIdentifier
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / DeviateStatementImpl.java
index 1cee5d7cdf82613ecf21b2cd78c3c51946fd41cf..b87656fd100a4e5e65a96c51d7165fedb170ea44 100644 (file)
@@ -10,7 +10,6 @@ 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;
@@ -24,7 +23,6 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 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;
@@ -37,6 +35,7 @@ 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;
@@ -90,6 +89,7 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
     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()) {
@@ -102,6 +102,9 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                 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);
         }
@@ -169,6 +172,9 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                             break;
                         case DELETE:
                             performDeviateDelete(sourceNodeStmtCtx, targetNodeStmtCtx);
+                            break;
+                        default:
+                            throw new IllegalStateException("Unsupported deviate " + deviateKind);
                     }
                 }
 
@@ -211,27 +217,21 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<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,
@@ -248,8 +248,8 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
 
             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;
             }
@@ -257,7 +257,7 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
             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;
                 }
             }
@@ -265,13 +265,21 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
             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());
         }
 
@@ -304,8 +312,8 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                 }
             }
 
-            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());
         }
 
@@ -360,7 +368,8 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
         }
     }
 
-    @Nonnull @Override
+    @Nonnull
+    @Override
     public DeviateKind getValue() {
         return argument();
     }