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 fda3df0b6beef35c9d2613e2c4beb2274579b284..b87656fd100a4e5e65a96c51d7165fedb170ea44 100644 (file)
@@ -89,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()) {
@@ -101,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);
         }
@@ -168,6 +172,9 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                             break;
                         case DELETE:
                             performDeviateDelete(sourceNodeStmtCtx, targetNodeStmtCtx);
+                            break;
+                        default:
+                            throw new IllegalStateException("Unsupported deviate " + deviateKind);
                     }
                 }
 
@@ -216,9 +223,10 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                         && 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());
+                            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());
                     }
                 }
             }
@@ -240,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;
             }
@@ -262,8 +270,16 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                 }
             }
 
-            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());
         }
 
@@ -296,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());
         }
 
@@ -352,7 +368,8 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
         }
     }
 
-    @Nonnull @Override
+    @Nonnull
+    @Override
     public DeviateKind getValue() {
         return argument();
     }