Bug 9242: Reuse deviating statement contexts 44/64644/1
authorIgor Foltin <igor.foltin@pantheon.tech>
Tue, 17 Oct 2017 14:08:18 +0000 (16:08 +0200)
committerIgor Foltin <igor.foltin@pantheon.tech>
Tue, 24 Oct 2017 11:17:42 +0000 (13:17 +0200)
In the process of deviate add/replace resolution we make
copies of deviated statement contexts which are then added
to the deviation target context.

However, making copies of these statement contexts is not
necessary except the ones which represent unknown statements.

Therefore, reuse them during the resolution of deviate add/replace.

By doing this, we also solve the failing deviate replace with
user-defined types as statement contexts that represent deviating
user-defined types are now resolved within their original context.

Change-Id: Ie61a38e270ef648fe61ea283805d149533c10f62
Signed-off-by: Igor Foltin <igor.foltin@pantheon.tech>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/DeviateStatementImpl.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug9242Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug9242/imp-module-2.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug9242/imp-module.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug9242/root-module.yang [new file with mode: 0644]

index c0748c53f760755000fceb73b94913fd299d0975..1493593cda87b03861c56a9096cb7e94dbde9f4d 100644 (file)
@@ -234,7 +234,7 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                 }
             }
 
-            targetCtx.addEffectiveSubstatement(stmtCtxToBeAdded.createCopy(targetCtx, CopyType.ORIGINAL));
+            copyStatement(stmtCtxToBeAdded, targetCtx);
         }
 
         private static void performDeviateReplace(final StatementContextBase<?, ?, ?> deviateStmtCtx,
@@ -260,7 +260,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));
+                    copyStatement(stmtCtxToBeReplaced, targetCtx);
                     return;
                 }
             }
@@ -268,7 +268,7 @@ 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));
+                    copyStatement(stmtCtxToBeReplaced, targetCtx);
                     return;
                 }
             }
@@ -320,6 +320,17 @@ public class DeviateStatementImpl extends AbstractDeclaredStatement<DeviateKind>
                     targetCtx.getStatementArgument(), stmtCtxToBeDeleted.getStatementSourceReference());
         }
 
+        private static void copyStatement(final Mutable<?, ?, ?> stmtCtxToBeCopied,
+                final StatementContextBase<?, ?, ?> targetCtx) {
+            // we need to make a copy of the statement context only if it is an unknown statement, otherwise
+            // we can reuse the original statement context
+            if (!StmtContextUtils.isUnknownStatement(stmtCtxToBeCopied)) {
+                targetCtx.addEffectiveSubstatement(stmtCtxToBeCopied);
+            } else {
+                targetCtx.addEffectiveSubstatement(stmtCtxToBeCopied.createCopy(targetCtx, CopyType.ORIGINAL));
+            }
+        }
+
         private static boolean statementsAreEqual(final StatementDefinition firstStmtDef, final String firstStmtArg,
                 final StatementDefinition secondStmtDef, final String secondStmtArg) {
             return firstStmtDef.equals(secondStmtDef) && Objects.equals(firstStmtArg, secondStmtArg);
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug9242Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug9242Test.java
new file mode 100644 (file)
index 0000000..feb93e6
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yangtools.yang.stmt;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+
+import java.util.Date;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.Deviation;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public class Bug9242Test {
+
+    @Test
+    public void testDeviateReplaceWithUserDefinedTypes() throws Exception {
+        final SchemaContext schemaContext = StmtTestUtils.parseYangSources("/bugs/bug9242/");
+        assertNotNull(schemaContext);
+
+        final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-10-13");
+
+        final Module rootModule = schemaContext.findModuleByName("root-module", revision);
+        final Module impModule = schemaContext.findModuleByName("imp-module", revision);
+        assertNotNull(impModule);
+
+        TypeDefinition<?> deviatedMyLeafType = null;
+        TypeDefinition<?> deviatedMyLeaf2Type = null;
+
+        for (final Deviation deviation : rootModule.getDeviations()) {
+            if (deviation.getTargetPath().getLastComponent().equals(QName.create(
+                    impModule.getQNameModule(), "my-leaf"))) {
+                deviatedMyLeafType = deviation.getDeviates().iterator().next().getDeviatedType();
+            }
+
+            if (deviation.getTargetPath().getLastComponent().equals(QName.create(
+                    impModule.getQNameModule(), "my-leaf-2"))) {
+                deviatedMyLeaf2Type = deviation.getDeviates().iterator().next().getDeviatedType();
+            }
+        }
+
+        assertNotNull(deviatedMyLeafType);
+        assertNotNull(deviatedMyLeaf2Type);
+
+        final LeafSchemaNode myLeaf = (LeafSchemaNode) impModule.getDataChildByName(QName.create(
+                impModule.getQNameModule(), "my-leaf"));
+        assertSame(deviatedMyLeafType, myLeaf.getType());
+
+        final LeafSchemaNode myLeaf2 = (LeafSchemaNode) impModule.getDataChildByName(QName.create(
+                impModule.getQNameModule(), "my-leaf-2"));
+        assertSame(deviatedMyLeaf2Type, myLeaf2.getType());
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug9242/imp-module-2.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug9242/imp-module-2.yang
new file mode 100644 (file)
index 0000000..0636c31
--- /dev/null
@@ -0,0 +1,12 @@
+module imp-module-2 {
+    namespace imp2-ns;
+    prefix imp2;
+
+    revision 2017-10-13;
+
+    typedef new-type {
+        type string {
+            length 10..15;
+        }
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug9242/imp-module.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug9242/imp-module.yang
new file mode 100644 (file)
index 0000000..b26b6c5
--- /dev/null
@@ -0,0 +1,14 @@
+module imp-module {
+    namespace imp-ns;
+    prefix imp;
+
+    revision 2017-10-13;
+
+    leaf my-leaf {
+        type string;
+    }
+
+    leaf my-leaf-2 {
+        type string;
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug9242/root-module.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug9242/root-module.yang
new file mode 100644 (file)
index 0000000..b5c0005
--- /dev/null
@@ -0,0 +1,32 @@
+module root-module {
+    namespace rm-ns;
+    prefix rm;
+
+    import imp-module {
+        prefix im;
+    }
+
+    import imp-module-2 {
+        prefix im2;
+    }
+
+    revision 2017-10-13;
+
+    deviation "/im:my-leaf" {
+        deviate replace {
+            type im2:new-type;
+        }
+    }
+
+    deviation "/im:my-leaf-2" {
+        deviate replace {
+            type new-type;
+        }
+    }
+
+    typedef new-type {
+        type int32 {
+            range 10..15;
+        }
+    }
+}
\ No newline at end of file