Eliminate PostDataTransactionUtil 01/107801/3
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 11 Sep 2023 22:22:13 +0000 (00:22 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 11 Sep 2023 22:29:47 +0000 (00:29 +0200)
These utilities are tightly coupled to RestconfStrategy, rehost them
there.

JIRA: NETCONF-1126
Change-Id: Ifacc3efa84c4dc91fdde181abe66c54291883941
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/MdsalRestconfStrategy.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/MdsalRestconfTransaction.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/NetconfRestconfStrategy.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/RestconfStrategy.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PostDataTransactionUtil.java [deleted file]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/AbstractRestconfStrategyTest.java

index 12acd86482285f514d13aff599a9add87a623a12..57e59d7d530a8273839c11c17c23d8e762e9ceb4 100644 (file)
@@ -84,7 +84,6 @@ import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSu
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.PatchDataTransactionUtil;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.ReadDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants;
 import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
@@ -498,7 +497,7 @@ public final class RestconfDataServiceImpl {
             path = path.node(arg);
         }
 
-        PostDataTransactionUtil.postData(path, data, strategy, context, params);
+        strategy.postData(path, data, context, params);
         return Response.created(resolveLocation(uriInfo, path, context, data)).build();
     }
 
index dbb1ce4f0df6c757289ade03c3012d101c2cf2f7..48105427e2167132397500af0d2ae19781cfad49 100644 (file)
@@ -102,9 +102,9 @@ public final class MdsalRestconfStrategy extends RestconfStrategy {
     }
 
     @Override
-    public ListenableFuture<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+    ListenableFuture<Boolean> exists(final YangInstanceIdentifier path) {
         try (var tx = dataBroker.newReadOnlyTransaction()) {
-            return tx.exists(store, path);
+            return tx.exists(LogicalDatastoreType.CONFIGURATION, path);
         }
     }
 }
index e2167fb5fe72d73e978302e4e587d7ab88d45afb..a4b598bfe4d9d4a59285ffc2e06ba4cbe9884712 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.restconf.nb.rfc8040.rests.transactions;
 
 import static com.google.common.base.Verify.verifyNotNull;
 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
-import static org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil.checkItemDoesNotExists;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Collection;
@@ -86,13 +85,13 @@ final class MdsalRestconfTransaction extends RestconfTransaction {
                 BatchedExistenceCheck.start(verifyNotNull(rwTx), CONFIGURATION, path, children);
 
             for (final NormalizedNode child : children) {
-                final YangInstanceIdentifier childPath = path.node(child.name());
+                final var childPath = path.node(child.name());
                 verifyNotNull(rwTx).put(CONFIGURATION, childPath, child);
             }
             // ... finally collect existence checks and abort the transaction if any of them failed.
             checkExistence(path, check);
         } else {
-            checkItemDoesNotExists(verifyNotNull(rwTx).exists(CONFIGURATION, path), path);
+            RestconfStrategy.checkItemDoesNotExists(verifyNotNull(rwTx).exists(CONFIGURATION, path), path);
             TransactionUtil.ensureParentsByMerge(path, schemaContext, this);
             verifyNotNull(rwTx).put(CONFIGURATION, path, data);
         }
index fc5922e8420abca4aac1905f50f96dfa52b19d38..be91400b25c83b8f9b9a234d47bb9322ee318462 100644 (file)
@@ -79,8 +79,8 @@ public final class NetconfRestconfStrategy extends RestconfStrategy {
     }
 
     @Override
-    public ListenableFuture<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-        return Futures.transform(remapException(read(store, path)),
+    ListenableFuture<Boolean> exists(final YangInstanceIdentifier path) {
+        return Futures.transform(remapException(netconfService.getConfig(path)),
             optionalNode -> optionalNode != null && optionalNode.isPresent(),
             MoreExecutors.directExecutor());
     }
index e66a306bfa76f8d3697e181df5d59790392bc1f9..0f2009145143bf3570fd25981a1ff27ec761d170 100644 (file)
@@ -26,18 +26,26 @@ import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
 import org.opendaylight.restconf.api.query.InsertParam;
 import org.opendaylight.restconf.api.query.PointParam;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfFuture;
 import org.opendaylight.restconf.common.errors.SettableRestconfFuture;
 import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.TransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.YangInstanceIdentifierDeserializer;
 import org.opendaylight.yangtools.yang.common.Empty;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Baseline execution strategy for various RESTCONF operations.
@@ -64,6 +72,8 @@ public abstract class RestconfStrategy {
         REPLACED;
     }
 
+    private static final Logger LOG = LoggerFactory.getLogger(RestconfStrategy.class);
+
     RestconfStrategy() {
         // Hidden on purpose
     }
@@ -115,13 +125,14 @@ public abstract class RestconfStrategy {
             YangInstanceIdentifier path, List<YangInstanceIdentifier> fields);
 
     /**
-     * Check if data already exists in the datastore.
+     * Check if data already exists in the configuration datastore.
      *
-     * @param store the logical data store which should be modified
      * @param path the data object path
-     * @return a FluentFuture containing the result of the check
+     * @return a ListenableFuture containing the result of the check
      */
-    public abstract ListenableFuture<Boolean> exists(LogicalDatastoreType store, YangInstanceIdentifier path);
+    // FIXME: this method should be hosted in RestconfTransaction
+    // FIXME: this method should only be needed in MdsalRestconfStrategy
+    abstract ListenableFuture<Boolean> exists(YangInstanceIdentifier path);
 
     /**
      * Delete data from the configuration datastore. If the data does not exist, this operation will fail, as outlined
@@ -188,13 +199,13 @@ public abstract class RestconfStrategy {
      */
     public @NonNull CreateOrReplaceResult putData(final YangInstanceIdentifier path, final NormalizedNode data,
             final EffectiveModelContext context, final WriteDataParams params) {
-        final var exists = TransactionUtil.syncAccess(exists(LogicalDatastoreType.CONFIGURATION, path), path);
+        final var exists = TransactionUtil.syncAccess(exists(path), path);
 
         final var insert = params.insert();
         final ListenableFuture<? extends CommitInfo> commitFuture;
         if (insert != null) {
             final var parentPath = path.coerceParent();
-            PostDataTransactionUtil.checkListAndOrderedType(context, parentPath);
+            checkListAndOrderedType(context, parentPath);
             commitFuture = insertAndCommit(path, data, insert, params.point(), parentPath, context);
         } else {
             commitFuture = replaceAndCommit(prepareWriteExecution(), path, data, context);
@@ -274,4 +285,148 @@ public abstract class RestconfStrategy {
         tx.replace(path, data, context);
         return tx.commit();
     }
+
+    private static DataSchemaNode checkListAndOrderedType(final EffectiveModelContext ctx,
+            final YangInstanceIdentifier path) {
+        final var dataSchemaNode = DataSchemaContextTree.from(ctx).findChild(path).orElseThrow().dataSchemaNode();
+
+        final String message;
+        if (dataSchemaNode instanceof ListSchemaNode listSchema) {
+            if (listSchema.isUserOrdered()) {
+                return listSchema;
+            }
+            message = "Insert parameter can be used only with ordered-by user list.";
+        } else if (dataSchemaNode instanceof LeafListSchemaNode leafListSchema) {
+            if (leafListSchema.isUserOrdered()) {
+                return leafListSchema;
+            }
+            message = "Insert parameter can be used only with ordered-by user leaf-list.";
+        } else {
+            message = "Insert parameter can be used only with list or leaf-list";
+        }
+        throw new RestconfDocumentedException(message, ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
+    }
+
+    /**
+     * Check mount point and prepare variables for post data. Close {@link DOMTransactionChain} if any inside of object
+     * {@link RestconfStrategy} provided as a parameter.
+     *
+     * @param path          path
+     * @param data          data
+     * @param schemaContext reference to actual {@link EffectiveModelContext}
+     * @param params        {@link WriteDataParams}
+     */
+    public final void postData(final YangInstanceIdentifier path, final NormalizedNode data,
+            final EffectiveModelContext schemaContext, final WriteDataParams params) {
+        TransactionUtil.syncCommit(submitData(path, data, schemaContext, params), "POST", path);
+    }
+
+    private ListenableFuture<? extends CommitInfo> submitData(final YangInstanceIdentifier path,
+            final NormalizedNode data, final EffectiveModelContext schemaContext, final WriteDataParams params) {
+        final var transaction = prepareWriteExecution();
+        final var insert = params.insert();
+        if (insert == null) {
+            return makePost(path, data, schemaContext, transaction);
+        }
+
+        final var parentPath = path.coerceParent();
+        checkListAndOrderedType(schemaContext, parentPath);
+        final var grandParentPath = parentPath.coerceParent();
+
+        return switch (insert) {
+            case FIRST -> {
+                final var readData = transaction.readList(grandParentPath);
+                if (readData == null || readData.isEmpty()) {
+                    transaction.replace(path, data, schemaContext);
+                } else {
+                    checkItemDoesNotExists(exists(path), path);
+                    transaction.remove(grandParentPath);
+                    transaction.replace(path, data, schemaContext);
+                    transaction.replace(grandParentPath, readData, schemaContext);
+                }
+                yield transaction.commit();
+            }
+            case LAST -> makePost(path, data, schemaContext, transaction);
+            case BEFORE -> {
+                final var readData = transaction.readList(grandParentPath);
+                if (readData == null || readData.isEmpty()) {
+                    transaction.replace(path, data, schemaContext);
+                } else {
+                    checkItemDoesNotExists(exists(path), path);
+                    insertWithPointPost(path, data, schemaContext, params.getPoint(), readData, true, transaction);
+                }
+                yield transaction.commit();
+            }
+            case AFTER -> {
+                final var readData = transaction.readList(grandParentPath);
+                if (readData == null || readData.isEmpty()) {
+                    transaction.replace(path, data, schemaContext);
+                } else {
+                    checkItemDoesNotExists(exists(path), path);
+                    insertWithPointPost(path, data, schemaContext, params.getPoint(), readData, false, transaction);
+                }
+                yield transaction.commit();
+            }
+        };
+    }
+
+    private static void insertWithPointPost(final YangInstanceIdentifier path, final NormalizedNode data,
+            final EffectiveModelContext schemaContext, final PointParam point,
+            final NormalizedNodeContainer<?> readList, final boolean before, final RestconfTransaction transaction) {
+        final YangInstanceIdentifier parent = path.coerceParent().coerceParent();
+        transaction.remove(parent);
+        final var pointArg = YangInstanceIdentifierDeserializer.create(schemaContext, point.value()).path
+            .getLastPathArgument();
+        int lastItemPosition = 0;
+        for (var nodeChild : readList.body()) {
+            if (nodeChild.name().equals(pointArg)) {
+                break;
+            }
+            lastItemPosition++;
+        }
+        if (!before) {
+            lastItemPosition++;
+        }
+        int lastInsertedPosition = 0;
+        final var emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, parent);
+        transaction.merge(YangInstanceIdentifier.of(emptySubtree.name()), emptySubtree);
+        for (var nodeChild : readList.body()) {
+            if (lastInsertedPosition == lastItemPosition) {
+                transaction.replace(path, data, schemaContext);
+            }
+            final YangInstanceIdentifier childPath = parent.node(nodeChild.name());
+            transaction.replace(childPath, nodeChild, schemaContext);
+            lastInsertedPosition++;
+        }
+    }
+
+    private static ListenableFuture<? extends CommitInfo> makePost(final YangInstanceIdentifier path,
+            final NormalizedNode data, final EffectiveModelContext schemaContext,
+            final RestconfTransaction transaction) {
+        try {
+            transaction.create(path, data, schemaContext);
+        } catch (RestconfDocumentedException e) {
+            // close transaction if any and pass exception further
+            transaction.cancel();
+            throw e;
+        }
+
+        return transaction.commit();
+    }
+
+    /**
+     * Check if items do NOT already exists at specified {@code path}.
+     *
+     * @param existsFuture if checked data exists
+     * @param path         Path to be checked
+     * @throws RestconfDocumentedException if data already exists.
+     */
+    static void checkItemDoesNotExists(final ListenableFuture<Boolean> existsFuture,
+            final YangInstanceIdentifier path) {
+        if (TransactionUtil.syncAccess(existsFuture, path)) {
+            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);
+        }
+    }
 }
diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PostDataTransactionUtil.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PostDataTransactionUtil.java
deleted file mode 100644 (file)
index 810894b..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.restconf.nb.rfc8040.rests.utils;
-
-import com.google.common.util.concurrent.FluentFuture;
-import com.google.common.util.concurrent.ListenableFuture;
-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.api.query.PointParam;
-import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfTransaction;
-import org.opendaylight.restconf.nb.rfc8040.utils.parser.YangInstanceIdentifierDeserializer;
-import org.opendaylight.yangtools.yang.common.ErrorTag;
-import org.opendaylight.yangtools.yang.common.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-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.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() {
-        // Hidden on purpose
-    }
-
-    /**
-     * Check mount point and prepare variables for post data. Close {@link DOMTransactionChain} if any inside of object
-     * {@link RestconfStrategy} provided as a parameter.
-     *
-     * @param path          path
-     * @param data          data
-     * @param strategy      Object that perform the actual DS operations
-     * @param schemaContext reference to actual {@link EffectiveModelContext}
-     * @param params        {@link WriteDataParams}
-     */
-    public static void postData(final YangInstanceIdentifier path, final NormalizedNode data,
-            final RestconfStrategy strategy, final EffectiveModelContext schemaContext, final WriteDataParams params) {
-        TransactionUtil.syncCommit(submitData(path, data, strategy, schemaContext, params), "POST", path);
-    }
-
-    public static DataSchemaNode checkListAndOrderedType(final EffectiveModelContext ctx,
-            final YangInstanceIdentifier path) {
-        final var dataSchemaNode = DataSchemaContextTree.from(ctx).findChild(path).orElseThrow().dataSchemaNode();
-
-        final String message;
-        if (dataSchemaNode instanceof ListSchemaNode listSchema) {
-            if (listSchema.isUserOrdered()) {
-                return listSchema;
-            }
-            message = "Insert parameter can be used only with ordered-by user list.";
-        } else if (dataSchemaNode instanceof LeafListSchemaNode leafListSchema) {
-            if (leafListSchema.isUserOrdered()) {
-                return leafListSchema;
-            }
-            message = "Insert parameter can be used only with ordered-by user leaf-list.";
-        } else {
-            message = "Insert parameter can be used only with list or leaf-list";
-        }
-        throw new RestconfDocumentedException(message, ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
-    }
-
-    /**
-     * Post data by type.
-     *
-     * @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 ListenableFuture<? extends CommitInfo> submitData(final YangInstanceIdentifier path,
-            final NormalizedNode data, final RestconfStrategy strategy, final EffectiveModelContext schemaContext,
-            final WriteDataParams params) {
-        final var transaction = strategy.prepareWriteExecution();
-        final var insert = params.insert();
-        if (insert == null) {
-            return makePost(path, data, schemaContext, transaction);
-        }
-
-        final var parentPath = path.coerceParent();
-        checkListAndOrderedType(schemaContext, parentPath);
-        final var grandParentPath = parentPath.coerceParent();
-
-        return switch (insert) {
-            case FIRST -> {
-                final var readData = transaction.readList(grandParentPath);
-                if (readData == null || readData.isEmpty()) {
-                    transaction.replace(path, data, schemaContext);
-                } else {
-                    checkItemDoesNotExists(strategy.exists(LogicalDatastoreType.CONFIGURATION, path), path);
-                    transaction.remove(grandParentPath);
-                    transaction.replace(path, data, schemaContext);
-                    transaction.replace(grandParentPath, readData, schemaContext);
-                }
-                yield transaction.commit();
-            }
-            case LAST -> makePost(path, data, schemaContext, transaction);
-            case BEFORE -> {
-                final var readData = transaction.readList(grandParentPath);
-                if (readData == null || readData.isEmpty()) {
-                    transaction.replace(path, data, schemaContext);
-                } else {
-                    checkItemDoesNotExists(strategy.exists(LogicalDatastoreType.CONFIGURATION, path), path);
-                    insertWithPointPost(path, data, schemaContext, params.getPoint(), readData, true, transaction);
-                }
-                yield transaction.commit();
-            }
-            case AFTER -> {
-                final var readData = transaction.readList(grandParentPath);
-                if (readData == null || readData.isEmpty()) {
-                    transaction.replace(path, data, schemaContext);
-                } else {
-                    checkItemDoesNotExists(strategy.exists(LogicalDatastoreType.CONFIGURATION, path), path);
-                    insertWithPointPost(path, data, schemaContext, params.getPoint(), readData, false, transaction);
-                }
-                yield transaction.commit();
-            }
-        };
-    }
-
-    private static void insertWithPointPost(final YangInstanceIdentifier path, final NormalizedNode data,
-                                            final EffectiveModelContext schemaContext, final PointParam point,
-                                            final NormalizedNodeContainer<?> readList, final boolean before,
-                                            final RestconfTransaction transaction) {
-        final YangInstanceIdentifier parent = path.coerceParent().coerceParent();
-        transaction.remove(parent);
-        final var pointArg = YangInstanceIdentifierDeserializer.create(schemaContext, point.value()).path
-            .getLastPathArgument();
-        int lastItemPosition = 0;
-        for (var nodeChild : readList.body()) {
-            if (nodeChild.name().equals(pointArg)) {
-                break;
-            }
-            lastItemPosition++;
-        }
-        if (!before) {
-            lastItemPosition++;
-        }
-        int lastInsertedPosition = 0;
-        final var emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, parent);
-        transaction.merge(YangInstanceIdentifier.of(emptySubtree.name()), emptySubtree);
-        for (var nodeChild : readList.body()) {
-            if (lastInsertedPosition == lastItemPosition) {
-                transaction.replace(path, data, schemaContext);
-            }
-            final YangInstanceIdentifier childPath = parent.node(nodeChild.name());
-            transaction.replace(childPath, nodeChild, schemaContext);
-            lastInsertedPosition++;
-        }
-    }
-
-    private static ListenableFuture<? extends CommitInfo> makePost(final YangInstanceIdentifier path,
-            final NormalizedNode data, final EffectiveModelContext schemaContext,
-            final RestconfTransaction transaction) {
-        try {
-            transaction.create(path, data, schemaContext);
-        } catch (RestconfDocumentedException e) {
-            // close transaction if any and pass exception further
-            transaction.cancel();
-            throw e;
-        }
-
-        return transaction.commit();
-    }
-
-    /**
-     * Check if items do NOT already exists at specified {@code path}.
-     *
-     * @param existsFuture if checked data exists
-     * @param path         Path to be checked
-     * @throws RestconfDocumentedException if data already exists.
-     */
-    public static void checkItemDoesNotExists(final ListenableFuture<Boolean> existsFuture,
-                                              final YangInstanceIdentifier path) {
-        if (TransactionUtil.syncAccess(existsFuture, path)) {
-            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);
-        }
-    }
-}
index 4e72b2532fe3797a2bdbceedca78003f7dca1d2c..5eec835858eadfa4f1243afec17aed992a10feac 100644 (file)
@@ -35,7 +35,6 @@ import org.opendaylight.restconf.common.patch.PatchStatusContext;
 import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
 import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.PatchDataTransactionUtil;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.ReadDataTransactionUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.patch.rev170222.yang.patch.yang.patch.Edit.Operation;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
@@ -247,7 +246,7 @@ abstract class AbstractRestconfStrategyTest extends AbstractJukeboxTest {
 
     @Test
     public final void testPostContainerData() {
-        PostDataTransactionUtil.postData(JUKEBOX_IID, EMPTY_JUKEBOX, testPostContainerDataStrategy(), JUKEBOX_SCHEMA,
+        testPostContainerDataStrategy().postData(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA,
             WriteDataParams.empty());
     }
 
@@ -255,9 +254,8 @@ abstract class AbstractRestconfStrategyTest extends AbstractJukeboxTest {
 
     @Test
     public final void testPostListData() {
-        PostDataTransactionUtil.postData(PLAYLIST_IID, PLAYLIST,
-            testPostListDataStrategy(BAND_ENTRY, PLAYLIST_IID.node(BAND_ENTRY.name())), JUKEBOX_SCHEMA,
-            WriteDataParams.empty());
+        testPostListDataStrategy(BAND_ENTRY, PLAYLIST_IID.node(BAND_ENTRY.name())).postData(PLAYLIST_IID, PLAYLIST,
+            JUKEBOX_SCHEMA, WriteDataParams.empty());
     }
 
     abstract @NonNull RestconfStrategy testPostListDataStrategy(MapEntryNode entryNode, YangInstanceIdentifier node);
@@ -267,8 +265,8 @@ abstract class AbstractRestconfStrategyTest extends AbstractJukeboxTest {
         final var domException = new DOMException((short) 414, "Post request failed");
 
         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
-            () -> PostDataTransactionUtil.postData(JUKEBOX_IID, EMPTY_JUKEBOX,
-                testPostDataFailStrategy(domException), JUKEBOX_SCHEMA, WriteDataParams.empty()));
+            () -> testPostDataFailStrategy(domException).postData(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA,
+                WriteDataParams.empty()));
         assertEquals(1, ex.getErrors().size());
         assertThat(ex.getErrors().get(0).getErrorInfo(), containsString(domException.getMessage()));
     }