Mis a whitespace problem
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / PostDataTransactionUtil.java
index 6041081dba03eaa0f8df669115090e7824e583b1..d3cc4531f8d58782055a7be5dd2d0b84a2c7b197 100644 (file)
@@ -9,21 +9,21 @@ package org.opendaylight.restconf.nb.rfc8040.rests.utils;
 
 import com.google.common.util.concurrent.FluentFuture;
 import java.net.URI;
+import java.util.Collection;
 import java.util.Optional;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-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.NormalizedNodeContext;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
-import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper;
+import org.opendaylight.restconf.common.errors.RestconfError;
+import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
+import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
@@ -34,191 +34,174 @@ import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Util class to post data to DS.
  *
  */
 public final class PostDataTransactionUtil {
+    private static final Logger LOG = LoggerFactory.getLogger(PostDataTransactionUtil.class);
+
     private PostDataTransactionUtil() {
-        throw new UnsupportedOperationException("Util class.");
+        // Hidden on purpose
     }
 
     /**
-     * Check mount point and prepare variables for post data.
-     *
-     * @param uriInfo
+     * Check mount point and prepare variables for post data. Close {@link DOMTransactionChain} if any inside of object
+     * {@link RestconfStrategy} provided as a parameter.
      *
-     * @param payload
-     *             data
-     * @param transactionNode
-     *             wrapper for transaction data
-     * @param schemaContextRef
-     *             reference to actual {@link SchemaContext}
-     * @param point
-     *             point
-     * @param insert
-     *             insert
+     * @param uriInfo       uri info
+     * @param payload       data
+     * @param strategy      Object that perform the actual DS operations
+     * @param schemaContext reference to actual {@link EffectiveModelContext}
+     * @param point         point
+     * @param insert        insert
      * @return {@link Response}
      */
     public static Response postData(final UriInfo uriInfo, final NormalizedNodeContext payload,
-            final TransactionVarsWrapper transactionNode, final SchemaContextRef schemaContextRef, final String insert,
-            final String point) {
-        final FluentFuture<? extends CommitInfo> future = submitData(
-                payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData(),
-                transactionNode, schemaContextRef.get(), insert, point);
-        final URI location = PostDataTransactionUtil.resolveLocation(uriInfo, transactionNode, schemaContextRef);
+                                    final RestconfStrategy strategy,
+                                    final EffectiveModelContext schemaContext, final String insert,
+                                    final String point) {
+        final YangInstanceIdentifier path = payload.getInstanceIdentifierContext().getInstanceIdentifier();
+        final FluentFuture<? extends CommitInfo> future = submitData(path, payload.getData(),
+                strategy, schemaContext, insert, point);
+        final URI location = resolveLocation(uriInfo, path, schemaContext, payload.getData());
         final ResponseFactory dataFactory = new ResponseFactory(Status.CREATED).location(location);
-        FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
+        //This method will close transactionChain if any
+        FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory,
+                strategy.getTransactionChain());
         return dataFactory.build();
     }
 
     /**
      * Post data by type.
      *
-     * @param path
-     *             path
-     * @param data
-     *             data
-     * @param transactionNode
-     *             wrapper for data to transaction
-     * @param schemaContext
-     *             schema context of data
-     * @param point
-     *             query parameter
-     * @param insert
-     *             query parameter
+     * @param path          path
+     * @param data          data
+     * @param strategy      object that perform the actual DS operations
+     * @param schemaContext schema context of data
+     * @param point         query parameter
+     * @param insert        query parameter
      * @return {@link FluentFuture}
      */
     private static FluentFuture<? extends CommitInfo> submitData(final YangInstanceIdentifier path,
-            final NormalizedNode<?, ?> data, final TransactionVarsWrapper transactionNode,
-            final SchemaContext schemaContext, final String insert, final String point) {
-        final DOMTransactionChain domTransactionChain = transactionNode.getTransactionChain();
-        final DOMDataTreeReadWriteTransaction newReadWriteTransaction = domTransactionChain.newReadWriteTransaction();
+                                                                 final NormalizedNode<?, ?> data,
+                                                                 final RestconfStrategy strategy,
+                                                                 final EffectiveModelContext schemaContext,
+                                                                 final String insert, final String point) {
+        strategy.prepareReadWriteExecution();
         if (insert == null) {
-            makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(), newReadWriteTransaction);
-            return newReadWriteTransaction.commit();
-        } else {
-            final DataSchemaNode schemaNode = PutDataTransactionUtil.checkListAndOrderedType(schemaContext, path);
-            switch (insert) {
-                case "first":
-                    if (schemaNode instanceof ListSchemaNode) {
-                        final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
-                            schemaContext, transactionNode.getTransactionChainHandler(), schemaNode);
-                        final OrderedMapNode readList = (OrderedMapNode) readData;
-                        if (readList == null || readList.getValue().isEmpty()) {
-                            makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        } else {
-                            newReadWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION,
-                                    path.getParent().getParent());
-                            simplePost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path, data,
-                                    schemaContext, transactionNode.getTransactionChainHandler());
-                            makePost(path, readData, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        }
-                    } else {
-                        final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
-                            schemaContext, transactionNode.getTransactionChainHandler(), schemaNode);
+            makePost(path, data, schemaContext, strategy);
+            return strategy.commit();
+        }
 
-                        final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
-                        if (readLeafList == null || readLeafList.getValue().isEmpty()) {
-                            makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        } else {
-                            newReadWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION,
-                                    path.getParent().getParent());
-                            simplePost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path, data,
-                                    schemaContext, transactionNode.getTransactionChainHandler());
-                            makePost(path, readData, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        }
+        final DataSchemaNode schemaNode = PutDataTransactionUtil.checkListAndOrderedType(schemaContext, path);
+        switch (insert) {
+            case "first":
+                if (schemaNode instanceof ListSchemaNode) {
+                    final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
+                            schemaContext, strategy, schemaNode);
+                    final OrderedMapNode readList = (OrderedMapNode) readData;
+                    if (readList == null || readList.getValue().isEmpty()) {
+                        makePost(path, data, schemaContext, strategy);
+                        return strategy.commit();
                     }
-                case "last":
-                    makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(),
-                            newReadWriteTransaction);
-                    return newReadWriteTransaction.commit();
-                case "before":
-                    if (schemaNode instanceof ListSchemaNode) {
-                        final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
-                            schemaContext, transactionNode.getTransactionChainHandler(), schemaNode);
-                        final OrderedMapNode readList = (OrderedMapNode) readData;
-                        if (readList == null || readList.getValue().isEmpty()) {
-                            makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        } else {
-                            insertWithPointListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path,
-                                    data, schemaContext, point, readList, true,
-                                    transactionNode.getTransactionChainHandler());
-                            return newReadWriteTransaction.commit();
-                        }
-                    } else {
-                        final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
-                            schemaContext, transactionNode.getTransactionChainHandler(), schemaNode);
 
-                        final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
-                        if (readLeafList == null || readLeafList.getValue().isEmpty()) {
-                            makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        } else {
-                            insertWithPointLeafListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                                    path, data, schemaContext, point, readLeafList, true,
-                                    transactionNode.getTransactionChainHandler());
-                            return newReadWriteTransaction.commit();
-                        }
+                    strategy.delete(LogicalDatastoreType.CONFIGURATION, path.getParent().getParent());
+                    simplePost(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext, strategy);
+                    makePost(path, readData, schemaContext, strategy);
+                    return strategy.commit();
+                } else {
+                    final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
+                            schemaContext, strategy, schemaNode);
+
+                    final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
+                    if (readLeafList == null || readLeafList.getValue().isEmpty()) {
+                        makePost(path, data, schemaContext, strategy);
+                        return strategy.commit();
                     }
-                case "after":
-                    if (schemaNode instanceof ListSchemaNode) {
-                        final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
-                            schemaContext, transactionNode.getTransactionChainHandler(), schemaNode);
-                        final OrderedMapNode readList = (OrderedMapNode) readData;
-                        if (readList == null || readList.getValue().isEmpty()) {
-                            makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        } else {
-                            insertWithPointListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path,
-                                    data, schemaContext, point, readList, false,
-                                    transactionNode.getTransactionChainHandler());
-                            return newReadWriteTransaction.commit();
-                        }
-                    } else {
-                        final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
-                            schemaContext, transactionNode.getTransactionChainHandler(), schemaNode);
 
-                        final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
-                        if (readLeafList == null || readLeafList.getValue().isEmpty()) {
-                            makePost(path, data, schemaContext, transactionNode.getTransactionChainHandler(),
-                                    newReadWriteTransaction);
-                            return newReadWriteTransaction.commit();
-                        } else {
-                            insertWithPointLeafListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                                    path, data, schemaContext, point, readLeafList, true,
-                                    transactionNode.getTransactionChainHandler());
-                            return newReadWriteTransaction.commit();
-                        }
+                    strategy.delete(LogicalDatastoreType.CONFIGURATION, path.getParent().getParent());
+                    simplePost(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext, strategy);
+                    makePost(path, readData, schemaContext, strategy);
+                    return strategy.commit();
+                }
+            case "last":
+                makePost(path, data, schemaContext, strategy);
+                return strategy.commit();
+            case "before":
+                if (schemaNode instanceof ListSchemaNode) {
+                    final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
+                            schemaContext, strategy, schemaNode);
+                    final OrderedMapNode readList = (OrderedMapNode) readData;
+                    if (readList == null || readList.getValue().isEmpty()) {
+                        makePost(path, data, schemaContext, strategy);
+                        return strategy.commit();
                     }
-                default:
-                    throw new RestconfDocumentedException(
-                            "Used bad value of insert parameter. Possible values are first, last, before or after, "
-                                    + "but was: " + insert);
-            }
+
+                    insertWithPointListPost(LogicalDatastoreType.CONFIGURATION, path,
+                            data, schemaContext, point, readList, true, strategy);
+                    return strategy.commit();
+                } else {
+                    final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
+                            schemaContext, strategy, schemaNode);
+
+                    final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
+                    if (readLeafList == null || readLeafList.getValue().isEmpty()) {
+                        makePost(path, data, schemaContext, strategy);
+                        return strategy.commit();
+                    }
+
+                    insertWithPointLeafListPost(LogicalDatastoreType.CONFIGURATION,
+                            path, data, schemaContext, point, readLeafList, true, strategy);
+                    return strategy.commit();
+                }
+            case "after":
+                if (schemaNode instanceof ListSchemaNode) {
+                    final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
+                            schemaContext, strategy, schemaNode);
+                    final OrderedMapNode readList = (OrderedMapNode) readData;
+                    if (readList == null || readList.getValue().isEmpty()) {
+                        makePost(path, data, schemaContext, strategy);
+                        return strategy.commit();
+                    }
+
+                    insertWithPointListPost(LogicalDatastoreType.CONFIGURATION, path,
+                            data, schemaContext, point, readList, false, strategy);
+                    return strategy.commit();
+                } else {
+                    final NormalizedNode<?, ?> readData = PutDataTransactionUtil.readList(path.getParent(),
+                            schemaContext, strategy, schemaNode);
+
+                    final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
+                    if (readLeafList == null || readLeafList.getValue().isEmpty()) {
+                        makePost(path, data, schemaContext, strategy);
+                        return strategy.commit();
+                    }
+
+                    insertWithPointLeafListPost(LogicalDatastoreType.CONFIGURATION,
+                            path, data, schemaContext, point, readLeafList, true, strategy);
+                    return strategy.commit();
+                }
+            default:
+                throw new RestconfDocumentedException(
+                    "Used bad value of insert parameter. Possible values are first, last, before or after, but was: "
+                            + insert, RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.BAD_ATTRIBUTE);
         }
     }
 
-    private static void insertWithPointLeafListPost(final DOMDataTreeReadWriteTransaction rwTransaction,
-            final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
-            final SchemaContext schemaContext, final String point, final OrderedLeafSetNode<?> readLeafList,
-            final boolean before, final TransactionChainHandler transactionChainHandler) {
-        rwTransaction.delete(datastore, path.getParent().getParent());
+    private static void insertWithPointLeafListPost(final LogicalDatastoreType datastore,
+                                                    final YangInstanceIdentifier path,
+                                                    final NormalizedNode<?, ?> payload,
+                                                    final EffectiveModelContext schemaContext, final String point,
+                                                    final OrderedLeafSetNode<?> readLeafList,
+                                                    final boolean before, final RestconfStrategy strategy) {
+        strategy.delete(datastore, path.getParent().getParent());
         final InstanceIdentifierContext<?> instanceIdentifier =
                 ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.empty());
         int lastItemPosition = 0;
@@ -234,26 +217,25 @@ public final class PostDataTransactionUtil {
         int lastInsertedPosition = 0;
         final NormalizedNode<?, ?> emptySubtree =
                 ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent());
-        rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
+        strategy.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
         for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
             if (lastInsertedPosition == lastItemPosition) {
-                TransactionUtil.checkItemDoesNotExists(transactionChainHandler, rwTransaction, datastore, path,
-                        RestconfDataServiceConstant.PostData.POST_TX_TYPE);
-                rwTransaction.put(datastore, path, payload);
+                checkItemDoesNotExists(strategy, datastore, path, RestconfDataServiceConstant.PostData.POST_TX_TYPE);
+                strategy.create(datastore, path, payload);
             }
             final YangInstanceIdentifier childPath = path.getParent().getParent().node(nodeChild.getIdentifier());
-            TransactionUtil.checkItemDoesNotExists(transactionChainHandler, rwTransaction, datastore, childPath,
-                    RestconfDataServiceConstant.PostData.POST_TX_TYPE);
-            rwTransaction.put(datastore, childPath, nodeChild);
+            checkItemDoesNotExists(strategy, datastore, childPath, RestconfDataServiceConstant.PostData.POST_TX_TYPE);
+            strategy.create(datastore, childPath, nodeChild);
             lastInsertedPosition++;
         }
     }
 
-    private static void insertWithPointListPost(final DOMDataTreeReadWriteTransaction rwTransaction,
-            final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
-            final SchemaContext schemaContext, final String point, final MapNode readList, final boolean before,
-            final TransactionChainHandler transactionChainHandler) {
-        rwTransaction.delete(datastore, path.getParent().getParent());
+    private static void insertWithPointListPost(final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
+                                                final NormalizedNode<?, ?> payload,
+                                                final EffectiveModelContext schemaContext, final String point,
+                                                final MapNode readList, final boolean before,
+                                                final RestconfStrategy strategy) {
+        strategy.delete(datastore, path.getParent().getParent());
         final InstanceIdentifierContext<?> instanceIdentifier =
                 ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.empty());
         int lastItemPosition = 0;
@@ -269,82 +251,107 @@ public final class PostDataTransactionUtil {
         int lastInsertedPosition = 0;
         final NormalizedNode<?, ?> emptySubtree =
                 ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent());
-        rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
+        strategy.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
         for (final MapEntryNode mapEntryNode : readList.getValue()) {
             if (lastInsertedPosition == lastItemPosition) {
-                TransactionUtil.checkItemDoesNotExists(transactionChainHandler, rwTransaction, datastore, path,
-                        RestconfDataServiceConstant.PostData.POST_TX_TYPE);
-                rwTransaction.put(datastore, path, payload);
+                checkItemDoesNotExists(strategy, datastore, path, RestconfDataServiceConstant.PostData.POST_TX_TYPE);
+                strategy.create(datastore, path, payload);
             }
             final YangInstanceIdentifier childPath = path.getParent().getParent().node(mapEntryNode.getIdentifier());
-            TransactionUtil.checkItemDoesNotExists(transactionChainHandler, rwTransaction, datastore, childPath,
-                    RestconfDataServiceConstant.PostData.POST_TX_TYPE);
-            rwTransaction.put(datastore, childPath, mapEntryNode);
+            checkItemDoesNotExists(strategy, datastore, childPath, RestconfDataServiceConstant.PostData.POST_TX_TYPE);
+            strategy.create(datastore, childPath, mapEntryNode);
             lastInsertedPosition++;
         }
     }
 
     private static void makePost(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data,
-            final SchemaContext schemaContext, final TransactionChainHandler transactionChainHandler,
-            final DOMDataTreeReadWriteTransaction transaction) {
+                                 final SchemaContext schemaContext, final RestconfStrategy strategy) {
         if (data instanceof MapNode) {
             boolean merge = false;
             for (final MapEntryNode child : ((MapNode) data).getValue()) {
                 final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
-                TransactionUtil.checkItemDoesNotExists(
-                        transactionChainHandler, transaction, LogicalDatastoreType.CONFIGURATION, childPath,
+                checkItemDoesNotExists(strategy, LogicalDatastoreType.CONFIGURATION, childPath,
                         RestconfDataServiceConstant.PostData.POST_TX_TYPE);
                 if (!merge) {
                     merge = true;
-                    TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
+                    TransactionUtil.ensureParentsByMerge(path, schemaContext, strategy);
                     final NormalizedNode<?, ?> emptySubTree = ImmutableNodes.fromInstanceId(schemaContext, path);
-                    transaction.merge(LogicalDatastoreType.CONFIGURATION,
+                    strategy.merge(LogicalDatastoreType.CONFIGURATION,
                             YangInstanceIdentifier.create(emptySubTree.getIdentifier()), emptySubTree);
                 }
-                transaction.put(LogicalDatastoreType.CONFIGURATION, childPath, child);
+                strategy.create(LogicalDatastoreType.CONFIGURATION, childPath, child);
             }
         } else {
-            TransactionUtil.checkItemDoesNotExists(
-                    transactionChainHandler, transaction, LogicalDatastoreType.CONFIGURATION, path,
+            checkItemDoesNotExists(strategy, LogicalDatastoreType.CONFIGURATION, path,
                     RestconfDataServiceConstant.PostData.POST_TX_TYPE);
 
-            TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
-            transaction.put(LogicalDatastoreType.CONFIGURATION, path, data);
+            TransactionUtil.ensureParentsByMerge(path, schemaContext, strategy);
+            strategy.create(LogicalDatastoreType.CONFIGURATION, path, data);
         }
     }
 
     /**
      * Get location from {@link YangInstanceIdentifier} and {@link UriInfo}.
      *
-     * @param uriInfo
-     *             uri info
-     * @param transactionNode
-     *             wrapper for data of transaction
-     * @param schemaContextRef
-     *            reference to {@link SchemaContext}
+     * @param uriInfo       uri info
+     * @param initialPath   data path
+     * @param schemaContext reference to {@link SchemaContext}
      * @return {@link URI}
      */
-    private static URI resolveLocation(final UriInfo uriInfo, final TransactionVarsWrapper transactionNode,
-            final SchemaContextRef schemaContextRef) {
+    private static URI resolveLocation(final UriInfo uriInfo, final YangInstanceIdentifier initialPath,
+                                       final EffectiveModelContext schemaContext, final NormalizedNode<?, ?> data) {
         if (uriInfo == null) {
             return null;
         }
 
-        final UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
-        uriBuilder.path("data");
-        uriBuilder.path(ParserIdentifier
-                .stringFromYangInstanceIdentifier(transactionNode.getInstanceIdentifier().getInstanceIdentifier(),
-                schemaContextRef.get()));
+        YangInstanceIdentifier path = initialPath;
+        if (data instanceof MapNode) {
+            final Collection<MapEntryNode> children = ((MapNode) data).getValue();
+            if (!children.isEmpty()) {
+                path = path.node(children.iterator().next().getIdentifier());
+            }
+        }
 
-        return uriBuilder.build();
+        return uriInfo.getBaseUriBuilder()
+                .path("data")
+                .path(ParserIdentifier.stringFromYangInstanceIdentifier(path, schemaContext))
+                .build();
     }
 
-    private static void simplePost(final DOMDataTreeReadWriteTransaction rwTransaction,
-            final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
-            final SchemaContext schemaContext, final TransactionChainHandler transactionChainHandler) {
-        TransactionUtil.checkItemDoesNotExists(transactionChainHandler, rwTransaction, datastore, path,
-                RestconfDataServiceConstant.PostData.POST_TX_TYPE);
-        TransactionUtil.ensureParentsByMerge(path, schemaContext, rwTransaction);
-        rwTransaction.put(datastore, path, payload);
+    private static void simplePost(final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
+                                   final NormalizedNode<?, ?> payload,
+                                   final SchemaContext schemaContext, final RestconfStrategy strategy) {
+        checkItemDoesNotExists(strategy, datastore, path, RestconfDataServiceConstant.PostData.POST_TX_TYPE);
+        TransactionUtil.ensureParentsByMerge(path, schemaContext, strategy);
+        strategy.create(datastore, path, payload);
     }
+
+
+    /**
+     * Check if items do NOT already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if
+     * data already exists.
+     *
+     * @param strategy      Object that perform the actual DS operations
+     * @param store         Datastore
+     * @param path          Path to be checked
+     * @param operationType Type of operation (READ, POST, PUT, DELETE...)
+     */
+    private static void checkItemDoesNotExists(final RestconfStrategy strategy,
+                                               final LogicalDatastoreType store, final YangInstanceIdentifier path,
+                                               final String operationType) {
+        final FluentFuture<Boolean> future = strategy.exists(store, path);
+        final FutureDataFactory<Boolean> response = new FutureDataFactory<>();
+
+        FutureCallbackTx.addCallback(future, operationType, response);
+
+        if (response.result) {
+            // close transaction
+            strategy.cancel();
+            // throw error
+            LOG.trace("Operation via Restconf was not executed because data at {} already exists", path);
+            throw new RestconfDocumentedException(
+                    "Data already exists", ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS, path);
+        }
+    }
+
 }