Fix PATCH request issue with top-level container as target 03/101003/5
authorSangwook Ha <sangwook.ha@verizon.com>
Fri, 6 May 2022 17:14:04 +0000 (10:14 -0700)
committerRobert Varga <nite@hq.sk>
Fri, 13 May 2022 05:07:08 +0000 (05:07 +0000)
PATCH request to the data root with a top-level container as
target does not work because JsonPatchBodyReader and
XmlPatchBodyReader expect a parent statement in the stack.

Address the issue by setting target schema node to the path
schema context when stack is empty and add test cases for
JsonPatchBodyReader and XmlPatchBodyReader.

JIRA: NETCONF-877
Change-Id: Ibb65ccdf3f03d8a9a9023d75bf288e5e4416ca50
Signed-off-by: Sangwook Ha <sangwook.ha@verizon.com>
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/JsonPatchBodyReader.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/XmlPatchBodyReader.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/JsonPatchBodyReaderTest.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/XmlPatchBodyReaderTest.java
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/json/jsonPATCHTargetTopLevelContainerWithEmptyURI.json [new file with mode: 0644]
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/xml/xmlPATCHTargetTopLevelContainerWithEmptyURI.xml [new file with mode: 0644]

index c2886b4de7a9d28cd870c5b2a6c150affa372f00..c581243ab3073cc3785fb39e38922d950aa03c75 100644 (file)
@@ -239,8 +239,10 @@ public class JsonPatchBodyReader extends AbstractPatchBodyReader {
                             stack.exit();
                         }
 
-                        final EffectiveStatement<?, ?> parentStmt = stack.currentStatement();
-                        verify(parentStmt instanceof SchemaNode, "Unexpected parent %s", parentStmt);
+                        if (!stack.isEmpty()) {
+                            final EffectiveStatement<?, ?> parentStmt = stack.currentStatement();
+                            verify(parentStmt instanceof SchemaNode, "Unexpected parent %s", parentStmt);
+                        }
                         edit.setTargetSchemaNode(stack.toInference());
                     }
 
index f6138d109cd023ec9a63b475f11a67f42e3d36ce..109c6a77f02c38b463af56dd7c8984c881ea66cd 100644 (file)
@@ -124,9 +124,13 @@ public class XmlPatchBodyReader extends AbstractPatchBodyReader {
                     stack.exit();
                 }
 
-                final EffectiveStatement<?, ?> parentStmt = stack.currentStatement();
-                verify(parentStmt instanceof SchemaNode, "Unexpected parent %s", parentStmt);
-                targetNode = (SchemaNode) parentStmt;
+                if (stack.isEmpty()) {
+                    targetNode = pathContext.getSchemaContext();
+                } else {
+                    final EffectiveStatement<?, ?> parentStmt = stack.currentStatement();
+                    verify(parentStmt instanceof SchemaNode, "Unexpected parent %s", parentStmt);
+                    targetNode = (SchemaNode) parentStmt;
+                }
             }
 
             if (targetNode == null) {
index 91a409d763eedd325052cf876f2e29201ccfee78..d9f42d9978f6247a0f53a38c25545f5c8ba58551 100644 (file)
@@ -162,4 +162,19 @@ public class JsonPatchBodyReaderTest extends AbstractBodyReaderTest {
         final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
         checkPatchContext(returnValue);
     }
+
+    /**
+     * Test of Yang Patch on the top-level container with empty URI for data root.
+     */
+    @Test
+    public void modulePatchTargetTopLevelContainerWithEmptyURITest() throws Exception {
+        final String uri = "";
+        mockBodyReader(uri, jsonToPatchBodyReader, false);
+
+        final InputStream inputStream = JsonBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/json/jsonPATCHTargetTopLevelContainerWithEmptyURI.json");
+
+        final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
+        checkPatchContext(returnValue);
+    }
 }
index 60571fa66a2d1d952bc3d923b2ef6f817b58eff4..96e16d71ebbffa2df60f84ad5975d38d8acc6bef 100644 (file)
@@ -116,4 +116,15 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
                 .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml");
         checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
     }
+
+    /**
+     * Test of Yang Patch on the top-level container with empty URI for data root.
+     */
+    @Test
+    public void modulePatchTargetTopLevelContainerWithEmptyURITest() throws Exception {
+        mockBodyReader("", xmlToPatchBodyReader, false);
+        final InputStream inputStream = XmlBodyReaderTest.class
+                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHTargetTopLevelContainerWithEmptyURI.xml");
+        checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
+    }
 }
diff --git a/restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/json/jsonPATCHTargetTopLevelContainerWithEmptyURI.json b/restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/json/jsonPATCHTargetTopLevelContainerWithEmptyURI.json
new file mode 100644 (file)
index 0000000..31bc148
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "ietf-yang-patch:yang-patch" : {
+    "patch-id" : "test-patch",
+    "comment" : "Test patch applied to the top-level container with empty URI",
+    "edit" : [
+      {
+        "edit-id": "edit1",
+        "operation": "replace",
+        "target": "/instance-identifier-patch-module:patch-cont",
+        "value": {
+          "patch-cont": {
+            "my-list1": [
+              {
+                "name": "my-leaf10"
+              }
+            ]
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/xml/xmlPATCHTargetTopLevelContainerWithEmptyURI.xml b/restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/xml/xmlPATCHTargetTopLevelContainerWithEmptyURI.xml
new file mode 100644 (file)
index 0000000..11b619d
--- /dev/null
@@ -0,0 +1,16 @@
+<yang-patch xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-patch">
+    <patch-id>test-patch</patch-id>
+    <comment>Test patch applied to the top-level container with empty URI</comment>
+    <edit>
+        <edit-id>edit1</edit-id>
+        <operation>replace</operation>
+        <target>/instance-identifier-patch-module:patch-cont</target>
+        <value>
+            <patch-cont xmlns="instance:identifier:patch:module">
+                <my-list1>
+                    <name>my-leaf10</name>
+                </my-list1>
+            </patch-cont>
+        </value>
+    </edit>
+</yang-patch>