Introduce restconf.server.api.DataPostPath 84/109084/3
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 28 Nov 2023 01:33:37 +0000 (02:33 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 28 Nov 2023 02:18:36 +0000 (03:18 +0100)
DataPostPath is a state capture of the context we get parsing the
ApiPath. Define in in restconf.server.api and use it in ChildBody.

This has the immediate benefit of reusing JSON/XML codecs.

JIRA: NETCONF-1157
Change-Id: I4177f963b09a732929c61617f56fd1fb24d55396
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/ChildBody.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/DataPostBody.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/JsonChildBody.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/XmlChildBody.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/api/DataPostPath.java [new file with mode: 0644]
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/MdsalRestconfServer.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/databind/JsonChildBodyTest.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/databind/XmlChildBodyTest.java

index 5e371438bc646d28bff25f6ddfcfd1d50636693c..61f64c290419b9eea2ee27ee57a46cf1f75d5ee6 100644 (file)
@@ -12,10 +12,9 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.collect.ImmutableList;
 import java.io.InputStream;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.restconf.server.api.DataPostPath;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
 
 public abstract sealed class ChildBody extends AbstractBody permits JsonChildBody, XmlChildBody {
     public record PrefixAndBody(@NonNull ImmutableList<PathArgument> prefix, @NonNull NormalizedNode body) {
@@ -29,11 +28,15 @@ public abstract sealed class ChildBody extends AbstractBody permits JsonChildBod
         super(inputStream);
     }
 
-    public final @NonNull PrefixAndBody toPayload(final @NonNull YangInstanceIdentifier parentPath,
-            final @NonNull Inference parentInference) {
-        return toPayload(acquireStream(), parentPath, parentInference);
+    /**
+     * Interpret this object as a child of specified path.
+     *
+     * @param path POST request path
+     * @return A {@link PrefixAndBody}
+     */
+    public final @NonNull PrefixAndBody toPayload(final @NonNull DataPostPath path) {
+        return toPayload(path, acquireStream());
     }
 
-    abstract @NonNull PrefixAndBody toPayload(@NonNull InputStream inputStream,
-        @NonNull YangInstanceIdentifier parentPath, @NonNull Inference parentInference);
+    abstract @NonNull PrefixAndBody toPayload(@NonNull DataPostPath path, @NonNull InputStream inputStream);
 }
index 551d664cd5f9d08cb90b30a6ccf7a2d7b057ce59..84800d65881d76748a4c45c8bd5b29b27146a453 100644 (file)
@@ -9,10 +9,12 @@ package org.opendaylight.restconf.nb.rfc8040.databind;
 
 import java.io.InputStream;
 import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.restconf.server.api.DataPostPath;
 
 /**
  * Body of a {@code POST} request as defined in
  * <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.4">RFC8040 section 4.4</a>.
+ * @see DataPostPath
  */
 @NonNullByDefault
 public abstract sealed class DataPostBody extends AbstractBody permits JsonDataPostBody, XmlDataPostBody {
index 95a608ff0c83da2b20845aae779deb1eee8dc5d6..22d184467a8abaac0590803eb83ad0d3168ed4fe 100644 (file)
@@ -15,20 +15,18 @@ import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.server.api.DataPostPath;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier;
 import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
 import org.opendaylight.yangtools.yang.data.impl.schema.ResultAlreadySetException;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,11 +39,10 @@ public final class JsonChildBody extends ChildBody {
 
     @Override
     @SuppressWarnings("checkstyle:illegalCatch")
-    PrefixAndBody toPayload(final InputStream inputStream, final YangInstanceIdentifier parentPath,
-            final Inference parentInference) {
+    PrefixAndBody toPayload(final DataPostPath path, final InputStream inputStream) {
         NormalizedNode result;
         try {
-            result = toNormalizedNode(inputStream, parentInference);
+            result = toNormalizedNode(path, inputStream);
         } catch (Exception e) {
             Throwables.throwIfInstanceOf(e, RestconfDocumentedException.class);
             LOG.debug("Error parsing json input", e);
@@ -77,11 +74,10 @@ public final class JsonChildBody extends ChildBody {
         return new PrefixAndBody(iiToDataList.build(), result);
     }
 
-    private static @NonNull NormalizedNode toNormalizedNode(final InputStream inputStream, final Inference inference) {
+    private static @NonNull NormalizedNode toNormalizedNode(final DataPostPath path, final InputStream inputStream) {
         final var resultHolder = new NormalizationResultHolder();
         final var writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
-        final var jsonParser = JsonParserStream.create(writer,
-            JSONCodecFactorySupplier.RFC7951.getShared(inference.getEffectiveModelContext()), inference);
+        final var jsonParser = JsonParserStream.create(writer, path.databind().jsonCodecs(), path.inference());
         final var reader = new JsonReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
         jsonParser.parse(reader);
 
index ca7f84a40db287857e5576f59a4f2991e37cebaf..4c843d1c1081675980027d363af3f89992147d3e 100644 (file)
@@ -17,12 +17,12 @@ import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.dom.DOMSource;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.server.api.DataPostPath;
 import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.XMLNamespace;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
@@ -30,10 +30,8 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeS
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContext;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContext.PathMixin;
-import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -48,10 +46,9 @@ public final class XmlChildBody extends ChildBody {
 
     @Override
     @SuppressWarnings("checkstyle:illegalCatch")
-    PrefixAndBody toPayload(final InputStream inputStream, final YangInstanceIdentifier parentPath,
-            final Inference parentInference) {
+    PrefixAndBody toPayload(final DataPostPath path, final InputStream inputStream) {
         try {
-            return parse(parentPath, parentInference, UntrustedXML.newDocumentBuilder().parse(inputStream));
+            return parse(path, UntrustedXML.newDocumentBuilder().parse(inputStream));
         } catch (final RestconfDocumentedException e) {
             throw e;
         } catch (final Exception e) {
@@ -62,8 +59,10 @@ public final class XmlChildBody extends ChildBody {
         }
     }
 
-    private static @NonNull PrefixAndBody parse(final YangInstanceIdentifier path, final Inference pathInference,
-            final Document doc) throws XMLStreamException, IOException, SAXException, URISyntaxException {
+    private static @NonNull PrefixAndBody parse(final DataPostPath path, final Document doc)
+            throws XMLStreamException, IOException, SAXException, URISyntaxException {
+        final var pathInference = path.inference();
+
         final DataSchemaNode parentNode;
         if (pathInference.isEmpty()) {
             parentNode = pathInference.getEffectiveModelContext();
@@ -86,7 +85,9 @@ public final class XmlChildBody extends ChildBody {
         final var qname = QName.create(it.next().localQNameModule(), docRootElm);
 
         final var iiToDataList = ImmutableList.<PathArgument>builder();
-        final var nodeAndStack = DataSchemaContextTree.from(context).enterPath(path).orElseThrow();
+        // FIXME: we should have this readily available: it is the last node the ApiPath->YangInstanceIdentifier parser
+        //        has seen (and it should have the nodeAndStack handy
+        final var nodeAndStack = path.databind().schemaTree().enterPath(path.instance()).orElseThrow();
         final var stack = nodeAndStack.stack();
         var current = nodeAndStack.node();
         do {
@@ -110,7 +111,7 @@ public final class XmlChildBody extends ChildBody {
         final var resultHolder = new NormalizationResultHolder();
         final var writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
 
-        final var xmlParser = XmlParserStream.create(writer, stack.toInference());
+        final var xmlParser = XmlParserStream.create(writer, path.databind().xmlCodecs(), stack.toInference());
         xmlParser.traverse(new DOMSource(doc.getDocumentElement()));
         var parsed = resultHolder.getResult().data();
 
diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/api/DataPostPath.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/api/DataPostPath.java
new file mode 100644 (file)
index 0000000..ce0dd78
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 PANTHEON.tech, 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.restconf.server.api;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.restconf.api.ApiPath;
+import org.opendaylight.restconf.nb.rfc8040.databind.DataPostBody;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
+
+/**
+ * An {@link ApiPath} subpath of {@code /data} {@code POST} HTTP operation, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.4">RFC8040 section 4.4</a>.
+ *
+ * @param databind Associated {@link DatabindContext}
+ * @param inference Associated {@link Inference} pointing to the {@link EffectiveStatement} of the last ApiPath element.
+ *                  This can be one of:
+ *                  <ul>
+ *                    <li>a datatore, inference being {@link Inference#isEmpty() empty}</li>
+ *                    <li>a data resource, inference pointing to the the {@code data schema node} identified by
+ *                        {@code instance}</li>
+ *                    <li>an {@code rpc} or an {@code action} invocation, inference pointing to the statement</li>
+ *                  </ul>
+ * @param instance Associated {@link YangInstanceIdentifier}
+ * @see DataPostBody
+ */
+@NonNullByDefault
+public record DataPostPath(DatabindContext databind, Inference inference, YangInstanceIdentifier instance)
+        implements DatabindAware {
+    public DataPostPath {
+        requireNonNull(databind);
+        requireNonNull(inference);
+        requireNonNull(instance);
+    }
+}
index 27e3d8f2e9f123c59f8bd8ab37f60516e8cd6a2e..e969b9115e8a0f3c48a93c9d4e8f93de0e8a1e63 100644 (file)
@@ -69,6 +69,7 @@ import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStra
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.NetconfFieldsTranslator;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.WriterFieldsTranslator;
+import org.opendaylight.restconf.server.api.DataPostPath;
 import org.opendaylight.restconf.server.api.DataPostResult;
 import org.opendaylight.restconf.server.api.DataPostResult.CreateResource;
 import org.opendaylight.restconf.server.api.DataPostResult.InvokeOperation;
@@ -331,18 +332,19 @@ public final class MdsalRestconfServer
 
     private @NonNull RestconfFuture<CreateResource> dataCreatePOST(final InstanceIdentifierContext reqPath,
             final ChildBody body, final Map<String, String> queryParameters) {
+        final var postPath = new DataPostPath(reqPath.databind(), reqPath.inference(), reqPath.getInstanceIdentifier());
+
         final Insert insert;
         try {
-            insert = Insert.ofQueryParameters(reqPath.databind(), queryParameters);
+            insert = Insert.ofQueryParameters(postPath.databind(), queryParameters);
         } catch (IllegalArgumentException e) {
             return RestconfFuture.failed(new RestconfDocumentedException(e.getMessage(),
                 ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, e));
         }
 
-        final var parentPath = reqPath.getInstanceIdentifier();
-        final var payload = body.toPayload(parentPath, reqPath.inference());
+        final var payload = body.toPayload(postPath);
         return getRestconfStrategy(reqPath.databind(), reqPath.getMountPoint())
-            .postData(concat(parentPath, payload.prefix()), payload.body(), insert);
+            .postData(concat(postPath.instance(), payload.prefix()), payload.body(), insert);
     }
 
     private static YangInstanceIdentifier concat(final YangInstanceIdentifier parent, final List<PathArgument> args) {
index 32f89de38293f80ff26c07d683fbe8b7e381f453..0db038732a8a75b9278fade98fc5daf173a2db4f 100644 (file)
@@ -7,37 +7,40 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.databind;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.List;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.opendaylight.restconf.server.api.DataPostPath;
+import org.opendaylight.restconf.server.api.DatabindContext;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
-public class JsonChildBodyTest extends AbstractBodyTest {
-    private static EffectiveModelContext schemaContext;
+class JsonChildBodyTest extends AbstractBodyTest {
+    private static DataPostPath CONT_PATH;
 
-    @BeforeClass
-    public static void initialization() throws Exception {
+    @BeforeAll
+    static void beforeAll() throws Exception {
         final var testFiles = loadFiles("/instanceidentifier/yang");
         testFiles.addAll(loadFiles("/modules"));
-        schemaContext = YangParserTestUtils.parseYangFiles(testFiles);
+        final var modelContext = YangParserTestUtils.parseYangFiles(testFiles);
+
+        CONT_PATH = new DataPostPath(DatabindContext.ofModel(modelContext),
+            Inference.ofDataTreePath(modelContext, CONT_QNAME), YangInstanceIdentifier.of(CONT_QNAME));
     }
 
     @Test
-    public void moduleSubContainerDataPostTest() throws Exception {
+    void moduleSubContainerDataPostTest() {
         final var body = new JsonChildBody(
             JsonChildBodyTest.class.getResourceAsStream("/instanceidentifier/json/json_sub_container.json"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(CONT_QNAME),
-            Inference.ofDataTreePath(schemaContext, CONT_QNAME));
+        final var payload = body.toPayload(CONT_PATH);
 
         final var lflst11 = QName.create("augment:module:leaf:list", "2014-01-27", "lflst11");
         assertEquals(List.of(new NodeIdentifier(CONT1_QNAME)), payload.prefix());
@@ -53,11 +56,10 @@ public class JsonChildBodyTest extends AbstractBodyTest {
     }
 
     @Test
-    public void moduleSubContainerAugmentDataPostTest() throws Exception {
+    void moduleSubContainerAugmentDataPostTest() {
         final var body = new JsonChildBody(
             JsonChildBodyTest.class.getResourceAsStream("/instanceidentifier/json/json_augment_container.json"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(CONT_QNAME),
-            Inference.ofDataTreePath(schemaContext, CONT_QNAME));
+        final var payload = body.toPayload(CONT_PATH);
 
         final var contAugment = QName.create("augment:module", "2014-01-17", "cont-augment");
         assertEquals(List.of(new NodeIdentifier(contAugment)), payload.prefix());
@@ -68,11 +70,10 @@ public class JsonChildBodyTest extends AbstractBodyTest {
     }
 
     @Test
-    public void moduleSubContainerChoiceAugmentDataPostTest() throws Exception {
+    void moduleSubContainerChoiceAugmentDataPostTest() {
         final var body = new JsonChildBody(
             JsonChildBodyTest.class.getResourceAsStream("/instanceidentifier/json/json_augment_choice_container.json"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(new NodeIdentifier(CONT_QNAME)),
-            Inference.ofDataTreePath(schemaContext, CONT_QNAME));
+        final var payload = body.toPayload(CONT_PATH);
 
         final var container1 = QName.create("augment:module", "2014-01-17", "case-choice-case-container1");
         assertEquals(List.of(
index e845f1bfb7207aa6706d1c1c62f048088afb82c3..690aa16e20d9288aeea0c221e54a7d222fdcd476 100644 (file)
@@ -7,11 +7,13 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.databind;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.List;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.opendaylight.restconf.server.api.DataPostPath;
+import org.opendaylight.restconf.server.api.DatabindContext;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -19,27 +21,32 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
-public class XmlChildBodyTest extends AbstractBodyTest {
+class XmlChildBodyTest extends AbstractBodyTest {
     private static final QName TOP_LEVEL_LIST = QName.create("foo", "2017-08-09", "top-level-list");
 
-    private static EffectiveModelContext schemaContext;
+    private static DataPostPath EMPTY_PATH;
+    private static DataPostPath CONT_PATH;
 
-    @BeforeClass
-    public static void initialization() throws Exception {
+    @BeforeAll
+    static void beforeAll() throws Exception {
         final var testFiles = loadFiles("/instanceidentifier/yang");
         testFiles.addAll(loadFiles("/modules"));
         testFiles.addAll(loadFiles("/foo-xml-test/yang"));
-        schemaContext = YangParserTestUtils.parseYangFiles(testFiles);
+        final var modelContext = YangParserTestUtils.parseYangFiles(testFiles);
+
+        CONT_PATH = new DataPostPath(DatabindContext.ofModel(modelContext),
+            Inference.ofDataTreePath(modelContext, CONT_QNAME), YangInstanceIdentifier.of(CONT_QNAME));
+        EMPTY_PATH = new DataPostPath(DatabindContext.ofModel(modelContext),
+            Inference.ofDataTreePath(modelContext), YangInstanceIdentifier.of());
     }
 
     @Test
-    public void postXmlTest() throws Exception {
+    void postXmlTest() {
         final var body = new XmlChildBody(XmlChildBodyTest.class.getResourceAsStream("/foo-xml-test/foo.xml"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(), Inference.ofDataTreePath(schemaContext));
+        final var payload = body.toPayload(EMPTY_PATH);
 
         final var entryId = NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST,
             QName.create(TOP_LEVEL_LIST, "key-leaf"), "key-value");
@@ -52,11 +59,10 @@ public class XmlChildBodyTest extends AbstractBodyTest {
     }
 
     @Test
-    public void moduleSubContainerDataPostTest() throws Exception {
+    void moduleSubContainerDataPostTest() {
         final var body = new XmlChildBody(
             XmlChildBodyTest.class.getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(CONT_QNAME),
-            Inference.ofDataTreePath(schemaContext, CONT_QNAME));
+        final var payload = body.toPayload(CONT_PATH);
 
         final var lflst11 = QName.create("augment:module:leaf:list", "2014-01-27", "lflst11");
         assertEquals(List.of(new NodeIdentifier(CONT1_QNAME)), payload.prefix());
@@ -77,11 +83,10 @@ public class XmlChildBodyTest extends AbstractBodyTest {
     }
 
     @Test
-    public void moduleSubContainerAugmentDataPostTest() throws Exception {
+    void moduleSubContainerAugmentDataPostTest() {
         final var body = new XmlChildBody(
             XmlChildBodyTest.class.getResourceAsStream("/instanceidentifier/xml/xml_augment_container.xml"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(CONT_QNAME),
-            Inference.ofDataTreePath(schemaContext, CONT_QNAME));
+        final var payload = body.toPayload(CONT_PATH);
 
         final var contAugment = QName.create("augment:module", "2014-01-17", "cont-augment");
         assertEquals(List.of(new NodeIdentifier(contAugment)), payload.prefix());
@@ -92,11 +97,10 @@ public class XmlChildBodyTest extends AbstractBodyTest {
     }
 
     @Test
-    public void moduleSubContainerChoiceAugmentDataPostTest() throws Exception {
+    void moduleSubContainerChoiceAugmentDataPostTest() {
         final var body = new XmlChildBody(
             XmlChildBodyTest.class.getResourceAsStream("/instanceidentifier/xml/xml_augment_choice_container.xml"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(CONT_QNAME),
-            Inference.ofDataTreePath(schemaContext, CONT_QNAME));
+        final var payload = body.toPayload(CONT_PATH);
 
         final var container1 = QName.create("augment:module", "2014-01-17", "case-choice-case-container1");
         assertEquals(List.of(
@@ -115,10 +119,10 @@ public class XmlChildBodyTest extends AbstractBodyTest {
      * name, but also by correct namespace used in payload.
      */
     @Test
-    public void findFooContainerUsingNamespaceTest() throws Exception {
+    void findFooContainerUsingNamespaceTest() {
         final var body = new XmlChildBody(
             XmlChildBodyTest.class.getResourceAsStream("/instanceidentifier/xml/xmlDataFindFooContainer.xml"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(), Inference.ofDataTreePath(schemaContext));
+        final var payload = body.toPayload(EMPTY_PATH);
 
         final var fooBarContainer = new NodeIdentifier(QName.create("foo:module", "2016-09-29", "foo-bar-container"));
         assertEquals(List.of(fooBarContainer), payload.prefix());
@@ -132,10 +136,10 @@ public class XmlChildBodyTest extends AbstractBodyTest {
      * name, but also by correct namespace used in payload.
      */
     @Test
-    public void findBarContainerUsingNamespaceTest() throws Exception {
+    void findBarContainerUsingNamespaceTest() {
         final var body = new XmlChildBody(
             XmlChildBodyTest.class.getResourceAsStream("/instanceidentifier/xml/xmlDataFindBarContainer.xml"));
-        final var payload = body.toPayload(YangInstanceIdentifier.of(), Inference.ofDataTreePath(schemaContext));
+        final var payload = body.toPayload(EMPTY_PATH);
 
         final var fooBarContainer = new NodeIdentifier(QName.create("bar:module", "2016-09-29", "foo-bar-container"));
         assertEquals(List.of(fooBarContainer), payload.prefix());