Fix patch target parsing 32/97232/1
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 13 Aug 2021 20:28:24 +0000 (22:28 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 17 Aug 2021 10:31:18 +0000 (12:31 +0200)
Our tests were not updated for RFC8040, hence they are written with
weird codecs which utterly do not match RFC8072 definition of
yang-patch.

The problem is that patch edit's target is interpreted in terms of an
extension to the URL, i.e. it does NOT follow JSON nor XML parsing
rules, nor is it anything in-between -- we must use ParserIdentifier's
facilities.

Update the parsers and the test suites, ditching a lot of complexity
in process of doing so.

JIRA: NETCONF-804
Change-Id: If9d9c77e0e2397ffdcb8e8c0f0fef0b9b02bac8b
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 845f511527e22741a1cf1053b04250d16bf7f6a0)

13 files changed:
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/JsonToPatchBodyReader.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/XmlToPatchBodyReader.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/utils/parser/ParserIdentifier.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/JsonPatchBodyReaderMountPointTest.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/patch/XmlPatchBodyReaderMountPointTest.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/jsonPATCHMergeOperationOnList.json
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/json/jsonPATCHSimpleLeafValue.json
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/json/jsonPATCHdata.json
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/json/jsonPATCHdataCreateAndDelete.json
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/xml/xmlPATCHdata.xml
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml
restconf/restconf-nb-rfc8040/src/test/resources/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml

index 142af2989639cc48a9d81b87410eac05ba723db6..9c53d185d01985086098c3b4f027ef34db4b0641 100644 (file)
@@ -234,7 +234,7 @@ public class JsonToPatchBodyReader extends AbstractToPatchBodyReader {
                         edit.setTarget(path.getInstanceIdentifier());
                         edit.setTargetSchemaNode(path.getSchemaContext());
                     } else {
-                        edit.setTarget(codec.deserialize(codec.serialize(path.getInstanceIdentifier()).concat(target)));
+                        edit.setTarget(ParserIdentifier.parserPatchTarget(path, target));
                         edit.setTargetSchemaNode(SchemaContextUtil.findDataSchemaNode(path.getSchemaContext(),
                                 codec.getDataContextTree().findChild(edit.getTarget()).orElseThrow().getDataSchemaNode()
                                         .getPath().getParent()));
index 95a78badb8d30e802be09379c55d7d9e0afb11bc..dbfb889edd7aa683824a0c872ad82ee445fd97b7 100644 (file)
@@ -7,14 +7,14 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch;
 
+import static com.google.common.base.Verify.verifyNotNull;
+
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import javax.ws.rs.Consumes;
@@ -24,7 +24,6 @@ import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.dom.DOMSource;
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
@@ -33,13 +32,11 @@ import org.opendaylight.restconf.common.patch.PatchContext;
 import org.opendaylight.restconf.common.patch.PatchEditOperation;
 import org.opendaylight.restconf.common.patch.PatchEntity;
 import org.opendaylight.restconf.nb.rfc8040.Rfc8040;
-import org.opendaylight.restconf.nb.rfc8040.codecs.StringModuleInstanceIdentifierCodec;
 import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
 import org.opendaylight.restconf.nb.rfc8040.utils.RestconfConstants;
+import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
 import org.opendaylight.yangtools.util.xml.UntrustedXML;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -47,11 +44,10 @@ import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStre
 import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
@@ -117,28 +113,15 @@ public class XmlToPatchBodyReader extends AbstractToPatchBodyReader {
                 targetII = pathContext.getInstanceIdentifier();
                 targetNode = pathContext.getSchemaContext();
             } else {
-                // get namespace according to schema node from path context or value
-                final URI namespace = firstValueElement == null ? schemaNode.getQName().getNamespace()
-                    : URI.create(firstValueElement.getNamespaceURI());
-
-                // find module according to namespace
-                final Module module = pathContext.getSchemaContext().findModules(namespace).iterator().next();
-
-                // initialize codec + set default prefix derived from module name
-                final StringModuleInstanceIdentifierCodec codec = new StringModuleInstanceIdentifierCodec(
-                        pathContext.getSchemaContext(), module.getName());
+                // interpret as simple context
+                targetII = ParserIdentifier.parserPatchTarget(pathContext, target);
 
-                targetII = codec.deserialize(codec.serialize(pathContext.getInstanceIdentifier())
-                        .concat(prepareNonCondXpath(schemaNode, target.replaceFirst("/", ""), firstValueElement,
-                                namespace, module.getQNameModule().getRevision().orElse(null))));
+                // move schema node
+                final DataSchemaContextTree tree = DataSchemaContextTree.from(pathContext.getSchemaContext());
+                schemaNode = verifyNotNull(tree.findChild(targetII).orElseThrow().getDataSchemaNode());
 
                 targetNode = SchemaContextUtil.findDataSchemaNode(pathContext.getSchemaContext(),
-                        codec.getDataContextTree().findChild(targetII).orElseThrow().getDataSchemaNode()
-                        .getPath().getParent());
-
-                // move schema node
-                schemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(pathContext.getSchemaContext(),
-                        codec.getDataContextTree().findChild(targetII).orElseThrow().getDataSchemaNode().getPath());
+                    schemaNode.getPath().getParent());
             }
 
             if (targetNode == null) {
@@ -209,73 +192,4 @@ public class XmlToPatchBodyReader extends AbstractToPatchBodyReader {
 
         return result;
     }
-
-    /**
-     * Prepare non-conditional XPath suitable for deserialization with {@link StringModuleInstanceIdentifierCodec}.
-     *
-     * @param schemaNode Top schema node
-     * @param target Edit operation target
-     * @param value Element with value
-     * @param namespace Module namespace
-     * @param revision Module revision
-     * @return Non-conditional XPath
-     */
-    private static String prepareNonCondXpath(final @NonNull DataSchemaNode schemaNode, final @NonNull String target,
-            final @NonNull Element value, final @NonNull URI namespace, final @Nullable Revision revision) {
-        final Iterator<String> args = SLASH_SPLITTER.split(target.substring(target.indexOf(':') + 1)).iterator();
-
-        final StringBuilder nonCondXpath = new StringBuilder();
-        SchemaNode childNode = schemaNode;
-
-        while (args.hasNext()) {
-            final String s = args.next();
-            nonCondXpath.append("/");
-            nonCondXpath.append(s);
-            childNode = ((DataNodeContainer) childNode).getDataChildByName(QName.create(namespace, revision, s));
-
-            if (childNode instanceof ListSchemaNode && args.hasNext()) {
-                appendKeys(nonCondXpath, ((ListSchemaNode) childNode).getKeyDefinition().iterator(), args);
-            }
-        }
-
-        if (childNode instanceof ListSchemaNode && value != null) {
-            final Iterator<String> keyValues = readKeyValues(value,
-                    ((ListSchemaNode) childNode).getKeyDefinition().iterator());
-            appendKeys(nonCondXpath, ((ListSchemaNode) childNode).getKeyDefinition().iterator(), keyValues);
-        }
-
-        return nonCondXpath.toString();
-    }
-
-    /**
-     * Read value for every list key.
-     *
-     * @param value Value element
-     * @param keys Iterator of list keys names
-     * @return Iterator of list keys values
-     */
-    private static Iterator<String> readKeyValues(final @NonNull Element value, final @NonNull Iterator<QName> keys) {
-        final List<String> result = new ArrayList<>();
-
-        while (keys.hasNext()) {
-            result.add(value.getElementsByTagName(keys.next().getLocalName()).item(0).getFirstChild().getNodeValue());
-        }
-
-        return result.iterator();
-    }
-
-    /**
-     * Append key name - key value pairs for every list key to {@code nonCondXpath}.
-     *
-     * @param nonCondXpath Builder for creating non-conditional XPath
-     * @param keyNames Iterator of list keys names
-     * @param keyValues Iterator of list keys values
-     */
-    private static void appendKeys(final @NonNull StringBuilder nonCondXpath, final @NonNull Iterator<QName> keyNames,
-            final @NonNull Iterator<String> keyValues) {
-        while (keyNames.hasNext()) {
-            nonCondXpath.append('[').append(keyNames.next().getLocalName()).append("='").append(keyValues.next())
-                .append("']");
-        }
-    }
 }
index 305b93ff7a95829daa5c8f34ea992eee13158842..9bfd60b3e69a4af2052736853f383fc70364e723 100644 (file)
@@ -270,6 +270,20 @@ public final class ParserIdentifier {
         }
     }
 
+    public static YangInstanceIdentifier parserPatchTarget(final InstanceIdentifierContext<?> context,
+            final String target) {
+        final var schemaContext = context.getSchemaContext();
+        final var urlPath = context.getInstanceIdentifier();
+        final String targetUrl;
+        if (urlPath.isEmpty()) {
+            targetUrl = target.startsWith("/") ? target.substring(1) : target;
+        } else {
+            targetUrl = stringFromYangInstanceIdentifier(urlPath, schemaContext) + target;
+        }
+
+        return toInstanceIdentifier(targetUrl, schemaContext, Optional.empty()).getInstanceIdentifier();
+    }
+
     /**
      * Validation and parsing of revision.
      *
index 5149c271dff1e3b031892c82ff311508140d6a6c..92ae4103ce1d030eb25822edf2355d4ad430df9b 100644 (file)
@@ -5,12 +5,11 @@
  * 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.restconf.nb.rfc8040.jersey.providers.patch;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThrows;
 
 import java.io.InputStream;
 import javax.ws.rs.core.MediaType;
@@ -48,11 +47,8 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream = JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdata.json");
-
-        final PatchContext returnValue = jsonToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+        final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            JsonBodyReaderTest.class.getResourceAsStream("/instanceidentifier/json/jsonPATCHdata.json"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -64,11 +60,8 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream = JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataCreateAndDelete.json");
-
-        final PatchContext returnValue = jsonToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+        final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            JsonBodyReaderTest.class.getResourceAsStream("/instanceidentifier/json/jsonPATCHdataCreateAndDelete.json"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -81,15 +74,11 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream = JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataValueMissing.json");
-
-        try {
-            jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
-            fail("Test should return error 400 due to missing value node when attempt to invoke create operation");
-        } catch (final RestconfDocumentedException e) {
-            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
-        }
+        final InputStream inputStream = JsonBodyReaderTest.class.getResourceAsStream(
+            "/instanceidentifier/json/jsonPATCHdataValueMissing.json");
+        final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
+            () -> jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
+        assertEquals("Error code 400 expected", 400, ex.getErrors().get(0).getErrorTag().getStatusCode());
     }
 
     /**
@@ -101,15 +90,11 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream = JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataValueNotSupported.json");
-
-        try {
-            jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
-            fail("Test should return error 400 due to present value node when attempt to invoke delete operation");
-        } catch (final RestconfDocumentedException e) {
-            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
-        }
+        final InputStream inputStream = JsonBodyReaderTest.class.getResourceAsStream(
+            "/instanceidentifier/json/jsonPATCHdataValueNotSupported.json");
+        final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
+            () -> jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
+        assertEquals("Error code 400 expected", 400, ex.getErrors().get(0).getErrorTag().getStatusCode());
     }
 
     /**
@@ -120,11 +105,9 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream = JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataCompleteTargetInURI.json");
-
-        final PatchContext returnValue = jsonToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+        final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            JsonBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/json/jsonPATCHdataCompleteTargetInURI.json"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -136,11 +119,9 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream = JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnList.json");
-
-        final PatchContext returnValue = jsonToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+        final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            JsonBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/json/jsonPATCHMergeOperationOnList.json"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -152,11 +133,9 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream = JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json");
-
-        final PatchContext returnValue = jsonToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+        final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            JsonBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -168,12 +147,8 @@ public class JsonPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, jsonToPatchBodyReader, false);
 
-        final InputStream inputStream =
-                JsonBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/json/jsonPATCHSimpleLeafValue.json");
-
-        final PatchContext returnValue = jsonToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+        final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            JsonBodyReaderTest.class.getResourceAsStream("/instanceidentifier/json/jsonPATCHSimpleLeafValue.json"));
         checkPatchContext(returnValue);
     }
 }
index 97b2da238d311aef101e82edd932497bf7939466..da1b92137a5c337dfce8729665314fd6040c9aa5 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThrows;
 
 import java.io.InputStream;
 import javax.ws.rs.core.MediaType;
@@ -46,10 +46,9 @@ public class XmlPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
     public void moduleDataTest() throws Exception {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdata.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdata.xml"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -60,14 +59,12 @@ public class XmlPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
     public void moduleDataValueMissingNegativeTest() throws Exception {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataValueMissing.xml");
-        try {
-            xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
-            fail("Test should return error 400 due to missing value node when attempt to invoke create operation");
-        } catch (final RestconfDocumentedException e) {
-            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
-        }
+        final InputStream inputStream = XmlBodyReaderTest.class.getResourceAsStream(
+            "/instanceidentifier/xml/xmlPATCHdataValueMissing.xml");
+
+        final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
+            () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
+        assertEquals("Error code 400 expected", 400, ex.getErrors().get(0).getErrorTag().getStatusCode());
     }
 
     /**
@@ -78,14 +75,12 @@ public class XmlPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
     public void moduleDataNotValueNotSupportedNegativeTest() throws Exception {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml");
-        try {
-            xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
-            fail("Test should return error 400 due to present value node when attempt to invoke delete operation");
-        } catch (final RestconfDocumentedException e) {
-            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
-        }
+        final InputStream inputStream = XmlBodyReaderTest.class.getResourceAsStream(
+            "/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml");
+
+        final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
+            () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
+        assertEquals("Error code 400 expected", 400, ex.getErrors().get(0).getErrorTag().getStatusCode());
     }
 
 
@@ -96,10 +91,9 @@ public class XmlPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
     public void moduleDataAbsoluteTargetPathTest() throws Exception {
         final String uri = MOUNT_POINT;
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -110,10 +104,9 @@ public class XmlPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
     public void modulePatchCompleteTargetInURITest() throws Exception {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -124,10 +117,10 @@ public class XmlPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
     public void moduleDataMergeOperationOnListTest() throws Exception {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml"));
         checkPatchContextMountPoint(returnValue);
     }
 
@@ -138,10 +131,10 @@ public class XmlPatchBodyReaderMountPointTest extends AbstractBodyReaderTest {
     public void moduleDataMergeOperationOnContainerTest() throws Exception {
         final String uri = MOUNT_POINT + "instance-identifier-patch-module:patch-cont";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml"));
         checkPatchContextMountPoint(returnValue);
     }
 }
index d8d7bb17c2bd4e6febc43b502fd085a2fa92421f..f88723391ff1a8e0740b5492c45d77392fbd9d21 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThrows;
 
 import java.io.InputStream;
 import javax.ws.rs.core.MediaType;
@@ -45,10 +45,9 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
     public void moduleDataTest() throws Exception {
         final String uri = "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdata.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdata.xml"));
         checkPatchContext(returnValue);
     }
 
@@ -59,14 +58,12 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
     public void moduleDataValueMissingNegativeTest() throws Exception {
         final String uri = "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataValueMissing.xml");
-        try {
-            xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
-            fail("Test should return error 400 due to missing value node when attempt to invoke create operation");
-        } catch (final RestconfDocumentedException e) {
-            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
-        }
+        final InputStream inputStream = XmlBodyReaderTest.class.getResourceAsStream(
+            "/instanceidentifier/xml/xmlPATCHdataValueMissing.xml");
+
+        final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
+            () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
+        assertEquals("Error code 400 expected", 400, ex.getErrors().get(0).getErrorTag().getStatusCode());
     }
 
     /**
@@ -77,14 +74,12 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
     public void moduleDataNotValueNotSupportedNegativeTest() throws Exception {
         final String uri = "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml");
-        try {
-            xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
-            fail("Test should return error 400 due to present value node when attempt to invoke delete operation");
-        } catch (final RestconfDocumentedException e) {
-            assertEquals("Error code 400 expected", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
-        }
+        final InputStream inputStream = XmlBodyReaderTest.class.getResourceAsStream(
+            "/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml");
+
+        final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
+            () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
+        assertEquals("Error code 400 expected", 400, ex.getErrors().get(0).getErrorTag().getStatusCode());
     }
 
 
@@ -95,10 +90,9 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
     public void moduleDataAbsoluteTargetPathTest() throws Exception {
         final String uri = "";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml"));
         checkPatchContext(returnValue);
     }
 
@@ -109,10 +103,9 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
     public void modulePatchCompleteTargetInURITest() throws Exception {
         final String uri = "instance-identifier-patch-module:patch-cont";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml"));
         checkPatchContext(returnValue);
     }
 
@@ -123,10 +116,10 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
     public void moduleDataMergeOperationOnListTest() throws Exception {
         final String uri = "instance-identifier-patch-module:patch-cont/my-list1=leaf1";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml"));
         checkPatchContext(returnValue);
     }
 
@@ -137,10 +130,9 @@ public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
     public void moduleDataMergeOperationOnContainerTest() throws Exception {
         final String uri = "instance-identifier-patch-module:patch-cont";
         mockBodyReader(uri, xmlToPatchBodyReader, false);
-        final InputStream inputStream = XmlBodyReaderTest.class
-                .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml");
-        final PatchContext returnValue = xmlToPatchBodyReader
-                .readFrom(null, null, null, mediaType, null, inputStream);
+        final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
+            XmlBodyReaderTest.class.getResourceAsStream(
+                "/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml"));
         checkPatchContext(returnValue);
     }
 }
index 3b809e0061b38e9e60a6cda1c601ebffac592951..cbb67a97699ca9bba092ef782fed5a79275b0b7c 100644 (file)
@@ -6,7 +6,7 @@
       {
         "edit-id": "edit1",
         "operation": "replace",
-        "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf20']",
+        "target": "/my-list2=my-leaf20",
         "value": {
           "my-list2": {
             "name": "my-leaf20",
@@ -18,7 +18,7 @@
       {
         "edit-id": "edit2",
         "operation": "merge",
-        "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf21']",
+        "target": "/my-list2=my-leaf21",
         "value": {
           "my-list2": {
             "name": "my-leaf21",
@@ -29,4 +29,4 @@
       }
     ]
   }
-}
\ No newline at end of file
+}
index 4a109efb919e66f6533388ab6c04bdddb84a1418..d63d43b8fb3041590afc1312ea204052e010cbf4 100644 (file)
@@ -7,11 +7,11 @@
       {
         "edit-id": "edit1",
         "operation": "replace",
-        "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf20']/instance-identifier-patch-module:name",
+        "target": "/my-list2=my-leaf20/name",
         "value": {
           "name": "my-leaf20"
         }
       }
     ]
   }
-}
\ No newline at end of file
+}
index e027a7667283685ff9f4d020c38da0ccbb326179..24988264ac139c09432ce1b2da02ecdc3637ae8b 100644 (file)
@@ -7,7 +7,7 @@
       {
         "edit-id": "edit1",
         "operation": "replace",
-        "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf20']",
+        "target": "/my-list2=my-leaf20",
         "value": {
           "my-list2": {
             "name": "my-leaf20",
@@ -20,7 +20,7 @@
       {
         "edit-id": "edit2",
         "operation": "replace",
-        "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf20']",
+        "target": "/my-list2=my-leaf20",
         "value": {
           "my-list2": {
             "name": "my-leaf20",
index 44550381341f39a747657a0833f5944a37f9eff1..8d705a8fdd72f034e89bbceb88d590df0a53cf9a 100644 (file)
             }
           ]
         },
-        "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf20']",
+        "target": "/my-list2=my-leaf20",
         "operation": "create"
       },
       {
         "edit-id": "edit2",
         "operation": "delete",
-        "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf20']"
+        "target": "/my-list2=my-leaf20"
       }
     ]
   }
-}
\ No newline at end of file
+}
index d7d3a6bea6fc13e2c3a8b14871603f33ea1d7f74..3542c9133ab7efb010e2808c1e4a8654d6120e3e 100644 (file)
@@ -4,7 +4,7 @@
     <edit>
         <edit-id>edit1</edit-id>
         <operation>create</operation>
-        <target>/my-list2</target>
+        <target>/my-list2=my-leaf20</target>
         <value>
             <my-list2 xmlns="instance:identifier:patch:module">
                 <name>my-leaf20</name>
@@ -16,7 +16,7 @@
     <edit>
         <edit-id>edit2</edit-id>
         <operation>create</operation>
-        <target>/my-list2</target>
+        <target>/my-list2=my-leaf21</target>
         <value>
             <my-list2 xmlns="instance:identifier:patch:module">
                 <name>my-leaf21</name>
@@ -25,4 +25,4 @@
             </my-list2>
         </value>
     </edit>
-</yang-patch>
\ No newline at end of file
+</yang-patch>
index 6e84c47a49fbf49f0a632edbfa464a73e328b1a2..d792356a7d9d844f07149c12ee9bf9068a7d4af2 100644 (file)
@@ -11,7 +11,7 @@
     <edit>
         <edit-id>edit1</edit-id>
         <operation>create</operation>
-        <target>/instance-identifier-patch-module:patch-cont/my-list1/leaf1/my-list2</target>
+        <target>/instance-identifier-patch-module:patch-cont/my-list1=leaf1/my-list2=my-leaf20</target>
         <value>
             <my-list2 xmlns="instance:identifier:patch:module">
                 <name>my-leaf20</name>
@@ -23,7 +23,7 @@
     <edit>
         <edit-id>edit2</edit-id>
         <operation>create</operation>
-        <target>/instance-identifier-patch-module:patch-cont/my-list1/leaf1/my-list2</target>
+        <target>/instance-identifier-patch-module:patch-cont/my-list1=leaf1/my-list2=my-leaf21</target>
         <value>
             <my-list2 xmlns="instance:identifier:patch:module">
                 <name>my-leaf21</name>
@@ -32,4 +32,4 @@
             </my-list2>
         </value>
     </edit>
-</yang-patch>
\ No newline at end of file
+</yang-patch>
index ad130413a4107265b4f920ffaca202c44fa4a8b4..bf852877c4179cef6c44fa150ed00a1c9bb25288 100644 (file)
@@ -11,7 +11,7 @@
     <edit>
         <edit-id>edit1</edit-id>
         <operation>replace</operation>
-        <target>/my-list2</target>
+        <target>/my-list2=my-leaf20</target>
         <value>
             <my-list2 xmlns="instance:identifier:patch:module">
                 <name>my-leaf20</name>
@@ -23,7 +23,7 @@
     <edit>
         <edit-id>edit2</edit-id>
         <operation>merge</operation>
-        <target>/my-list2</target>
+        <target>/my-list2=my-leaf21</target>
         <value>
             <my-list2 xmlns="instance:identifier:patch:module">
                 <name>my-leaf21</name>
@@ -32,4 +32,4 @@
             </my-list2>
         </value>
     </edit>
-</yang-patch>
\ No newline at end of file
+</yang-patch>