Move SubscribeToStreamUtil to rests.services.impl
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / ReadDataTransactionUtil.java
index a309c035527f320ecdb6b62328f1010d781f3a05..8ba6802833e3789e9221f8d718ff3bb9427abb47 100644 (file)
@@ -7,13 +7,8 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
 
-import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants.STREAMS_PATH;
-import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants.STREAM_PATH_PART;
-
-import com.google.common.collect.Iterables;
 import com.google.common.primitives.Ints;
 import com.google.common.util.concurrent.FluentFuture;
-import java.net.URI;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -21,23 +16,19 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import javax.ws.rs.core.UriInfo;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 import org.opendaylight.restconf.common.context.WriterParameters;
 import org.opendaylight.restconf.common.context.WriterParameters.WriterParametersBuilder;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfError;
-import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper;
-import org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationListenerAdapter;
-import org.opendaylight.restconf.nb.rfc8040.utils.mapping.RestconfMappingNodeUtil;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserFieldsParameter;
-import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -62,17 +53,15 @@ 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.builder.api.CollectionNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -94,41 +83,15 @@ public final class ReadDataTransactionUtil {
     /**
      * Parse parameters from URI request and check their types and values.
      *
-     *
-     * @param identifier
-     *             {@link InstanceIdentifierContext}
-     * @param uriInfo
-     *             URI info
-     * @param tagged
-     *             set tagged for {@link WriterParameters}
-     * @return {@link WriterParameters}
-     */
-    @Nonnull
-    public static WriterParameters parseUriParameters(@Nonnull final InstanceIdentifierContext<?> identifier,
-            @Nullable final UriInfo uriInfo, final boolean tagged) {
-        return parseParams(identifier, uriInfo, tagged);
-    }
-
-    /**
-     * Parse parameters from URI request and check their types and values.
-     *
-     *
      * @param identifier
      *             {@link InstanceIdentifierContext}
      * @param uriInfo
      *             URI info
      * @return {@link WriterParameters}
      */
-    @Nonnull
-    public static WriterParameters parseUriParameters(@Nonnull final InstanceIdentifierContext<?> identifier,
-                                                               @Nullable final UriInfo uriInfo) {
-        return parseParams(identifier, uriInfo, false);
-    }
-
-    private static WriterParameters parseParams(final InstanceIdentifierContext<?> identifier, final UriInfo uriInfo,
-            final boolean tagged) {
+    public static WriterParameters parseUriParameters(final InstanceIdentifierContext<?> identifier,
+                                                      final UriInfo uriInfo) {
         final WriterParametersBuilder builder = new WriterParametersBuilder();
-        builder.setTagged(tagged);
 
         if (uriInfo == null) {
             return builder.build();
@@ -149,6 +112,9 @@ public final class ReadDataTransactionUtil {
         final List<String> depth = uriInfo.getQueryParameters().getOrDefault(
                 RestconfDataServiceConstant.ReadData.DEPTH,
                 Collections.singletonList(RestconfDataServiceConstant.ReadData.UNBOUNDED));
+        final List<String> withDefaults = uriInfo.getQueryParameters().getOrDefault(
+                RestconfDataServiceConstant.ReadData.WITH_DEFAULTS,
+                Collections.emptyList());
         // fields
         final List<String> fields = uriInfo.getQueryParameters().getOrDefault(
                 RestconfDataServiceConstant.ReadData.FIELDS,
@@ -158,6 +124,7 @@ public final class ReadDataTransactionUtil {
         ParametersUtil.checkParameterCount(content, RestconfDataServiceConstant.ReadData.CONTENT);
         ParametersUtil.checkParameterCount(depth, RestconfDataServiceConstant.ReadData.DEPTH);
         ParametersUtil.checkParameterCount(fields, RestconfDataServiceConstant.ReadData.FIELDS);
+        ParametersUtil.checkParameterCount(fields, RestconfDataServiceConstant.ReadData.WITH_DEFAULTS);
 
         // check and set content
         final String contentValue = content.get(0);
@@ -194,6 +161,19 @@ public final class ReadDataTransactionUtil {
             builder.setFields(ParserFieldsParameter.parseFieldsParameter(identifier, fields.get(0)));
         }
 
+        // check and set withDefaults parameter
+        if (!withDefaults.isEmpty()) {
+            switch (withDefaults.get(0)) {
+                case RestconfDataServiceConstant.ReadData.REPORT_ALL_TAGGED_DEFAULT_VALUE:
+                    builder.setTagged(true);
+                    break;
+                case RestconfDataServiceConstant.ReadData.REPORT_ALL_DEFAULT_VALUE:
+                    break;
+                default:
+                    builder.setWithDefault(withDefaults.get(0));
+            }
+        }
+
         return builder.build();
     }
 
@@ -208,28 +188,27 @@ public final class ReadDataTransactionUtil {
      *            schema context
      * @return {@link NormalizedNode}
      */
-    @Nullable
-    public static NormalizedNode<?, ?> readData(@Nonnull final String valueOfContent,
-            @Nonnull final TransactionVarsWrapper transactionNode, final SchemaContext schemaContext) {
+    public static @Nullable NormalizedNode<?, ?> readData(final @NonNull String valueOfContent,
+            final @NonNull TransactionVarsWrapper transactionNode, final SchemaContext schemaContext) {
         return readData(valueOfContent, transactionNode, null, schemaContext);
     }
 
     /**
-     * Read specific type of data from data store via transaction.
+     * Read specific type of data from data store via transaction. Close {@link DOMTransactionChain} inside of object
+     * {@link TransactionVarsWrapper} provided as a parameter.
      *
      * @param valueOfContent
      *            type of data to read (config, state, all)
      * @param transactionNode
      *            {@link TransactionVarsWrapper} - wrapper for variables
      * @param withDefa
-     *            vaule of with-defaults parameter
+     *            value of with-defaults parameter
      * @param ctx
      *            schema context
      * @return {@link NormalizedNode}
      */
-    @Nullable
-    public static NormalizedNode<?, ?> readData(@Nonnull final String valueOfContent,
-            @Nonnull final TransactionVarsWrapper transactionNode, final String withDefa, final SchemaContext ctx) {
+    public static @Nullable NormalizedNode<?, ?> readData(final @NonNull String valueOfContent,
+            final @NonNull TransactionVarsWrapper transactionNode, final String withDefa, final SchemaContext ctx) {
         switch (valueOfContent) {
             case RestconfDataServiceConstant.ReadData.CONFIG:
                 transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
@@ -247,6 +226,7 @@ public final class ReadDataTransactionUtil {
                 return readAllData(transactionNode, withDefa, ctx);
 
             default:
+                transactionNode.getTransactionChain().close();
                 throw new RestconfDocumentedException(
                         new RestconfError(RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.INVALID_VALUE,
                                 "Invalid content parameter: " + valueOfContent, null,
@@ -254,56 +234,6 @@ public final class ReadDataTransactionUtil {
         }
     }
 
-    /**
-     * Read specific type of data from data store via transaction and if identifier read data from
-     * streams then put streams from actual schema context to datastore.
-     *
-     * @param identifier
-     *             identifier of data to read
-     * @param content
-     *             type of data to read (config, state, all)
-     * @param transactionNode
-     *             {@link TransactionVarsWrapper} - wrapper for variables
-     * @param withDefa
-     *             vaule of with-defaults parameter
-     * @param schemaContextRef
-     *             schema context
-     * @param uriInfo
-     *             uri info
-     * @return {@link NormalizedNode}
-     */
-    public static NormalizedNode<?, ?> readData(final String identifier, final String content,
-                                                final TransactionVarsWrapper transactionNode, final String withDefa,
-                                                final SchemaContextRef schemaContextRef, final UriInfo uriInfo) {
-        final SchemaContext schemaContext = schemaContextRef.get();
-        if (identifier.contains(STREAMS_PATH) && !identifier.contains(STREAM_PATH_PART)) {
-            final DOMDataTreeReadWriteTransaction wTx = transactionNode.getTransactionChain().newReadWriteTransaction();
-            final boolean exist = SubscribeToStreamUtil.checkExist(schemaContext, wTx);
-
-            for (final NotificationDefinition notificationDefinition : schemaContextRef.get().getNotifications()) {
-                final List<NotificationListenerAdapter> notifiStreamXML =
-                        CreateStreamUtil.createYangNotifiStream(notificationDefinition, schemaContextRef,
-                                NotificationOutputType.XML.getName());
-                final List<NotificationListenerAdapter> notifiStreamJSON =
-                        CreateStreamUtil.createYangNotifiStream(notificationDefinition, schemaContextRef,
-                                NotificationOutputType.JSON.getName());
-                for (final NotificationListenerAdapter listener : Iterables.concat(notifiStreamXML, notifiStreamJSON)) {
-                    final URI uri = SubscribeToStreamUtil.prepareUriByStreamName(uriInfo, listener.getStreamName());
-                    final NormalizedNode mapToStreams =
-                            RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
-                                    listener.getSchemaPath().getLastComponent(), schemaContext.getNotifications(),
-                                    null, listener.getOutputType(), uri,
-                                    SubscribeToStreamUtil.getMonitoringModule(schemaContext), exist);
-                    SubscribeToStreamUtil.writeDataToDS(schemaContext,
-                            listener.getSchemaPath().getLastComponent().getLocalName(), wTx, exist,
-                            mapToStreams);
-                }
-            }
-            SubscribeToStreamUtil.submitData(wTx);
-        }
-        return readData(content, transactionNode, withDefa, schemaContext);
-    }
-
     private static NormalizedNode<?, ?> prepareDataByParamWithDef(final NormalizedNode<?, ?> result,
             final YangInstanceIdentifier path, final String withDefa, final SchemaContext ctx) {
         boolean trim;
@@ -321,12 +251,12 @@ public final class ReadDataTransactionUtil {
         final DataSchemaContextTree baseSchemaCtxTree = DataSchemaContextTree.from(ctx);
         final DataSchemaNode baseSchemaNode = baseSchemaCtxTree.getChild(path).getDataSchemaNode();
         if (result instanceof ContainerNode) {
-            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder =
+            final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builder =
                     Builders.containerBuilder((ContainerSchemaNode) baseSchemaNode);
             buildCont(builder, (ContainerNode) result, baseSchemaCtxTree, path, trim);
             return builder.build();
         } else {
-            final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder =
+            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder =
                     Builders.mapEntryBuilder((ListSchemaNode) baseSchemaNode);
             buildMapEntryBuilder(builder, (MapEntryNode) result, baseSchemaCtxTree, path, trim,
                     ((ListSchemaNode) baseSchemaNode).getKeyDefinition());
@@ -335,14 +265,14 @@ public final class ReadDataTransactionUtil {
     }
 
     private static void buildMapEntryBuilder(
-            final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder,
+            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder,
             final MapEntryNode result, final DataSchemaContextTree baseSchemaCtxTree,
             final YangInstanceIdentifier actualPath, final boolean trim, final List<QName> keys) {
         for (final DataContainerChild<? extends PathArgument, ?> child : result.getValue()) {
             final YangInstanceIdentifier path = actualPath.node(child.getIdentifier());
             final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(path).getDataSchemaNode();
             if (child instanceof ContainerNode) {
-                final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> childBuilder =
+                final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> childBuilder =
                         Builders.containerBuilder((ContainerSchemaNode) childSchema);
                 buildCont(childBuilder, (ContainerNode) child, baseSchemaCtxTree, path, trim);
                 builder.withChild(childBuilder.build());
@@ -355,20 +285,20 @@ public final class ReadDataTransactionUtil {
             } else if (child instanceof LeafNode) {
                 final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null);
                 final Object nodeVal = child.getValue();
-                final NormalizedNodeAttrBuilder<NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
+                final NormalizedNodeBuilder<NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
                         Builders.leafBuilder((LeafSchemaNode) childSchema);
                 if (keys.contains(child.getNodeType())) {
-                    leafBuilder.withValue(((LeafNode) child).getValue());
+                    leafBuilder.withValue(((LeafNode<?>) child).getValue());
                     builder.withChild(leafBuilder.build());
                 } else {
                     if (trim) {
                         if (defaultVal == null || !defaultVal.equals(nodeVal)) {
-                            leafBuilder.withValue(((LeafNode) child).getValue());
+                            leafBuilder.withValue(((LeafNode<?>) child).getValue());
                             builder.withChild(leafBuilder.build());
                         }
                     } else {
                         if (defaultVal != null && defaultVal.equals(nodeVal)) {
-                            leafBuilder.withValue(((LeafNode) child).getValue());
+                            leafBuilder.withValue(((LeafNode<?>) child).getValue());
                             builder.withChild(leafBuilder.build());
                         }
                     }
@@ -383,21 +313,21 @@ public final class ReadDataTransactionUtil {
         for (final MapEntryNode mapEntryNode : result.getValue()) {
             final YangInstanceIdentifier actualNode = path.node(mapEntryNode.getIdentifier());
             final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(actualNode).getDataSchemaNode();
-            final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder =
+            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder =
                     Builders.mapEntryBuilder((ListSchemaNode) childSchema);
             buildMapEntryBuilder(mapEntryBuilder, mapEntryNode, baseSchemaCtxTree, actualNode, trim, keys);
             builder.withChild(mapEntryBuilder.build());
         }
     }
 
-    private static void buildCont(final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder,
+    private static void buildCont(final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builder,
             final ContainerNode result, final DataSchemaContextTree baseSchemaCtxTree,
             final YangInstanceIdentifier actualPath, final boolean trim) {
         for (final DataContainerChild<? extends PathArgument, ?> child : result.getValue()) {
             final YangInstanceIdentifier path = actualPath.node(child.getIdentifier());
             final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(path).getDataSchemaNode();
             if (child instanceof ContainerNode) {
-                final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builderChild =
+                final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builderChild =
                         Builders.containerBuilder((ContainerSchemaNode) childSchema);
                 buildCont(builderChild, result, baseSchemaCtxTree, actualPath, trim);
                 builder.withChild(builderChild.build());
@@ -410,16 +340,16 @@ public final class ReadDataTransactionUtil {
             } else if (child instanceof LeafNode) {
                 final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null);
                 final Object nodeVal = child.getValue();
-                final NormalizedNodeAttrBuilder<NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
+                final NormalizedNodeBuilder<NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
                         Builders.leafBuilder((LeafSchemaNode) childSchema);
                 if (trim) {
                     if (defaultVal == null || !defaultVal.equals(nodeVal)) {
-                        leafBuilder.withValue(((LeafNode) child).getValue());
+                        leafBuilder.withValue(((LeafNode<?>) child).getValue());
                         builder.withChild(leafBuilder.build());
                     }
                 } else {
                     if (defaultVal != null && defaultVal.equals(nodeVal)) {
-                        leafBuilder.withValue(((LeafNode) child).getValue());
+                        leafBuilder.withValue(((LeafNode<?>) child).getValue());
                         builder.withChild(leafBuilder.build());
                     }
                 }
@@ -427,6 +357,23 @@ public final class ReadDataTransactionUtil {
         }
     }
 
+    /**
+     * If is set specific {@link LogicalDatastoreType} in
+     * {@link TransactionVarsWrapper}, then read this type of data from DS. If
+     * don't, we have to read all data from DS (state + config).
+     * This method will close {@link org.opendaylight.mdsal.dom.api.DOMTransactionChain} inside of
+     * {@link TransactionVarsWrapper}.
+     *
+     * @param transactionNode
+     *             {@link TransactionVarsWrapper} - wrapper for variables
+     * @return {@link NormalizedNode}
+     */
+    private static @Nullable NormalizedNode<?, ?> readDataViaTransaction(
+            final @NonNull TransactionVarsWrapper transactionNode) {
+        return readDataViaTransaction(transactionNode, true);
+    }
+
+
     /**
      * If is set specific {@link LogicalDatastoreType} in
      * {@link TransactionVarsWrapper}, then read this type of data from DS. If
@@ -434,24 +381,32 @@ public final class ReadDataTransactionUtil {
      *
      * @param transactionNode
      *             {@link TransactionVarsWrapper} - wrapper for variables
+     * @param closeTransactionChain
+     *             If is set to true, after transaction it will close transactionChain in {@link TransactionVarsWrapper}
      * @return {@link NormalizedNode}
      */
-    @Nullable
-    private static NormalizedNode<?, ?> readDataViaTransaction(
-            @Nonnull final TransactionVarsWrapper transactionNode) {
+    private static @Nullable NormalizedNode<?, ?> readDataViaTransaction(
+            final @NonNull TransactionVarsWrapper transactionNode, final boolean closeTransactionChain) {
         final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
         try (DOMDataTreeReadTransaction tx = transactionNode.getTransactionChain().newReadOnlyTransaction()) {
             final FluentFuture<Optional<NormalizedNode<?, ?>>> listenableFuture = tx.read(
                 transactionNode.getLogicalDatastoreType(),
                 transactionNode.getInstanceIdentifier().getInstanceIdentifier());
-            FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
-                dataFactory);
+            if (closeTransactionChain) {
+                //Method close transactionChain inside of TransactionVarsWrapper, if is provide as a parameter.
+                FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
+                        dataFactory, transactionNode.getTransactionChain());
+            } else {
+                FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
+                        dataFactory);
+            }
         }
         return dataFactory.build();
     }
 
     /**
-     * Read config and state data, then map them.
+     * Read config and state data, then map them. Close {@link DOMTransactionChain} inside of object
+     * {@link TransactionVarsWrapper} provided as a parameter.
      *
      * @param transactionNode
      *            {@link TransactionVarsWrapper} - wrapper for variables
@@ -461,16 +416,16 @@ public final class ReadDataTransactionUtil {
      *            schema context
      * @return {@link NormalizedNode}
      */
-    @Nullable
-    private static NormalizedNode<?, ?> readAllData(@Nonnull final TransactionVarsWrapper transactionNode,
+    private static @Nullable NormalizedNode<?, ?> readAllData(final @NonNull TransactionVarsWrapper transactionNode,
             final String withDefa, final SchemaContext ctx) {
         // PREPARE STATE DATA NODE
         transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
-        final NormalizedNode<?, ?> stateDataNode = readDataViaTransaction(transactionNode);
+        final NormalizedNode<?, ?> stateDataNode = readDataViaTransaction(transactionNode, false);
 
         // PREPARE CONFIG DATA NODE
         transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
         final NormalizedNode<?, ?> configDataNode;
+        //Here will be closed transactionChain
         if (withDefa == null) {
             configDataNode = readDataViaTransaction(transactionNode);
         } else {
@@ -494,11 +449,11 @@ public final class ReadDataTransactionUtil {
         }
 
         // merge data from config and state
-        return mapNode(stateDataNode, configDataNode);
+        return mergeStateAndConfigData(stateDataNode, configDataNode);
     }
 
     /**
-     * Map data by type of read node.
+     * Merge state and config data into a single NormalizedNode.
      *
      * @param stateDataNode
      *             data node of state data
@@ -506,10 +461,9 @@ public final class ReadDataTransactionUtil {
      *             data node of config data
      * @return {@link NormalizedNode}
      */
-    @Nonnull
-    private static NormalizedNode<?, ?> mapNode(@Nonnull final NormalizedNode<?, ?> stateDataNode,
-                                                         @Nonnull final NormalizedNode<?, ?> configDataNode) {
-        validPossibilityOfMergeNodes(stateDataNode, configDataNode);
+    private static @NonNull NormalizedNode<?, ?> mergeStateAndConfigData(
+            final @NonNull NormalizedNode<?, ?> stateDataNode, final @NonNull NormalizedNode<?, ?> configDataNode) {
+        validateNodeMerge(stateDataNode, configDataNode);
         if (configDataNode instanceof RpcDefinition) {
             return prepareRpcData(configDataNode, stateDataNode);
         } else {
@@ -518,19 +472,19 @@ public final class ReadDataTransactionUtil {
     }
 
     /**
-     * Valid of can be data merged together.
+     * Validates whether the two NormalizedNodes can be merged.
      *
      * @param stateDataNode
      *             data node of state data
      * @param configDataNode
      *             data node of config data
      */
-    private static void validPossibilityOfMergeNodes(@Nonnull final NormalizedNode<?, ?> stateDataNode,
-                                                     @Nonnull final NormalizedNode<?, ?> configDataNode) {
+    private static void validateNodeMerge(final @NonNull NormalizedNode<?, ?> stateDataNode,
+                                          final @NonNull NormalizedNode<?, ?> configDataNode) {
         final QNameModule moduleOfStateData = stateDataNode.getIdentifier().getNodeType().getModule();
         final QNameModule moduleOfConfigData = configDataNode.getIdentifier().getNodeType().getModule();
-        if (moduleOfStateData != moduleOfConfigData) {
-            throw new RestconfDocumentedException("It is not possible to merge ");
+        if (!moduleOfStateData.equals(moduleOfConfigData)) {
+            throw new RestconfDocumentedException("Unable to merge data from different modules.");
         }
     }
 
@@ -543,9 +497,8 @@ public final class ReadDataTransactionUtil {
      *             data node of state data
      * @return {@link NormalizedNode}
      */
-    @Nonnull
-    private static NormalizedNode<?, ?> prepareRpcData(@Nonnull final NormalizedNode<?, ?> configDataNode,
-                                                                @Nonnull final NormalizedNode<?, ?> stateDataNode) {
+    private static @NonNull NormalizedNode<?, ?> prepareRpcData(final @NonNull NormalizedNode<?, ?> configDataNode,
+                                                                final @NonNull NormalizedNode<?, ?> stateDataNode) {
         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = ImmutableNodes
                 .mapEntryBuilder();
         mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier());
@@ -566,9 +519,8 @@ public final class ReadDataTransactionUtil {
      * @param mapEntryBuilder
      *             builder for mapping data
      */
-    private static void mapRpcDataNode(@Nonnull final NormalizedNode<?, ?> dataNode,
-                                       @Nonnull final DataContainerNodeBuilder<
-                                               NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
+    private static void mapRpcDataNode(final @NonNull NormalizedNode<?, ?> dataNode,
+            final @NonNull DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
         ((ContainerNode) dataNode).getValue().forEach(mapEntryBuilder::addChild);
     }
 
@@ -582,9 +534,8 @@ public final class ReadDataTransactionUtil {
      * @return {@link NormalizedNode}
      */
     @SuppressWarnings("unchecked")
-    @Nonnull
-    private static NormalizedNode<?, ?> prepareData(@Nonnull final NormalizedNode<?, ?> configDataNode,
-                                                             @Nonnull final NormalizedNode<?, ?> stateDataNode) {
+    private static @NonNull NormalizedNode<?, ?> prepareData(final @NonNull NormalizedNode<?, ?> configDataNode,
+                                                             final @NonNull NormalizedNode<?, ?> stateDataNode) {
         if (configDataNode instanceof OrderedMapNode) {
             final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> builder = Builders
                     .orderedMapBuilder().withNodeIdentifier(((MapNode) configDataNode).getIdentifier());
@@ -610,7 +561,7 @@ public final class ReadDataTransactionUtil {
 
             return builder.build();
         } else if (configDataNode instanceof ContainerNode) {
-            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = Builders
+            final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builder = Builders
                     .containerBuilder().withNodeIdentifier(((ContainerNode) configDataNode).getIdentifier());
 
             mapValueToBuilder(
@@ -649,6 +600,11 @@ public final class ReadDataTransactionUtil {
             mapValueToBuilder(((LeafSetNode<Object>) configDataNode).getValue(),
                     ((LeafSetNode<Object>) stateDataNode).getValue(), builder);
             return builder.build();
+        } else if (configDataNode instanceof LeafSetEntryNode) {
+            return Builders.leafSetEntryBuilder()
+                    .withNodeIdentifier(((LeafSetEntryNode<?>) configDataNode).getIdentifier())
+                    .withValue(configDataNode.getValue())
+                    .build();
         } else if (configDataNode instanceof UnkeyedListNode) {
             final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> builder = Builders
                     .unkeyedListBuilder().withNodeIdentifier(((UnkeyedListNode) configDataNode).getIdentifier());
@@ -657,7 +613,7 @@ public final class ReadDataTransactionUtil {
                     ((UnkeyedListNode) stateDataNode).getValue(), builder);
             return builder.build();
         } else if (configDataNode instanceof UnkeyedListEntryNode) {
-            final DataContainerNodeAttrBuilder<NodeIdentifier, UnkeyedListEntryNode> builder = Builders
+            final DataContainerNodeBuilder<NodeIdentifier, UnkeyedListEntryNode> builder = Builders
                 .unkeyedListEntryBuilder().withNodeIdentifier(((UnkeyedListEntryNode) configDataNode).getIdentifier());
 
             mapValueToBuilder(((UnkeyedListEntryNode) configDataNode).getValue(),
@@ -679,9 +635,8 @@ public final class ReadDataTransactionUtil {
      *             builder
      */
     private static <T extends NormalizedNode<? extends PathArgument, ?>> void mapValueToBuilder(
-            @Nonnull final Collection<T> configData,
-            @Nonnull final Collection<T> stateData,
-            @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+            final @NonNull Collection<T> configData, final @NonNull Collection<T> stateData,
+            final @NonNull NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
         final Map<PathArgument, T> configMap = configData.stream().collect(
                 Collectors.toMap(NormalizedNode::getIdentifier, Function.identity()));
         final Map<PathArgument, T> stateMap = stateData.stream().collect(
@@ -706,9 +661,8 @@ public final class ReadDataTransactionUtil {
      *           - builder
      */
     private static <T extends NormalizedNode<? extends PathArgument, ?>> void mapDataToBuilder(
-            @Nonnull final Map<PathArgument, T> configMap,
-            @Nonnull final Map<PathArgument, T> stateMap,
-            @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+            final @NonNull Map<PathArgument, T> configMap, final @NonNull Map<PathArgument, T> stateMap,
+            final @NonNull NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
         configMap.entrySet().stream().filter(x -> !stateMap.containsKey(x.getKey())).forEach(
             y -> builder.addChild(y.getValue()));
         stateMap.entrySet().stream().filter(x -> !configMap.containsKey(x.getKey())).forEach(
@@ -728,9 +682,8 @@ public final class ReadDataTransactionUtil {
      */
     @SuppressWarnings("unchecked")
     private static <T extends NormalizedNode<? extends PathArgument, ?>> void mergeDataToBuilder(
-            @Nonnull final Map<PathArgument, T> configMap,
-            @Nonnull final Map<PathArgument, T> stateMap,
-            @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+            final @NonNull Map<PathArgument, T> configMap, final @NonNull Map<PathArgument, T> stateMap,
+            final @NonNull NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
         // it is enough to process only config data because operational contains the same data
         configMap.entrySet().stream().filter(x -> stateMap.containsKey(x.getKey())).forEach(
             y -> builder.addChild((T) prepareData(y.getValue(), stateMap.get(y.getKey()))));