Create NetconfDataTreeService with base and additional operations for netconf
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / PutDataTransactionUtil.java
index 200605da4b626b77fd72c811bd14ad019aeb4064..b9f20b79df08a9d84b039ff5f36132ad5b4597c9 100644 (file)
@@ -7,27 +7,23 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
-import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FluentFuture;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+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.common.errors.RestconfError;
 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
 import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
-import org.opendaylight.restconf.common.validation.RestconfValidationUtils;
-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.nb.rfc8040.rests.transactions.RestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -43,6 +39,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -55,16 +52,13 @@ import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 public final class PutDataTransactionUtil {
 
     private PutDataTransactionUtil() {
-
     }
 
     /**
      * Valid input data with {@link SchemaNode}.
      *
-     * @param schemaNode
-     *             {@link SchemaNode}
-     * @param payload
-     *             input data
+     * @param schemaNode {@link SchemaNode}
+     * @param payload    input data
      */
     public static void validInputData(final SchemaNode schemaNode, final NormalizedNodeContext payload) {
         if (schemaNode != null && payload.getData() == null) {
@@ -77,10 +71,8 @@ public final class PutDataTransactionUtil {
     /**
      * Valid top level node name.
      *
-     * @param path
-     *             path of node
-     * @param payload
-     *             data
+     * @param path    path of node
+     * @param payload data
      */
     public static void validTopLevelNodeName(final YangInstanceIdentifier path, final NormalizedNodeContext payload) {
         final String payloadName = payload.getData().getNodeType().getLocalName();
@@ -104,8 +96,7 @@ public final class PutDataTransactionUtil {
      * Validates whether keys in {@code payload} are equal to values of keys in
      * {@code iiWithData} for list schema node.
      *
-     * @throws RestconfDocumentedException
-     *             if key values or key count in payload and URI isn't equal
+     * @throws RestconfDocumentedException if key values or key count in payload and URI isn't equal
      */
     public static void validateListKeysEqualityInPayloadAndUri(final NormalizedNodeContext payload) {
         final InstanceIdentifierContext<?> iiWithData = payload.getInstanceIdentifierContext();
@@ -115,22 +106,21 @@ public final class PutDataTransactionUtil {
         if (schemaNode instanceof ListSchemaNode) {
             final List<QName> keyDefinitions = ((ListSchemaNode) schemaNode).getKeyDefinition();
             if (lastPathArgument instanceof NodeIdentifierWithPredicates && data instanceof MapEntryNode) {
-                final Map<QName, Object> uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument)
-                        .getKeyValues();
+                final Map<QName, Object> uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument).asMap();
                 isEqualUriAndPayloadKeyValues(uriKeyValues, (MapEntryNode) data, keyDefinitions);
             }
         }
     }
 
     private static void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final MapEntryNode payload,
-            final List<QName> keyDefinitions) {
-        final Map<QName, Object> mutableCopyUriKeyValues = Maps.newHashMap(uriKeyValues);
+                                                      final List<QName> keyDefinitions) {
+        final Map<QName, Object> mutableCopyUriKeyValues = new HashMap<>(uriKeyValues);
         for (final QName keyDefinition : keyDefinitions) {
-            final Object uriKeyValue = mutableCopyUriKeyValues.remove(keyDefinition);
-            RestconfValidationUtils.checkDocumentedError(uriKeyValue != null, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING,
-                    "Missing key " + keyDefinition + " in URI.");
+            final Object uriKeyValue = RestconfDocumentedException.throwIfNull(
+                    mutableCopyUriKeyValues.remove(keyDefinition), ErrorType.PROTOCOL, ErrorTag.DATA_MISSING,
+                    "Missing key %s in URI.", keyDefinition);
 
-            final Object dataKeyValue = payload.getIdentifier().getKeyValues().get(keyDefinition);
+            final Object dataKeyValue = payload.getIdentifier().getValue(keyDefinition);
 
             if (!uriKeyValue.equals(dataKeyValue)) {
                 final String errMsg = "The value '" + uriKeyValue + "' for key '" + keyDefinition.getLocalName()
@@ -142,175 +132,161 @@ public final class PutDataTransactionUtil {
     }
 
     /**
-     * Check mount point and prepare variables for put data to DS.
+     * Check mount point and prepare variables for put data to DS. Close {@link DOMTransactionChain} if any
+     * inside of object {@link RestconfStrategy} provided as a parameter if any.
      *
-     * @param payload
-     *             data to put
-     * @param schemaCtxRef
-     *             reference to {@link SchemaContext}
-     * @param transactionNode
-     *             wrapper of variables for transaction
-     * @param point
-     *             query parameter
-     * @param insert
-     *             query parameter
-     * @return {@link CheckedFuture}
+     * @param payload       data to put
+     * @param schemaContext reference to {@link EffectiveModelContext}
+     * @param strategy      object that perform the actual DS operations
+     * @param point         query parameter
+     * @param insert        query parameter
+     * @return {@link Response}
      */
-    public static Response putData(final NormalizedNodeContext payload, final SchemaContextRef schemaCtxRef,
-                               final TransactionVarsWrapper transactionNode, final String insert, final String point) {
+    public static Response putData(final NormalizedNodeContext payload, final EffectiveModelContext schemaContext,
+                                   final RestconfStrategy strategy, final String insert, final String point) {
         final YangInstanceIdentifier path = payload.getInstanceIdentifierContext().getInstanceIdentifier();
-        final SchemaContext schemaContext = schemaCtxRef.get();
-
-        final DOMDataReadWriteTransaction readWriteTransaction =
-                transactionNode.getTransactionChain().newReadWriteTransaction();
 
-        final CheckedFuture<Boolean, ReadFailedException> existsFuture =
-                readWriteTransaction.exists(LogicalDatastoreType.CONFIGURATION, path);
+        strategy.prepareReadWriteExecution();
+        final FluentFuture<Boolean> existsFuture = strategy.exists(LogicalDatastoreType.CONFIGURATION, path);
         final FutureDataFactory<Boolean> existsResponse = new FutureDataFactory<>();
         FutureCallbackTx.addCallback(existsFuture, RestconfDataServiceConstant.PutData.PUT_TX_TYPE, existsResponse);
 
         final ResponseFactory responseFactory =
                 new ResponseFactory(existsResponse.result ? Status.NO_CONTENT : Status.CREATED);
-        final CheckedFuture<Void, TransactionCommitFailedException> submitData = submitData(path, schemaContext,
-                transactionNode.getTransactionChainHandler(), readWriteTransaction, payload.getData(), insert, point);
-        FutureCallbackTx.addCallback(submitData, RestconfDataServiceConstant.PutData.PUT_TX_TYPE, responseFactory);
+        final FluentFuture<? extends CommitInfo> submitData = submitData(path, schemaContext, strategy,
+                payload.getData(), insert, point, existsResponse.result);
+        //This method will close transactionChain if any
+        FutureCallbackTx.addCallback(submitData, RestconfDataServiceConstant.PutData.PUT_TX_TYPE, responseFactory,
+                strategy.getTransactionChain());
         return responseFactory.build();
     }
 
     /**
      * Put data to DS.
      *
-     * @param path
-     *             path of data
-     * @param schemaContext
-     *             {@link SchemaContext}
-     * @param transactionChainHandler
-     *             write transaction
-     * @param data
-     *             data
-     * @param point
-     *             query parameter
-     * @param insert
-     *             query parameter
-     * @return {@link CheckedFuture}
+     * @param path          path of data
+     * @param schemaContext {@link SchemaContext}
+     * @param strategy      object that perform the actual DS operations
+     * @param data          data
+     * @param point         query parameter
+     * @param insert        query parameter
+     * @return {@link FluentFuture}
      */
-    private static CheckedFuture<Void, TransactionCommitFailedException> submitData(final YangInstanceIdentifier path,
-            final SchemaContext schemaContext, final TransactionChainHandler transactionChainHandler,
-            final DOMDataReadWriteTransaction readWriteTransaction,
-            final NormalizedNode<?, ?> data, final String insert, final String point) {
+    private static FluentFuture<? extends CommitInfo> submitData(
+            final YangInstanceIdentifier path,
+            final EffectiveModelContext schemaContext,
+            final RestconfStrategy strategy,
+            final NormalizedNode<?, ?> data, final String insert, final String point, final boolean exists) {
         if (insert == null) {
-            return makePut(path, schemaContext, readWriteTransaction, data);
-        } else {
-            final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path);
-            switch (insert) {
-                case "first":
-                    if (schemaNode instanceof ListSchemaNode) {
-                        final NormalizedNode<?, ?> readData =
-                                readList(path, schemaContext, transactionChainHandler, schemaNode);
-                        final OrderedMapNode readList = (OrderedMapNode) readData;
-                        if (readList == null || readList.getValue().isEmpty()) {
-                            return makePut(path, schemaContext, readWriteTransaction, data);
-                        } else {
-                            readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, path.getParent());
-                            simplePut(LogicalDatastoreType.CONFIGURATION, path, readWriteTransaction,
-                                    schemaContext, data);
-                            listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), readWriteTransaction,
-                                    schemaContext, readList);
-                            return readWriteTransaction.submit();
-                        }
+            return makePut(path, schemaContext, strategy, data, exists);
+        }
+
+        final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path);
+        switch (insert) {
+            case "first":
+                if (schemaNode instanceof ListSchemaNode) {
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
+                    final OrderedMapNode readList = (OrderedMapNode) readData;
+                    if (readList == null || readList.getValue().isEmpty()) {
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        final NormalizedNode<?, ?> readData =
-                                readList(path, schemaContext, transactionChainHandler, schemaNode);
+                        strategy.delete(LogicalDatastoreType.CONFIGURATION, path.getParent());
+                        simplePut(LogicalDatastoreType.CONFIGURATION, path, strategy, schemaContext, data, exists);
+                        listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), strategy,
+                                schemaContext, readList, exists);
+                        return strategy.commit();
+                    }
+                } else {
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
 
-                        final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
-                        if (readLeafList == null || readLeafList.getValue().isEmpty()) {
-                            return makePut(path, schemaContext, readWriteTransaction, data);
-                        } else {
-                            readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, path.getParent());
-                            simplePut(LogicalDatastoreType.CONFIGURATION, path, readWriteTransaction,
-                                    schemaContext, data);
-                            listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), readWriteTransaction,
-                                    schemaContext, readLeafList);
-                            return readWriteTransaction.submit();
-                        }
+                    final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
+                    if (readLeafList == null || readLeafList.getValue().isEmpty()) {
+                        return makePut(path, schemaContext, strategy, data, exists);
+                    } else {
+                        strategy.delete(LogicalDatastoreType.CONFIGURATION, path.getParent());
+                        simplePut(LogicalDatastoreType.CONFIGURATION, path, strategy,
+                                schemaContext, data, exists);
+                        listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), strategy,
+                                schemaContext, readLeafList, exists);
+                        return strategy.commit();
                     }
-                case "last":
-                    return makePut(path, schemaContext, readWriteTransaction, data);
-                case "before":
-                    if (schemaNode instanceof ListSchemaNode) {
-                        final NormalizedNode<?, ?> readData =
-                                readList(path, schemaContext, transactionChainHandler, schemaNode);
-                        final OrderedMapNode readList = (OrderedMapNode) readData;
-                        if (readList == null || readList.getValue().isEmpty()) {
-                            return makePut(path, schemaContext, readWriteTransaction, data);
-                        } else {
-                            insertWithPointListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION, path,
-                                    data, schemaContext, point, readList, true);
-                            return readWriteTransaction.submit();
-                        }
+                }
+            case "last":
+                return makePut(path, schemaContext, strategy, data, exists);
+            case "before":
+                if (schemaNode instanceof ListSchemaNode) {
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
+                    final OrderedMapNode readList = (OrderedMapNode) readData;
+                    if (readList == null || readList.getValue().isEmpty()) {
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        final NormalizedNode<?, ?> readData =
-                                readList(path, schemaContext, transactionChainHandler, schemaNode);
+                        insertWithPointListPut(strategy, LogicalDatastoreType.CONFIGURATION, path,
+                                data, schemaContext, point, readList, true, exists);
+                        return strategy.commit();
+                    }
+                } else {
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
 
-                        final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
-                        if (readLeafList == null || readLeafList.getValue().isEmpty()) {
-                            return makePut(path, schemaContext, readWriteTransaction, data);
-                        } else {
-                            insertWithPointLeafListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                                    path, data, schemaContext, point, readLeafList, true);
-                            return readWriteTransaction.submit();
-                        }
+                    final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
+                    if (readLeafList == null || readLeafList.getValue().isEmpty()) {
+                        return makePut(path, schemaContext, strategy, data, exists);
+                    } else {
+                        insertWithPointLeafListPut(strategy, LogicalDatastoreType.CONFIGURATION,
+                                path, data, schemaContext, point, readLeafList, true, exists);
+                        return strategy.commit();
                     }
-                case "after":
-                    if (schemaNode instanceof ListSchemaNode) {
-                        final NormalizedNode<?, ?> readData =
-                                readList(path, schemaContext, transactionChainHandler, schemaNode);
-                        final OrderedMapNode readList = (OrderedMapNode) readData;
-                        if (readList == null || readList.getValue().isEmpty()) {
-                            return makePut(path, schemaContext, readWriteTransaction, data);
-                        } else {
-                            insertWithPointListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                                    path, data, schemaContext, point, readList, false);
-                            return readWriteTransaction.submit();
-                        }
+                }
+            case "after":
+                if (schemaNode instanceof ListSchemaNode) {
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
+                    final OrderedMapNode readList = (OrderedMapNode) readData;
+                    if (readList == null || readList.getValue().isEmpty()) {
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        final NormalizedNode<?, ?> readData =
-                                readList(path, schemaContext, transactionChainHandler, schemaNode);
+                        insertWithPointListPut(strategy, LogicalDatastoreType.CONFIGURATION,
+                                path, data, schemaContext, point, readList, false, exists);
+                        return strategy.commit();
+                    }
+                } else {
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
 
-                        final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
-                        if (readLeafList == null || readLeafList.getValue().isEmpty()) {
-                            return makePut(path, schemaContext, readWriteTransaction, data);
-                        } else {
-                            insertWithPointLeafListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                                    path, data, schemaContext, point, readLeafList, true);
-                            return readWriteTransaction.submit();
-                        }
+                    final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
+                    if (readLeafList == null || readLeafList.getValue().isEmpty()) {
+                        return makePut(path, schemaContext, strategy, data, exists);
+                    } else {
+                        insertWithPointLeafListPut(strategy, LogicalDatastoreType.CONFIGURATION,
+                                path, data, schemaContext, point, readLeafList, true, exists);
+                        return strategy.commit();
                     }
-                default:
-                    throw new RestconfDocumentedException(
-                            "Used bad value of insert parameter. Possible values are first, last, before or after, "
-                                    + "but was: " + insert);
-            }
+                }
+            default:
+                throw new RestconfDocumentedException(
+                        "Used bad value of insert parameter. Possible values are first, last, before or after, "
+                                + "but was: " + insert, RestconfError.ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE);
         }
     }
 
-    public static NormalizedNode<?, ?> readList(final YangInstanceIdentifier path, final SchemaContext schemaContext,
-            final TransactionChainHandler transactionChainHandler, final DataSchemaNode schemaNode) {
+    public static NormalizedNode<?, ?> readList(final YangInstanceIdentifier path,
+                                                final EffectiveModelContext schemaContext,
+                                                final RestconfStrategy strategy,
+                                                final DataSchemaNode schemaNode) {
         final InstanceIdentifierContext<?> iid = new InstanceIdentifierContext<SchemaNode>(
                 path.getParent(), schemaNode, null, schemaContext);
-        final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(iid, null, transactionChainHandler);
-        final NormalizedNode<?, ?> readData = ReadDataTransactionUtil
-                .readData(RestconfDataServiceConstant.ReadData.CONFIG, transactionNode, schemaContext);
-        return readData;
+        final RestconfStrategy restconfStrategy = strategy.buildStrategy(iid);
+        return ReadDataTransactionUtil.readData(
+                RestconfDataServiceConstant.ReadData.CONFIG, restconfStrategy, schemaContext);
     }
 
-    private static void insertWithPointLeafListPut(final DOMDataReadWriteTransaction rwTransaction,
-            final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
-            final NormalizedNode<?, ?> data, final SchemaContext schemaContext, final String point,
-            final OrderedLeafSetNode<?> readLeafList, final boolean before) {
-        rwTransaction.delete(datastore, path.getParent());
+    private static void insertWithPointLeafListPut(final RestconfStrategy strategy,
+                                                   final LogicalDatastoreType datastore,
+                                                   final YangInstanceIdentifier path,
+                                                   final NormalizedNode<?, ?> data,
+                                                   final EffectiveModelContext schemaContext, final String point,
+                                                   final OrderedLeafSetNode<?> readLeafList, final boolean before,
+                                                   final boolean exists) {
+        strategy.delete(datastore, path.getParent());
         final InstanceIdentifierContext<?> instanceIdentifier =
-                ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.absent());
+                ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.empty());
         int lastItemPosition = 0;
         for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
             if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
@@ -323,24 +299,30 @@ public final class PutDataTransactionUtil {
         }
         int lastInsertedPosition = 0;
         final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.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) {
-                simplePut(datastore, path, rwTransaction, schemaContext, data);
+                simplePut(datastore, path, strategy, schemaContext, data, exists);
             }
             final YangInstanceIdentifier childPath = path.getParent().node(nodeChild.getIdentifier());
-            rwTransaction.put(datastore, childPath, nodeChild);
+            if (exists) {
+                strategy.replace(datastore, childPath, nodeChild);
+            } else {
+                strategy.create(datastore, childPath, nodeChild);
+            }
             lastInsertedPosition++;
         }
     }
 
-    private static void insertWithPointListPut(final DOMDataReadWriteTransaction writeTx,
-            final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
-            final NormalizedNode<?, ?> data, final SchemaContext schemaContext, final String point,
-            final OrderedMapNode readList, final boolean before) {
-        writeTx.delete(datastore, path.getParent());
+    private static void insertWithPointListPut(final RestconfStrategy strategy,
+                                               final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
+                                               final NormalizedNode<?, ?> data,
+                                               final EffectiveModelContext schemaContext, final String point,
+                                               final OrderedMapNode readList, final boolean before,
+                                               final boolean exists) {
+        strategy.delete(datastore, path.getParent());
         final InstanceIdentifierContext<?> instanceIdentifier =
-                ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.absent());
+                ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.empty());
         int lastItemPosition = 0;
         for (final MapEntryNode mapEntryNode : readList.getValue()) {
             if (mapEntryNode.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
@@ -353,53 +335,76 @@ public final class PutDataTransactionUtil {
         }
         int lastInsertedPosition = 0;
         final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent());
-        writeTx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
+        strategy.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
         for (final MapEntryNode mapEntryNode : readList.getValue()) {
             if (lastInsertedPosition == lastItemPosition) {
-                simplePut(datastore, path, writeTx, schemaContext, data);
+                simplePut(datastore, path, strategy, schemaContext, data, exists);
             }
             final YangInstanceIdentifier childPath = path.getParent().node(mapEntryNode.getIdentifier());
-            writeTx.put(datastore, childPath, mapEntryNode);
+            if (exists) {
+                strategy.replace(datastore, childPath, mapEntryNode);
+            } else {
+                strategy.create(datastore, childPath, mapEntryNode);
+            }
             lastInsertedPosition++;
         }
     }
 
     private static void listPut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
-            final DOMDataReadWriteTransaction writeTx, final SchemaContext schemaContext,
-            final OrderedLeafSetNode<?> payload) {
+                                final RestconfStrategy strategy, final SchemaContext schemaContext,
+                                final OrderedLeafSetNode<?> payload, final boolean exists) {
         final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path);
-        writeTx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
-        TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx);
+        strategy.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
+        TransactionUtil.ensureParentsByMerge(path, schemaContext, strategy);
         for (final LeafSetEntryNode<?> child : ((LeafSetNode<?>) payload).getValue()) {
             final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
-            writeTx.put(datastore, childPath, child);
+            if (exists) {
+                strategy.replace(datastore, childPath, child);
+            } else {
+                strategy.create(datastore, childPath, child);
+            }
         }
     }
 
     private static void listPut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
-            final DOMDataReadWriteTransaction writeTx, final SchemaContext schemaContext,
-            final OrderedMapNode payload) {
+                                final RestconfStrategy strategy, final SchemaContext schemaContext,
+                                final OrderedMapNode payload, final boolean exists) {
         final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path);
-        writeTx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
-        TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx);
+        strategy.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
+        TransactionUtil.ensureParentsByMerge(path, schemaContext, strategy);
         for (final MapEntryNode child : payload.getValue()) {
             final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
-            writeTx.put(datastore, childPath, child);
+            if (exists) {
+                strategy.replace(datastore, childPath, child);
+            } else {
+                strategy.create(datastore, childPath, child);
+            }
         }
     }
 
     private static void simplePut(final LogicalDatastoreType configuration, final YangInstanceIdentifier path,
-            final DOMDataReadWriteTransaction writeTx, final SchemaContext schemaContext,
-            final NormalizedNode<?, ?> data) {
-        TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx);
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data);
+                                  final RestconfStrategy strategy, final SchemaContext schemaContext,
+                                  final NormalizedNode<?, ?> data, final boolean exists) {
+        TransactionUtil.ensureParentsByMerge(path, schemaContext, strategy);
+        if (exists) {
+            strategy.replace(LogicalDatastoreType.CONFIGURATION, path, data);
+        } else {
+            strategy.create(LogicalDatastoreType.CONFIGURATION, path, data);
+        }
     }
 
-    private static CheckedFuture<Void, TransactionCommitFailedException> makePut(final YangInstanceIdentifier path,
-            final SchemaContext schemaContext, final DOMDataWriteTransaction writeTx, final NormalizedNode<?, ?> data) {
-        TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx);
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data);
-        return writeTx.submit();
+    private static FluentFuture<? extends CommitInfo> makePut(final YangInstanceIdentifier path,
+                                                              final SchemaContext schemaContext,
+                                                              final RestconfStrategy strategy,
+                                                              final NormalizedNode<?, ?> data,
+                                                              final boolean exists) {
+        TransactionUtil.ensureParentsByMerge(path, schemaContext, strategy);
+        if (exists) {
+            strategy.replace(LogicalDatastoreType.CONFIGURATION, path, data);
+        } else {
+            strategy.create(LogicalDatastoreType.CONFIGURATION, path, data);
+        }
+        return strategy.commit();
     }
 
     public static DataSchemaNode checkListAndOrderedType(final SchemaContext ctx, final YangInstanceIdentifier path) {
@@ -409,17 +414,20 @@ public final class PutDataTransactionUtil {
 
         if (dataSchemaNode instanceof ListSchemaNode) {
             if (!((ListSchemaNode) dataSchemaNode).isUserOrdered()) {
-                throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user list.");
+                throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user list.",
+                        RestconfError.ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
             }
             return dataSchemaNode;
         }
         if (dataSchemaNode instanceof LeafListSchemaNode) {
             if (!((LeafListSchemaNode) dataSchemaNode).isUserOrdered()) {
                 throw new RestconfDocumentedException(
-                        "Insert parameter can be used only with ordered-by user leaf-list.");
+                        "Insert parameter can be used only with ordered-by user leaf-list.",
+                        RestconfError.ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
             }
             return dataSchemaNode;
         }
-        throw new RestconfDocumentedException("Insert parameter can be used only with list or leaf-list");
+        throw new RestconfDocumentedException("Insert parameter can be used only with list or leaf-list",
+                RestconfError.ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
     }
 }