Do not reference individual builders
[netconf.git] / netconf / sal-netconf-connector / src / test / java / org / opendaylight / netconf / sal / connect / netconf / schema / mapping / NetconfMessageTransformerTest.java
index 4a1fbc7bbf510e03e839cc3349a2be8941a6f69b..533c31f6e0a47f3d2743b38f4079a712f0c3a67a 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.netconf.sal.connect.netconf.schema.mapping;
 
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.CREATE_SUBSCRIPTION_RPC_CONTENT;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.CREATE_SUBSCRIPTION_RPC_QNAME;
@@ -26,14 +27,12 @@ import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTr
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.createEditConfigStructure;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toId;
-import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
 import static org.opendaylight.netconf.util.NetconfUtil.NETCONF_DATA_QNAME;
 
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -49,22 +48,33 @@ import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
 import org.opendaylight.mdsal.dom.api.DOMActionResult;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.api.xml.XmlUtil;
+import org.opendaylight.netconf.sal.connect.netconf.AbstractBaseSchemasTest;
 import org.opendaylight.netconf.sal.connect.netconf.schema.NetconfRemoteSchemaYangSourceProvider;
+import org.opendaylight.netconf.sal.connect.netconf.util.FieldsFilter;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.netconf.util.NetconfUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.$YangModuleInfoImpl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.IetfNetconfService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Datastores;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Statistics;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.datastores.Datastore;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.datastores.datastore.Locks;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.datastores.datastore.locks.lock.type.partial.lock.PartialLock;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
-import org.opendaylight.yangtools.rcf8528.data.util.EmptyMountPointContext;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfConfigChange;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.netconf.config.change.Edit;
+import org.opendaylight.yangtools.rfc8528.data.util.EmptyMountPointContext;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
@@ -72,25 +82,24 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyxmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DOMSourceAnyxmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
 
-public class NetconfMessageTransformerTest {
+public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
 
     private static final String REVISION_EXAMPLE_SERVER_FARM = "2018-08-07";
     private static final String URN_EXAMPLE_SERVER_FARM = "urn:example:server-farm";
@@ -100,65 +109,79 @@ public class NetconfMessageTransformerTest {
 
     private static final String URN_EXAMPLE_CONFLICT = "urn:example:conflict";
 
+    private static final String URN_EXAMPLE_AUGMENTED_ACTION = "urn:example:augmented-action";
+
+    private static final String URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS = "urn:example:rpcs-actions-outputs";
+
     private static final QName SERVER_QNAME =
             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "server");
     private static final QName RESET_QNAME = QName.create(SERVER_QNAME, "reset");
-    private static final SchemaPath RESET_SERVER_PATH = SchemaPath.create(true, SERVER_QNAME, RESET_QNAME);
+    private static final Absolute RESET_SERVER_PATH = Absolute.of(SERVER_QNAME, RESET_QNAME);
     private static final QName APPLICATIONS_QNAME = QName.create(URN_EXAMPLE_SERVER_FARM_2,
             REVISION_EXAMPLE_SERVER_FARM_2, "applications");
     private static final QName APPLICATION_QNAME = QName.create(APPLICATIONS_QNAME, "application");
     private static final QName KILL_QNAME = QName.create(APPLICATION_QNAME, "kill");
-    private static final SchemaPath KILL_SERVER_APP_PATH =
-            SchemaPath.create(true, SERVER_QNAME, APPLICATIONS_QNAME, APPLICATION_QNAME, KILL_QNAME);
+    private static final Absolute KILL_SERVER_APP_PATH =
+            Absolute.of(SERVER_QNAME, APPLICATIONS_QNAME, APPLICATION_QNAME, KILL_QNAME);
 
     private static final QName DEVICE_QNAME =
             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "device");
     private static final QName START_QNAME = QName.create(DEVICE_QNAME, "start");
-    private static final SchemaPath START_DEVICE_PATH = SchemaPath.create(true, DEVICE_QNAME, START_QNAME);
+    private static final Absolute START_DEVICE_PATH = Absolute.of(DEVICE_QNAME, START_QNAME);
     private static final QName INTERFACE_QNAME = QName.create(DEVICE_QNAME, "interface");
     private static final QName ENABLE_QNAME = QName.create(INTERFACE_QNAME, "enable");
-    private static final SchemaPath ENABLE_INTERFACE_PATH =
-            SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, ENABLE_QNAME);
+    private static final Absolute ENABLE_INTERFACE_PATH = Absolute.of(DEVICE_QNAME, INTERFACE_QNAME, ENABLE_QNAME);
+
+    private static final QName DISABLE_QNAME = QName.create(URN_EXAMPLE_AUGMENTED_ACTION, "disable");
+    private static final Absolute DISABLE_INTERFACE_PATH = Absolute.of(DEVICE_QNAME, INTERFACE_QNAME, DISABLE_QNAME);
+
+    private static final QName CHECK_WITH_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "check-with-output");
+    private static final Absolute CHECK_WITH_OUTPUT_INTERFACE_PATH =
+            Absolute.of(DEVICE_QNAME, INTERFACE_QNAME, CHECK_WITH_OUTPUT_QNAME);
+    private static final QName CHECK_WITHOUT_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "check-without-output");
+    private static final Absolute CHECK_WITHOUT_OUTPUT_INTERFACE_PATH =
+            Absolute.of(DEVICE_QNAME, INTERFACE_QNAME, CHECK_WITHOUT_OUTPUT_QNAME);
+    private static final QName RPC_WITH_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "rpc-with-output");
+    private static final QName RPC_WITHOUT_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "rpc-without-output");
 
     private static final QName BOX_OUT_QNAME =
             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "box-out");
     private static final QName BOX_IN_QNAME = QName.create(BOX_OUT_QNAME, "box-in");
     private static final QName OPEN_QNAME = QName.create(BOX_IN_QNAME, "open");
-    private static final SchemaPath OPEN_BOXES_PATH =
-            SchemaPath.create(true, BOX_OUT_QNAME, BOX_IN_QNAME, OPEN_QNAME);
+    private static final Absolute OPEN_BOXES_PATH = Absolute.of(BOX_OUT_QNAME, BOX_IN_QNAME, OPEN_QNAME);
 
     private static final QName FOO_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "foo");
     private static final QName BAR_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "bar");
     private static final QName XYZZY_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "xyzzy");
-    private static final SchemaPath XYZZY_FOO_PATH = SchemaPath.create(true, FOO_QNAME, XYZZY_QNAME);
-    private static final SchemaPath XYZZY_BAR_PATH = SchemaPath.create(true, BAR_QNAME, XYZZY_QNAME);
+    private static final Absolute XYZZY_FOO_PATH = Absolute.of(FOO_QNAME, XYZZY_QNAME);
+    private static final Absolute XYZZY_BAR_PATH = Absolute.of(BAR_QNAME, XYZZY_QNAME);
 
     private static final QName CONFLICT_CHOICE_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "conflict-choice");
     private static final QName CHOICE_CONT_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "choice-cont");
     private static final QName CHOICE_ACTION_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "choice-action");
-    private static final SchemaPath CHOICE_ACTION_PATH =
-            SchemaPath.create(true, CONFLICT_CHOICE_QNAME, CHOICE_CONT_QNAME, CHOICE_CONT_QNAME, CHOICE_ACTION_QNAME);
+    private static final Absolute CHOICE_ACTION_PATH =
+            Absolute.of(CONFLICT_CHOICE_QNAME, CHOICE_CONT_QNAME, CHOICE_CONT_QNAME, CHOICE_ACTION_QNAME);
 
-    private static SchemaContext PARTIAL_SCHEMA;
-    private static SchemaContext SCHEMA;
-    private static SchemaContext ACTION_SCHEMA;
+    private static EffectiveModelContext PARTIAL_SCHEMA;
+    private static EffectiveModelContext SCHEMA;
+    private static EffectiveModelContext ACTION_SCHEMA;
 
     private NetconfMessageTransformer actionNetconfMessageTransformer;
     private NetconfMessageTransformer netconfMessageTransformer;
 
     @BeforeClass
     public static void beforeClass() {
-        final ModuleInfoBackedContext context = ModuleInfoBackedContext.create();
-        context.addModuleInfos(Collections.singleton(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
-            .netconf.monitoring.rev101004.$YangModuleInfoImpl.getInstance()));
-        PARTIAL_SCHEMA = context.tryToCreateSchemaContext().get();
-
-        context.addModuleInfos(Collections.singleton($YangModuleInfoImpl.getInstance()));
-        SCHEMA = context.tryToCreateSchemaContext().get();
-
+        PARTIAL_SCHEMA = BindingRuntimeHelpers.createEffectiveModel(NetconfState.class);
+        SCHEMA = BindingRuntimeHelpers.createEffectiveModel(IetfNetconfService.class, NetconfState.class,
+            NetconfConfigChange.class);
         ACTION_SCHEMA = YangParserTestUtils.parseYangResources(NetconfMessageTransformerTest.class,
             "/schemas/example-server-farm.yang","/schemas/example-server-farm-2.yang",
-            "/schemas/conflicting-actions.yang");
+            "/schemas/conflicting-actions.yang", "/schemas/augmented-action.yang",
+            "/schemas/rpcs-actions-outputs.yang");
     }
 
     @AfterClass
@@ -176,13 +199,13 @@ public class NetconfMessageTransformerTest {
 
         netconfMessageTransformer = getTransformer(SCHEMA);
         actionNetconfMessageTransformer = new NetconfMessageTransformer(new EmptyMountPointContext(ACTION_SCHEMA),
-            true);
+            true, BASE_SCHEMAS.getBaseSchema());
     }
 
     @Test
     public void testLockRequestBaseSchemaNotPresent() throws Exception {
         final NetconfMessageTransformer transformer = getTransformer(PARTIAL_SCHEMA);
-        final NetconfMessage netconfMessage = transformer.toRpcRequest(toPath(NETCONF_LOCK_QNAME),
+        final NetconfMessage netconfMessage = transformer.toRpcRequest(NETCONF_LOCK_QNAME,
                 NetconfBaseOps.getLockContent(NETCONF_CANDIDATE_QNAME));
 
         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<lock"));
@@ -192,11 +215,9 @@ public class NetconfMessageTransformerTest {
     @Test
     public void testCreateSubscriberNotificationSchemaNotPresent() throws Exception {
         final NetconfMessageTransformer transformer = new NetconfMessageTransformer(new EmptyMountPointContext(SCHEMA),
-            true, BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS);
-        NetconfMessage netconfMessage = transformer.toRpcRequest(
-                toPath(CREATE_SUBSCRIPTION_RPC_QNAME),
-                CREATE_SUBSCRIPTION_RPC_CONTENT
-        );
+            true, BASE_SCHEMAS.getBaseSchemaWithNotifications());
+        NetconfMessage netconfMessage = transformer.toRpcRequest(CREATE_SUBSCRIPTION_RPC_QNAME,
+                CREATE_SUBSCRIPTION_RPC_CONTENT);
         String documentString = XmlUtil.toString(netconfMessage.getDocument());
         assertThat(documentString, CoreMatchers.containsString("<create-subscription"));
         assertThat(documentString, CoreMatchers.containsString("<rpc"));
@@ -207,13 +228,31 @@ public class NetconfMessageTransformerTest {
         final NetconfMessageTransformer transformer = getTransformer(PARTIAL_SCHEMA);
         final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
 
-        transformer.toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)), toPath(NETCONF_LOCK_QNAME));
+        transformer.toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)), NETCONF_LOCK_QNAME);
+    }
+
+    @Test
+    public void testRpcEmptyBodyWithOutputDefinedSchemaResult() throws Exception {
+        final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
+
+        DOMRpcResult domRpcResult = actionNetconfMessageTransformer
+                .toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)), RPC_WITH_OUTPUT_QNAME);
+        assertNotNull(domRpcResult);
+    }
+
+    @Test
+    public void testRpcEmptyBodyWithoutOutputDefinedSchemaResult() throws Exception {
+        final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
+
+        DOMRpcResult domRpcResult = actionNetconfMessageTransformer
+                .toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)), RPC_WITHOUT_OUTPUT_QNAME);
+        assertNotNull(domRpcResult);
     }
 
     @Test
     public void testDiscardChangesRequest() throws Exception {
         final NetconfMessage netconfMessage =
-                netconfMessageTransformer.toRpcRequest(toPath(NETCONF_DISCARD_CHANGES_QNAME), null);
+                netconfMessageTransformer.toRpcRequest(NETCONF_DISCARD_CHANGES_QNAME, null);
         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<discard"));
         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<rpc"));
         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("message-id"));
@@ -221,7 +260,7 @@ public class NetconfMessageTransformerTest {
 
     @Test
     public void testGetSchemaRequest() throws Exception {
-        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(GET_SCHEMA_QNAME),
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(GET_SCHEMA_QNAME,
                 NetconfRemoteSchemaYangSourceProvider.createGetSchemaRequest("module", Optional.of("2012-12-12")));
         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
                 + "<get-schema xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
@@ -246,11 +285,11 @@ public class NetconfMessageTransformerTest {
                         + "</data>\n"
                         + "</rpc-reply>"
         ));
-        final DOMRpcResult compositeNodeRpcResult = transformer.toRpcResult(response, toPath(GET_SCHEMA_QNAME));
+        final DOMRpcResult compositeNodeRpcResult = transformer.toRpcResult(response, GET_SCHEMA_QNAME);
         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
         assertNotNull(compositeNodeRpcResult.getResult());
-        final DOMSource schemaContent =
-            ((AnyXmlNode) ((ContainerNode) compositeNodeRpcResult.getResult()).getValue().iterator().next()).getValue();
+        final DOMSource schemaContent = ((DOMSourceAnyxmlNode) ((ContainerNode) compositeNodeRpcResult.getResult())
+                .body().iterator().next()).body();
         assertThat(schemaContent.getNode().getTextContent(),
                 CoreMatchers.containsString("Random YANG SCHEMA"));
     }
@@ -273,18 +312,17 @@ public class NetconfMessageTransformerTest {
                 + "</rpc-reply>"));
 
         final NetconfMessageTransformer transformer = getTransformer(SCHEMA);
-        final DOMRpcResult compositeNodeRpcResult =
-                transformer.toRpcResult(response, toPath(NETCONF_GET_CONFIG_QNAME));
+        final DOMRpcResult compositeNodeRpcResult = transformer.toRpcResult(response, NETCONF_GET_CONFIG_QNAME);
         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
         assertNotNull(compositeNodeRpcResult.getResult());
 
-        final List<DataContainerChild<?, ?>> values = Lists.newArrayList(
+        final List<DataContainerChild> values = Lists.newArrayList(
                 NetconfRemoteSchemaYangSourceProvider
-                        .createGetSchemaRequest("module", Optional.of("2012-12-12")).getValue());
+                        .createGetSchemaRequest("module", Optional.of("2012-12-12")).body());
 
         final Map<QName, Object> keys = new HashMap<>();
-        for (final DataContainerChild<?, ?> value : values) {
-            keys.put(value.getNodeType(), value.getValue());
+        for (final DataContainerChild value : values) {
+            keys.put(value.getIdentifier().getNodeType(), value.body());
         }
 
         final NodeIdentifierWithPredicates identifierWithPredicates =
@@ -292,30 +330,30 @@ public class NetconfMessageTransformerTest {
         final MapEntryNode schemaNode =
                 Builders.mapEntryBuilder().withNodeIdentifier(identifierWithPredicates).withValue(values).build();
 
-        final AnyXmlNode data = (AnyXmlNode) ((ContainerNode) compositeNodeRpcResult
-                .getResult()).getChild(toId(NETCONF_DATA_QNAME)).get();
+        final DOMSourceAnyxmlNode data = (DOMSourceAnyxmlNode) ((ContainerNode) compositeNodeRpcResult.getResult())
+                .findChildByArg(toId(NETCONF_DATA_QNAME)).get();
 
         NormalizedNodeResult nodeResult =
-                NetconfUtil.transformDOMSourceToNormalizedNode(SCHEMA, data.getValue());
+                NetconfUtil.transformDOMSourceToNormalizedNode(SCHEMA, data.body());
         ContainerNode result = (ContainerNode) nodeResult.getResult();
-        final ContainerNode state = (ContainerNode) result.getChild(toId(NetconfState.QNAME)).get();
-        final ContainerNode schemas = (ContainerNode) state.getChild(toId(Schemas.QNAME)).get();
-        final MapNode schemaParent = (MapNode) schemas.getChild(toId(Schema.QNAME)).get();
-        assertEquals(1, Iterables.size(schemaParent.getValue()));
+        final ContainerNode state = (ContainerNode) result.findChildByArg(toId(NetconfState.QNAME)).get();
+        final ContainerNode schemas = (ContainerNode) state.findChildByArg(toId(Schemas.QNAME)).get();
+        final MapNode schemaParent = (MapNode) schemas.findChildByArg(toId(Schema.QNAME)).get();
+        assertEquals(1, Iterables.size(schemaParent.body()));
 
-        assertEquals(schemaNode, schemaParent.getValue().iterator().next());
+        assertEquals(schemaNode, schemaParent.body().iterator().next());
     }
 
     @Test
     public void testGetConfigLeafRequest() throws Exception {
-        final DataContainerChild<?, ?> filter = toFilterStructure(
+        final AnyxmlNode<?> filter = toFilterStructure(
                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Schemas.QNAME), toId(Schema.QNAME),
                     NodeIdentifierWithPredicates.of(Schema.QNAME),
                     toId(QName.create(Schemas.QNAME, "version"))), SCHEMA);
 
-        final DataContainerChild<?, ?> source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
+        final ContainerNode source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
 
-        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_CONFIG_QNAME),
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_CONFIG_QNAME,
                 NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, source, filter));
 
         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
@@ -338,12 +376,12 @@ public class NetconfMessageTransformerTest {
 
     @Test
     public void testGetConfigRequest() throws Exception {
-        final DataContainerChild<?, ?> filter = toFilterStructure(
+        final AnyxmlNode<?> filter = toFilterStructure(
                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Schemas.QNAME)), SCHEMA);
 
-        final DataContainerChild<?, ?> source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
+        final ContainerNode source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
 
-        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_CONFIG_QNAME),
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_CONFIG_QNAME,
                 NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, source, filter));
 
         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
@@ -362,13 +400,13 @@ public class NetconfMessageTransformerTest {
 
     @Test
     public void testEditConfigRequest() throws Exception {
-        final List<DataContainerChild<?, ?>> values = Lists.newArrayList(
+        final List<DataContainerChild> values = Lists.newArrayList(
                 NetconfRemoteSchemaYangSourceProvider
-                        .createGetSchemaRequest("module", Optional.of("2012-12-12")).getValue());
+                        .createGetSchemaRequest("module", Optional.of("2012-12-12")).body());
 
         final Map<QName, Object> keys = new HashMap<>();
-        for (final DataContainerChild<?, ?> value : values) {
-            keys.put(value.getNodeType(), value.getValue());
+        for (final DataContainerChild value : values) {
+            keys.put(value.getIdentifier().getNodeType(), value.body());
         }
 
         final NodeIdentifierWithPredicates identifierWithPredicates =
@@ -379,16 +417,15 @@ public class NetconfMessageTransformerTest {
         final YangInstanceIdentifier id = YangInstanceIdentifier.builder()
                 .node(NetconfState.QNAME).node(Schemas.QNAME).node(Schema.QNAME)
                 .nodeWithKey(Schema.QNAME, keys).build();
-        final DataContainerChild<?, ?> editConfigStructure =
-                createEditConfigStructure(BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS.getSchemaContext(), id,
+        final DataContainerChild editConfigStructure =
+                createEditConfigStructure(BASE_SCHEMAS.getBaseSchemaWithNotifications().getEffectiveModelContext(), id,
                     Optional.empty(), Optional.ofNullable(schemaNode));
 
-        final DataContainerChild<?, ?> target = NetconfBaseOps.getTargetNode(NETCONF_CANDIDATE_QNAME);
+        final DataContainerChild target = NetconfBaseOps.getTargetNode(NETCONF_CANDIDATE_QNAME);
 
         final ContainerNode wrap =
                 NetconfMessageTransformUtil.wrap(NETCONF_EDIT_CONFIG_QNAME, editConfigStructure, target);
-        final NetconfMessage netconfMessage =
-                netconfMessageTransformer.toRpcRequest(toPath(NETCONF_EDIT_CONFIG_QNAME), wrap);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_EDIT_CONFIG_QNAME, wrap);
 
         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
                 + "<edit-config>\n"
@@ -421,11 +458,11 @@ public class NetconfMessageTransformerTest {
     public void testGetRequest() throws Exception {
 
         final QName capability = QName.create(Capabilities.QNAME, "capability");
-        final DataContainerChild<?, ?> filter = toFilterStructure(
+        final DataContainerChild filter = toFilterStructure(
                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Capabilities.QNAME), toId(capability),
                     new NodeWithValue<>(capability, "a:b:c")), SCHEMA);
 
-        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_QNAME),
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
                 NetconfMessageTransformUtil.wrap(NETCONF_GET_QNAME, filter));
 
         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
@@ -441,8 +478,54 @@ public class NetconfMessageTransformerTest {
                 + "</rpc>");
     }
 
-    private static NetconfMessageTransformer getTransformer(final SchemaContext schema) {
-        return new NetconfMessageTransformer(new EmptyMountPointContext(schema), true);
+    @Test
+    public void testGetLeafList() throws IOException, SAXException {
+        final YangInstanceIdentifier path = YangInstanceIdentifier.create(
+                toId(NetconfState.QNAME),
+                toId(Capabilities.QNAME),
+                toId(QName.create(Capabilities.QNAME, "capability")));
+        final DataContainerChild filter = toFilterStructure(path, SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filter));
+
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<capabilities>\n"
+                + "<capability/>\n"
+                + "</capabilities>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>\n");
+    }
+
+    @Test
+    public void testGetList() throws IOException, SAXException {
+        final YangInstanceIdentifier path = YangInstanceIdentifier.create(
+                toId(NetconfState.QNAME),
+                toId(Datastores.QNAME),
+                toId(QName.create(Datastores.QNAME, "datastore")));
+        final DataContainerChild filter = toFilterStructure(path, SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filter));
+
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<datastores>\n"
+                + "<datastore/>\n"
+                + "</datastores>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>\n");
+    }
+
+    private static NetconfMessageTransformer getTransformer(final EffectiveModelContext schema) {
+        return new NetconfMessageTransformer(new EmptyMountPointContext(schema), true, BASE_SCHEMAS.getBaseSchema());
     }
 
     @Test
@@ -451,14 +534,14 @@ public class NetconfMessageTransformerTest {
                 "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>"
         ));
         final DOMRpcResult compositeNodeRpcResult =
-                netconfMessageTransformer.toRpcResult(response, toPath(NETCONF_COMMIT_QNAME));
+                netconfMessageTransformer.toRpcResult(response, NETCONF_COMMIT_QNAME);
         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
         assertNull(compositeNodeRpcResult.getResult());
     }
 
     @Test
     public void getActionsTest() {
-        Set<SchemaPath> schemaPaths = new HashSet<>();
+        Set<Absolute> schemaPaths = new HashSet<>();
         schemaPaths.add(RESET_SERVER_PATH);
         schemaPaths.add(START_DEVICE_PATH);
         schemaPaths.add(ENABLE_INTERFACE_PATH);
@@ -467,12 +550,15 @@ public class NetconfMessageTransformerTest {
         schemaPaths.add(XYZZY_FOO_PATH);
         schemaPaths.add(XYZZY_BAR_PATH);
         schemaPaths.add(CHOICE_ACTION_PATH);
+        schemaPaths.add(DISABLE_INTERFACE_PATH);
+        schemaPaths.add(CHECK_WITH_OUTPUT_INTERFACE_PATH);
+        schemaPaths.add(CHECK_WITHOUT_OUTPUT_INTERFACE_PATH);
 
-        List<ActionDefinition> actions = NetconfMessageTransformer.getActions(ACTION_SCHEMA);
+        var actions = NetconfMessageTransformer.getActions(ACTION_SCHEMA);
         assertEquals(schemaPaths.size(), actions.size());
-        for (ActionDefinition actionDefinition : actions) {
-            SchemaPath path = actionDefinition.getPath();
-            assertTrue(schemaPaths.remove(path));
+
+        for (var path : schemaPaths) {
+            assertNotNull("Action for " + path + " not found", actions.get(path));
         }
     }
 
@@ -505,10 +591,10 @@ public class NetconfMessageTransformerTest {
 
     @Test
     public void toActionRequestContainerTopLevelTest() {
-        List<PathArgument> nodeIdentifiers = Collections.singletonList(NodeIdentifier.create(DEVICE_QNAME));
+        List<PathArgument> nodeIdentifiers = List.of(NodeIdentifier.create(DEVICE_QNAME));
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
 
-        NormalizedNode<?, ?> payload = initInputAction(QName.create(DEVICE_QNAME, "start-at"), "now");
+        ContainerNode payload = initInputAction(QName.create(DEVICE_QNAME, "start-at"), "now");
         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
                 START_DEVICE_PATH, domDataTreeIdentifier, payload);
 
@@ -528,7 +614,7 @@ public class NetconfMessageTransformerTest {
 
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
 
-        NormalizedNode<?, ?> payload = initInputAction(QName.create(BOX_OUT_QNAME, "start-at"), "now");
+        ContainerNode payload = initInputAction(QName.create(BOX_OUT_QNAME, "start-at"), "now");
         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
                 OPEN_BOXES_PATH, domDataTreeIdentifier, payload);
 
@@ -541,7 +627,7 @@ public class NetconfMessageTransformerTest {
         checkNode(childBoxIn, "box-in", "box-in", URN_EXAMPLE_SERVER_FARM);
 
         Node action = childBoxIn.getFirstChild();
-        checkNode(action, null, OPEN_QNAME.getLocalName(), null);
+        checkNode(action, OPEN_QNAME.getLocalName(), OPEN_QNAME.getLocalName(), OPEN_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -555,7 +641,7 @@ public class NetconfMessageTransformerTest {
 
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
 
-        NormalizedNode<?, ?> payload = initEmptyInputAction(INTERFACE_QNAME);
+        ContainerNode payload = initEmptyInputAction(INTERFACE_QNAME);
         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
                 ENABLE_INTERFACE_PATH, domDataTreeIdentifier, payload);
 
@@ -574,7 +660,8 @@ public class NetconfMessageTransformerTest {
         assertEquals(childTest.getNodeValue(), "test");
 
         Node action = childInterface.getLastChild();
-        checkNode(action, null, ENABLE_QNAME.getLocalName(), null);
+        checkNode(action, ENABLE_QNAME.getLocalName(), ENABLE_QNAME.getLocalName(),
+                ENABLE_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -585,7 +672,7 @@ public class NetconfMessageTransformerTest {
         List<PathArgument> nodeIdentifiers = new ArrayList<>();
         nodeIdentifiers.add(NodeIdentifier.create(SERVER_QNAME));
         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(SERVER_QNAME, serverNameQname, "testServer"));
-        nodeIdentifiers.add(new AugmentationIdentifier(Collections.singleton(APPLICATIONS_QNAME)));
+        nodeIdentifiers.add(new AugmentationIdentifier(Set.of(APPLICATIONS_QNAME)));
         nodeIdentifiers.add(NodeIdentifier.create(APPLICATIONS_QNAME));
         nodeIdentifiers.add(NodeIdentifier.create(APPLICATION_QNAME));
         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(APPLICATION_QNAME,
@@ -593,7 +680,7 @@ public class NetconfMessageTransformerTest {
 
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
 
-        NormalizedNode<?, ?> payload = initEmptyInputAction(APPLICATION_QNAME);
+        ContainerNode payload = initEmptyInputAction(APPLICATION_QNAME);
         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
                 KILL_SERVER_APP_PATH, domDataTreeIdentifier, payload);
 
@@ -622,14 +709,15 @@ public class NetconfMessageTransformerTest {
 
         Node childKillAction = childApplication.getLastChild();
         checkNode(childApplication, "application", "application", URN_EXAMPLE_SERVER_FARM_2);
-        checkNode(childKillAction, null, KILL_QNAME.getLocalName(), null);
+        checkNode(childKillAction, KILL_QNAME.getLocalName(), KILL_QNAME.getLocalName(),
+                KILL_QNAME.getNamespace().toString());
     }
 
     @Test
     public void toActionRequestConflictingInListTest() {
         QName barInputQname = QName.create(BAR_QNAME, "bar");
         QName barIdQname = QName.create(BAR_QNAME, "bar-id");
-        Byte barInput = new Byte("1");
+        Byte barInput = 1;
 
         List<PathArgument> nodeIdentifiers = new ArrayList<>();
         nodeIdentifiers.add(NodeIdentifier.create(BAR_QNAME));
@@ -637,11 +725,10 @@ public class NetconfMessageTransformerTest {
 
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
 
-        ImmutableLeafNodeBuilder<Byte> immutableLeafNodeBuilder = new ImmutableLeafNodeBuilder<>();
-        DataContainerChild<NodeIdentifier, Byte> build = immutableLeafNodeBuilder.withNodeIdentifier(
-                NodeIdentifier.create(barInputQname)).withValue(barInput).build();
-        NormalizedNode<?, ?> payload = ImmutableContainerNodeBuilder.create().withNodeIdentifier(NodeIdentifier.create(
-                QName.create(barInputQname, "input"))).withChild(build).build();
+        ContainerNode payload = Builders.containerBuilder()
+            .withNodeIdentifier(NodeIdentifier.create(QName.create(barInputQname, "input")))
+            .withChild(ImmutableNodes.leafNode(barInputQname, barInput))
+            .build();
 
         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
                 XYZZY_BAR_PATH, domDataTreeIdentifier, payload);
@@ -658,7 +745,8 @@ public class NetconfMessageTransformerTest {
         assertEquals(childTest.getNodeValue(), "test");
 
         Node action = childBar.getLastChild();
-        checkNode(action, null, XYZZY_QNAME.getLocalName(), null);
+        checkNode(action, XYZZY_QNAME.getLocalName(), XYZZY_QNAME.getLocalName(),
+                XYZZY_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -668,7 +756,7 @@ public class NetconfMessageTransformerTest {
         List<PathArgument> nodeIdentifiers = new ArrayList<>();
         nodeIdentifiers.add(NodeIdentifier.create(FOO_QNAME));
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
-        NormalizedNode<?, ?> payload = initInputAction(fooInputQname, "test");
+        ContainerNode payload = initInputAction(fooInputQname, "test");
 
         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
                 XYZZY_FOO_PATH, domDataTreeIdentifier, payload);
@@ -679,7 +767,8 @@ public class NetconfMessageTransformerTest {
         checkNode(childBar, "foo", "foo", URN_EXAMPLE_CONFLICT);
 
         Node action = childBar.getLastChild();
-        checkNode(action, null, XYZZY_QNAME.getLocalName(), null);
+        checkNode(action, XYZZY_QNAME.getLocalName(), XYZZY_QNAME.getLocalName(),
+                XYZZY_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -688,7 +777,7 @@ public class NetconfMessageTransformerTest {
         nodeIdentifiers.add(NodeIdentifier.create(CONFLICT_CHOICE_QNAME));
         nodeIdentifiers.add(NodeIdentifier.create(CHOICE_CONT_QNAME));
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
-        NormalizedNode<?, ?> payload = initEmptyInputAction(CHOICE_ACTION_QNAME);
+        NormalizedNode payload = initEmptyInputAction(CHOICE_ACTION_QNAME);
 
         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
                 CHOICE_ACTION_PATH, domDataTreeIdentifier, payload);
@@ -699,10 +788,44 @@ public class NetconfMessageTransformerTest {
         checkNode(childChoiceCont, "choice-cont", "choice-cont", URN_EXAMPLE_CONFLICT);
 
         Node action = childChoiceCont.getLastChild();
-        checkNode(action, null, CHOICE_ACTION_QNAME.getLocalName(), null);
+        checkNode(action, CHOICE_ACTION_QNAME.getLocalName(), CHOICE_ACTION_QNAME.getLocalName(),
+                CHOICE_ACTION_QNAME.getNamespace().toString());
+    }
+
+    @Test
+    public void toAugmentedActionRequestListInContainerTest() {
+        QName nameQname = QName.create(INTERFACE_QNAME, "name");
+
+        List<PathArgument> nodeIdentifiers = new ArrayList<>();
+        nodeIdentifiers.add(NodeIdentifier.create(DEVICE_QNAME));
+        nodeIdentifiers.add(NodeIdentifier.create(INTERFACE_QNAME));
+        nodeIdentifiers.add(NodeIdentifierWithPredicates.of(INTERFACE_QNAME, nameQname, "test"));
+
+        DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
+
+        NormalizedNode payload = initEmptyInputAction(INTERFACE_QNAME);
+        NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
+                DISABLE_INTERFACE_PATH, domDataTreeIdentifier, payload);
+
+        Node childAction = checkBasePartOfActionRequest(actionRequest);
+
+        Node childDevice = childAction.getFirstChild();
+        checkNode(childDevice, "device", "device", URN_EXAMPLE_SERVER_FARM);
+
+        Node childInterface = childDevice.getFirstChild();
+        checkNode(childInterface, "interface", "interface", URN_EXAMPLE_SERVER_FARM);
+
+        Node childName = childInterface.getFirstChild();
+        checkNode(childName, "name", "name", nameQname.getNamespace().toString());
+
+        Node childTest = childName.getFirstChild();
+        assertEquals(childTest.getNodeValue(), "test");
+
+        Node action = childInterface.getLastChild();
+        checkNode(action, DISABLE_QNAME.getLocalName(), DISABLE_QNAME.getLocalName(),
+                DISABLE_QNAME.getNamespace().toString());
     }
 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
     @Test
     public void toActionResultTest() throws Exception {
         NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
@@ -715,13 +838,304 @@ public class NetconfMessageTransformerTest {
         assertNotNull(actionResult);
         ContainerNode containerNode = actionResult.getOutput().get();
         assertNotNull(containerNode);
-        LeafNode<String> leaf = (LeafNode) containerNode.getValue().iterator().next();
-        assertEquals("now", leaf.getValue());
+        assertEquals("now", containerNode.body().iterator().next().body());
+    }
+
+    @Test
+    public void toActionEmptyBodyWithOutputDefinedResultTest() throws Exception {
+        NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
+                "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
+                + "<ok/>"
+                + "</rpc-reply>"));
+        DOMActionResult actionResult =
+                actionNetconfMessageTransformer.toActionResult(CHECK_WITH_OUTPUT_INTERFACE_PATH, message);
+        assertNotNull(actionResult);
+        assertTrue(actionResult.getOutput().isEmpty());
+    }
+
+    @Test
+    public void toActionEmptyBodyWithoutOutputDefinedResultTest() throws Exception {
+        NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
+                "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
+                + "<ok/>"
+                + "</rpc-reply>"));
+        DOMActionResult actionResult =
+                actionNetconfMessageTransformer.toActionResult(CHECK_WITHOUT_OUTPUT_INTERFACE_PATH, message);
+        assertNotNull(actionResult);
+        assertTrue(actionResult.getOutput().isEmpty());
+    }
+
+    @Test
+    public void getTwoNonOverlappingFieldsTest() throws IOException, SAXException {
+        // preparation of the fields
+        final YangInstanceIdentifier parentYiid = YangInstanceIdentifier.create(toId(NetconfState.QNAME));
+        final YangInstanceIdentifier netconfStartTimeField = YangInstanceIdentifier.create(toId(Statistics.QNAME),
+                toId(QName.create(Statistics.QNAME, "netconf-start-time")));
+        final YangInstanceIdentifier datastoresField = YangInstanceIdentifier.create(toId(Datastores.QNAME));
+
+        // building filter structure and NETCONF message
+        final AnyxmlNode<?> filterStructure = toFilterStructure(
+            List.of(FieldsFilter.of(parentYiid, List.of(netconfStartTimeField, datastoresField))), SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
+
+        // testing
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<statistics>\n"
+                + "<netconf-start-time/>\n"
+                + "</statistics>\n"
+                + "<datastores/>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>");
+    }
+
+    @Test
+    public void getOverlappingFieldsTest() throws IOException, SAXException {
+        // preparation of the fields
+        final YangInstanceIdentifier parentYiid = YangInstanceIdentifier.create(toId(NetconfState.QNAME));
+        final YangInstanceIdentifier capabilitiesField = YangInstanceIdentifier.create(toId(Capabilities.QNAME));
+        final YangInstanceIdentifier capabilityField = YangInstanceIdentifier.create(toId(Capabilities.QNAME),
+                toId(QName.create(Capabilities.QNAME, "capability").intern()));
+        final YangInstanceIdentifier datastoreField = YangInstanceIdentifier.create(toId(Datastores.QNAME));
+        final YangInstanceIdentifier locksFields = YangInstanceIdentifier.create(toId(Datastores.QNAME),
+                toId(Datastore.QNAME), NodeIdentifierWithPredicates.of(Datastore.QNAME), toId(Locks.QNAME));
+
+        // building filter structure and NETCONF message
+        final AnyxmlNode<?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid,
+                    List.of(capabilitiesField, capabilityField, datastoreField, locksFields))),
+                SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
+
+        // testing
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<capabilities/>\n"
+                + "<datastores/>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>");
+    }
+
+    @Test
+    public void getOverlappingFieldsWithEmptyFieldTest() throws IOException, SAXException {
+        // preparation of the fields
+        final YangInstanceIdentifier parentYiid = YangInstanceIdentifier.create(toId(NetconfState.QNAME));
+        final YangInstanceIdentifier capabilitiesField = YangInstanceIdentifier.create(toId(Capabilities.QNAME));
+
+        // building filter structure and NETCONF message
+        final AnyxmlNode<?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid, List.of(capabilitiesField, YangInstanceIdentifier.empty()))),
+                SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
+
+        // testing
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"/>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>");
+    }
+
+    @Test
+    public void getSpecificFieldsUnderListTest() throws IOException, SAXException {
+        // preparation of the fields
+        final YangInstanceIdentifier parentYiid = YangInstanceIdentifier.create(toId(NetconfState.QNAME),
+                toId(Schemas.QNAME), toId(Schema.QNAME), NodeIdentifierWithPredicates.of(Schema.QNAME));
+        final YangInstanceIdentifier versionField = YangInstanceIdentifier.create(
+                toId(QName.create(Schema.QNAME, "version").intern()));
+        final YangInstanceIdentifier identifierField = YangInstanceIdentifier.create(
+                toId(QName.create(Schema.QNAME, "namespace").intern()));
+
+        // building filter structure and NETCONF message
+        final AnyxmlNode<?> filterStructure = toFilterStructure(
+            List.of(FieldsFilter.of(parentYiid, List.of(versionField, identifierField))), SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
+
+        // testing
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<schemas>\n"
+                + "<schema>\n"
+                + "<version/>\n"
+                + "<namespace/>\n"
+                // explicitly fetched list keys - identifier and format
+                + "<identifier/>\n"
+                + "<format/>\n"
+                + "</schema>\n"
+                + "</schemas>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>");
+    }
+
+    @Test
+    public void getSpecificFieldsUnderMultipleLists() throws IOException, SAXException {
+        // preparation of the fields
+        final YangInstanceIdentifier parentYiid = YangInstanceIdentifier.create(
+                toId(NetconfState.QNAME), toId(Datastores.QNAME));
+        final YangInstanceIdentifier partialLockYiid = YangInstanceIdentifier.create(toId(Datastore.QNAME),
+                NodeIdentifierWithPredicates.of(Datastore.QNAME), toId(Locks.QNAME),
+                toId(QName.create(Locks.QNAME, "lock-type").intern()), toId(PartialLock.QNAME),
+                NodeIdentifierWithPredicates.of(PartialLock.QNAME));
+        final YangInstanceIdentifier lockedTimeField = partialLockYiid.node(
+                QName.create(Locks.QNAME, "locked-time").intern());
+        final YangInstanceIdentifier lockedBySessionField = partialLockYiid.node(
+                QName.create(Locks.QNAME, "locked-by-session").intern());
+
+        // building filter structure and NETCONF message
+        final AnyxmlNode<?> filterStructure = toFilterStructure(
+            List.of(FieldsFilter.of(parentYiid, List.of(lockedTimeField, lockedBySessionField))),
+            SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
+
+        // testing
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<datastores>\n"
+                + "<datastore>\n"
+                + "<locks>\n"
+                + "<partial-lock>\n"
+                + "<locked-time/>\n"
+                + "<locked-by-session/>\n"
+                + "<lock-id/>\n"
+                + "</partial-lock>\n"
+                + "</locks>\n"
+                + "<name/>\n"
+                + "</datastore>\n"
+                + "</datastores>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>");
+    }
+
+    @Test
+    public void getWholeListsUsingFieldsTest() throws IOException, SAXException {
+        // preparation of the fields
+        final YangInstanceIdentifier parentYiid = YangInstanceIdentifier.create(toId(NetconfState.QNAME));
+        final YangInstanceIdentifier datastoreListField = YangInstanceIdentifier.create(toId(Datastores.QNAME),
+                toId(Datastore.QNAME), NodeIdentifierWithPredicates.of(Datastore.QNAME));
+        final YangInstanceIdentifier sessionListField = YangInstanceIdentifier.create(toId(Sessions.QNAME),
+                toId(Session.QNAME), NodeIdentifierWithPredicates.of(Session.QNAME));
+
+        // building filter structure and NETCONF message
+        final AnyxmlNode<?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid, List.of(datastoreListField, sessionListField))), SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
+
+        // testing
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<datastores>\n"
+                + "<datastore/>\n"
+                + "</datastores>\n"
+                + "<sessions>\n"
+                + "<session/>\n"
+                + "</sessions>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>");
+    }
+
+    @Test
+    public void getSpecificListEntriesWithSpecificFieldsTest() throws IOException, SAXException {
+        // preparation of the fields
+        final YangInstanceIdentifier parentYiid = YangInstanceIdentifier.create(toId(NetconfState.QNAME),
+                toId(Sessions.QNAME));
+        final QName sessionId = QName.create(Session.QNAME, "session-id").intern();
+        final YangInstanceIdentifier session1Field = YangInstanceIdentifier.create(toId(Session.QNAME),
+                NodeIdentifierWithPredicates.of(Session.QNAME, sessionId, 1));
+        final YangInstanceIdentifier session2TransportField = YangInstanceIdentifier.create(toId(Session.QNAME),
+                NodeIdentifierWithPredicates.of(Session.QNAME, sessionId, 2),
+                toId(QName.create(Session.QNAME, "transport").intern()));
+
+        // building filter structure and NETCONF message
+        final AnyxmlNode<?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid, List.of(session1Field, session2TransportField))), SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
+
+        // testing
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<sessions>\n"
+                + "<session>\n"
+                + "<session-id>1</session-id>\n"
+                + "</session>\n"
+                + "<session>\n"
+                + "<session-id>2</session-id>\n"
+                + "<transport/>\n"
+                + "</session>\n"
+                + "</sessions>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>");
+    }
+
+    @Test
+    // Proof that YANGTOOLS-1362 works on DOM level
+    public void testConfigChangeToNotification() throws SAXException, IOException {
+        final var message = new NetconfMessage(XmlUtil.readXmlToDocument(
+            "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">\n"
+            + " <eventTime>2021-11-11T11:26:16Z</eventTime> \n"
+            + "  <netconf-config-change xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-notifications\">\n"
+            + "     <changed-by> \n"
+            + "       <username>root</username> \n"
+            + "       <session-id>3</session-id> \n"
+            + "     </changed-by> \n"
+            + "     <datastore>running</datastore> \n"
+            + "     <edit> \n"
+            + "        <target xmlns:ncm=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">/ncm:netconf-state"
+            + "/ncm:datastores/ncm:datastore[ncm:name='running']</target>\n"
+            + "        <operation>replace</operation> \n"
+            + "     </edit> \n"
+            + "  </netconf-config-change> \n"
+            + "</notification>"));
+
+        final var change = netconfMessageTransformer.toNotification(message).getBody();
+        final var editList = change.getChildByArg(new NodeIdentifier(Edit.QNAME));
+        assertThat(editList, instanceOf(UnkeyedListNode.class));
+        final var edits = ((UnkeyedListNode) editList).body();
+        assertEquals(1, edits.size());
+        final var edit = edits.iterator().next();
+        final var target = edit.getChildByArg(new NodeIdentifier(QName.create(Edit.QNAME, "target"))).body();
+        assertThat(target, instanceOf(YangInstanceIdentifier.class));
+
+        final var args = ((YangInstanceIdentifier) target).getPathArguments();
+        assertEquals(4, args.size());
     }
 
     private static void checkAction(final QName actionQname, final Node action , final String inputLocalName,
             final String inputNodeName, final String inputValue) {
-        checkNode(action, null, actionQname.getLocalName(), null);
+        checkNode(action, actionQname.getLocalName(), actionQname.getLocalName(),
+                actionQname.getNamespace().toString());
 
         Node childResetAt = action.getFirstChild();
         checkNode(childResetAt, inputLocalName, inputNodeName, actionQname.getNamespace().toString());
@@ -739,8 +1153,8 @@ public class NetconfMessageTransformerTest {
         Node messageId = baseRpc.getAttributes().getNamedItem("message-id");
         assertNotNull(messageId);
         assertTrue(messageId.getNodeValue().contains("m-"));
-
         Node childAction = baseRpc.getFirstChild();
+
         checkNode(childAction, "action", "action", NetconfMessageTransformUtil.NETCONF_ACTION_NAMESPACE.toString());
         return childAction;
     }
@@ -755,17 +1169,16 @@ public class NetconfMessageTransformerTest {
     }
 
     private static ContainerNode initInputAction(final QName qname, final String value) {
-        ImmutableLeafNodeBuilder<String> immutableLeafNodeBuilder = new ImmutableLeafNodeBuilder<>();
-        DataContainerChild<NodeIdentifier, String> build = immutableLeafNodeBuilder.withNodeIdentifier(
-                NodeIdentifier.create(qname)).withValue(value).build();
-        ContainerNode data = ImmutableContainerNodeBuilder.create().withNodeIdentifier(NodeIdentifier.create(
-                QName.create(qname, "input"))).withChild(build).build();
-        return data;
+        return Builders.containerBuilder()
+            .withNodeIdentifier(NodeIdentifier.create(QName.create(qname, "input")))
+            .withChild(ImmutableNodes.leafNode(qname, value))
+            .build();
     }
 
     private static ContainerNode initEmptyInputAction(final QName qname) {
-        return ImmutableContainerNodeBuilder.create().withNodeIdentifier(NodeIdentifier.create(
-                QName.create(qname, "input"))).build();
+        return Builders.containerBuilder()
+            .withNodeIdentifier(NodeIdentifier.create(QName.create(qname, "input")))
+            .build();
     }
 
     private static void checkNode(final Node childServer, final String expectedLocalName, final String expectedNodeName,