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 72ee864ad3e2d25fc79a6102c519c68b5d1a0001..b9f20b79df08a9d84b039ff5f36132ad5b4597c9 100644 (file)
@@ -16,8 +16,6 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 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.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
@@ -25,9 +23,7 @@ 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.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();
@@ -122,12 +113,12 @@ public final class PutDataTransactionUtil {
     }
 
     private static void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final MapEntryNode payload,
-            final List<QName> keyDefinitions) {
+                                                      final List<QName> keyDefinitions) {
         final Map<QName, Object> mutableCopyUriKeyValues = new HashMap<>(uriKeyValues);
         for (final QName keyDefinition : keyDefinitions) {
             final Object uriKeyValue = RestconfDocumentedException.throwIfNull(
-                mutableCopyUriKeyValues.remove(keyDefinition), ErrorType.PROTOCOL, ErrorTag.DATA_MISSING,
-                "Missing key %s in URI.", keyDefinition);
+                    mutableCopyUriKeyValues.remove(keyDefinition), ErrorType.PROTOCOL, ErrorTag.DATA_MISSING,
+                    "Missing key %s in URI.", keyDefinition);
 
             final Object dataKeyValue = payload.getIdentifier().getValue(keyDefinition);
 
@@ -141,152 +132,131 @@ public final class PutDataTransactionUtil {
     }
 
     /**
-     * Check mount point and prepare variables for put data to DS. Close {@link DOMTransactionChain} inside of object
-     * {@link TransactionVarsWrapper} provided as a parameter.
+     * 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
+     * @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 DOMDataTreeReadWriteTransaction readWriteTransaction =
-                transactionNode.getTransactionChain().newReadWriteTransaction();
 
-        final FluentFuture<Boolean> 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 FluentFuture<? extends CommitInfo> submitData = submitData(path, schemaContext,
-                transactionNode.getTransactionChainHandler(), readWriteTransaction, payload.getData(), insert, point);
-        //This method will close transactionChain
+        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,
-                transactionNode.getTransactionChain());
+                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
+     * @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 FluentFuture<? extends CommitInfo> submitData(final YangInstanceIdentifier path,
-            final SchemaContext schemaContext, final TransactionChainHandler transactionChainHandler,
-            final DOMDataTreeReadWriteTransaction 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);
+            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, transactionChainHandler, schemaNode);
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
                     final OrderedMapNode readList = (OrderedMapNode) readData;
                     if (readList == null || readList.getValue().isEmpty()) {
-                        return makePut(path, schemaContext, readWriteTransaction, data);
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, path.getParent());
-                        simplePut(LogicalDatastoreType.CONFIGURATION, path, readWriteTransaction,
-                            schemaContext, data);
-                        listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), readWriteTransaction,
-                            schemaContext, readList);
-                        return readWriteTransaction.commit();
+                        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, transactionChainHandler, schemaNode);
+                    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);
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, path.getParent());
-                        simplePut(LogicalDatastoreType.CONFIGURATION, path, readWriteTransaction,
-                            schemaContext, data);
-                        listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), readWriteTransaction,
-                            schemaContext, readLeafList);
-                        return readWriteTransaction.commit();
+                        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);
+                return makePut(path, schemaContext, strategy, data, exists);
             case "before":
                 if (schemaNode instanceof ListSchemaNode) {
-                    final NormalizedNode<?, ?> readData =
-                            readList(path, schemaContext, transactionChainHandler, schemaNode);
+                    final NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
                     final OrderedMapNode readList = (OrderedMapNode) readData;
                     if (readList == null || readList.getValue().isEmpty()) {
-                        return makePut(path, schemaContext, readWriteTransaction, data);
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        insertWithPointListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION, path,
-                            data, schemaContext, point, readList, true);
-                        return readWriteTransaction.commit();
+                        insertWithPointListPut(strategy, LogicalDatastoreType.CONFIGURATION, path,
+                                data, schemaContext, point, readList, true, exists);
+                        return strategy.commit();
                     }
                 } else {
-                    final NormalizedNode<?, ?> readData =
-                            readList(path, schemaContext, transactionChainHandler, schemaNode);
+                    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);
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        insertWithPointLeafListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                            path, data, schemaContext, point, readLeafList, true);
-                        return readWriteTransaction.commit();
+                        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 NormalizedNode<?, ?> readData = readList(path, schemaContext, strategy, schemaNode);
                     final OrderedMapNode readList = (OrderedMapNode) readData;
                     if (readList == null || readList.getValue().isEmpty()) {
-                        return makePut(path, schemaContext, readWriteTransaction, data);
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        insertWithPointListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                            path, data, schemaContext, point, readList, false);
-                        return readWriteTransaction.commit();
+                        insertWithPointListPut(strategy, LogicalDatastoreType.CONFIGURATION,
+                                path, data, schemaContext, point, readList, false, exists);
+                        return strategy.commit();
                     }
                 } else {
-                    final NormalizedNode<?, ?> readData =
-                            readList(path, schemaContext, transactionChainHandler, schemaNode);
+                    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);
+                        return makePut(path, schemaContext, strategy, data, exists);
                     } else {
-                        insertWithPointLeafListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION,
-                            path, data, schemaContext, point, readLeafList, true);
-                        return readWriteTransaction.commit();
+                        insertWithPointLeafListPut(strategy, LogicalDatastoreType.CONFIGURATION,
+                                path, data, schemaContext, point, readLeafList, true, exists);
+                        return strategy.commit();
                     }
                 }
             default:
@@ -296,21 +266,25 @@ public final class PutDataTransactionUtil {
         }
     }
 
-    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 DOMDataTreeReadWriteTransaction 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.empty());
         int lastItemPosition = 0;
@@ -325,22 +299,28 @@ 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 DOMDataTreeReadWriteTransaction 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.empty());
         int lastItemPosition = 0;
@@ -355,54 +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 DOMDataTreeWriteTransaction 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 DOMDataTreeWriteTransaction 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 DOMDataTreeWriteTransaction 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 FluentFuture<? extends CommitInfo> makePut(final YangInstanceIdentifier path,
-            final SchemaContext schemaContext, final DOMDataTreeWriteTransaction writeTx,
-            final NormalizedNode<?, ?> data) {
-        TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx);
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data);
-        return writeTx.commit();
+                                                              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) {