Merge "BUG 1839 - HTTP delete of non existing data"
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / restconf / impl / BrokerFacade.java
index f11e25c046feab69fe3c41f229dfdbadd496e18d..95fb9a4826d2b6c5115c31d6dfff066b9a0b4af5 100644 (file)
@@ -7,8 +7,18 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
+
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import javax.ws.rs.core.Response.Status;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
@@ -36,15 +46,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.ws.rs.core.Response.Status;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Future;
-
-import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
-import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
-
 public class BrokerFacade {
     private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class);
 
@@ -176,31 +177,39 @@ public class BrokerFacade {
     private NormalizedNode<?, ?> readDataViaTransaction(final DOMDataReadTransaction transaction,
             LogicalDatastoreType datastore, YangInstanceIdentifier path) {
         LOG.trace("Read " + datastore.name() + " via Restconf: {}", path);
-        final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture =
-                                                                 transaction.read(datastore, path);
+        final ListenableFuture<Optional<NormalizedNode<?, ?>>> listenableFuture = transaction.read(datastore, path);
+        if (listenableFuture != null) {
+            Optional<NormalizedNode<?, ?>> optional;
+            try {
+                LOG.debug("Reading result data from transaction.");
+                optional = listenableFuture.get();
+            } catch (InterruptedException | ExecutionException e) {
+                throw new RestconfDocumentedException("Problem to get data from transaction.", e.getCause());
 
-        try {
-            Optional<NormalizedNode<?, ?>> optional = listenableFuture.checkedGet();
-            return optional.isPresent() ? optional.get() : null;
-        } catch(ReadFailedException e) {
-            throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
+            }
+            if (optional != null) {
+                if (optional.isPresent()) {
+                    return optional.get();
+                }
+            }
         }
+        return null;
     }
 
     private CheckedFuture<Void, TransactionCommitFailedException> postDataViaTransaction(
             final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
             final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, DataNormalizationOperation<?> root) {
-        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> futureDatastoreData =
-                                                               rWTransaction.read(datastore, path);
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> futureDatastoreData = rWTransaction.read(datastore, path);
         try {
-            final Optional<NormalizedNode<?, ?>> optionalDatastoreData = futureDatastoreData.checkedGet();
+            final Optional<NormalizedNode<?, ?>> optionalDatastoreData = futureDatastoreData.get();
             if (optionalDatastoreData.isPresent() && payload.equals(optionalDatastoreData.get())) {
-                LOG.trace("Post Configuration via Restconf was not executed because data already exists :{}", path);
+                String errMsg = "Post Configuration via Restconf was not executed because data already exists";
+                LOG.trace(errMsg + ":{}", path);
                 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
                         ErrorTag.DATA_EXISTS);
             }
-        } catch(ReadFailedException e) {
-            LOG.warn("Error reading from datastore with path: " + path, e);
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.trace("It wasn't possible to get data loaded from datastore at path " + path);
         }
 
         ensureParentsByMerge(datastore, path, rWTransaction, root);
@@ -221,7 +230,7 @@ public class BrokerFacade {
     private CheckedFuture<Void, TransactionCommitFailedException> deleteDataViaTransaction(
             final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType datastore,
             YangInstanceIdentifier path) {
-        LOG.info("Delete " + datastore.name() + " via Restconf: {}", path);
+        LOG.trace("Delete " + datastore.name() + " via Restconf: {}", path);
         writeTransaction.delete(datastore, path);
         return writeTransaction.submit();
     }
@@ -241,21 +250,25 @@ public class BrokerFacade {
             try {
                 currentOp = currentOp.getChild(currentArg);
             } catch (DataNormalizationException e) {
-                throw new RestconfDocumentedException(
-                        String.format("Error normalizing data for path %s", normalizedPath), e);
+                throw new IllegalArgumentException(
+                        String.format("Invalid child encountered in path %s", normalizedPath), e);
             }
             currentArguments.add(currentArg);
             YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments);
 
+            final Boolean exists;
+
             try {
 
-                boolean exists = rwTx.exists(store, currentPath).checkedGet();
-                if (!exists && iterator.hasNext()) {
-                    rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
-                }
+                CheckedFuture<Boolean, ReadFailedException> future = rwTx.exists(store, currentPath);
+                exists = future.checkedGet();
             } catch (ReadFailedException e) {
                 LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
-                throw new RestconfDocumentedException("Failed to read pre-existing data", e);
+                throw new IllegalStateException("Failed to read pre-existing data", e);
+            }
+
+            if (!exists && iterator.hasNext()) {
+                rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
             }
         }
     }