Remove RestconfError.ErrorType
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / FutureCallbackTx.java
index e925612e63bc8e00c582b4e6c3e195c3660daab6..f73e9f1713f4d715ca98a23fd855ff10933ba671 100644 (file)
@@ -12,14 +12,21 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
+import org.opendaylight.mdsal.dom.api.DOMActionException;
 import org.opendaylight.mdsal.dom.api.DOMRpcException;
 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
+import org.opendaylight.netconf.api.DocumentedException;
 import org.opendaylight.netconf.api.NetconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfError;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
+import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -27,7 +34,6 @@ import org.slf4j.LoggerFactory;
  * Add callback for future objects and result set to the data factory.
  */
 final class FutureCallbackTx {
-
     private static final Logger LOG = LoggerFactory.getLogger(FutureCallbackTx.class);
 
     private FutureCallbackTx() {
@@ -46,10 +52,31 @@ final class FutureCallbackTx {
      * @throws RestconfDocumentedException
      *             if the Future throws an exception
      */
-    @SuppressWarnings("checkstyle:IllegalCatch")
+    // FIXME: this is a *synchronous operation* and has to die
     static <T> void addCallback(final ListenableFuture<T> listenableFuture, final String txType,
-            final FutureDataFactory<? super T> dataFactory) throws RestconfDocumentedException {
+                                final FutureDataFactory<? super T> dataFactory) throws RestconfDocumentedException {
+        addCallback(listenableFuture, txType, dataFactory, null, null);
+    }
 
+    /**
+     * Add callback to the future object and close transaction chain.
+     *
+     * @param listenableFuture
+     *             future object
+     * @param txType
+     *             type of operation (READ, POST, PUT, DELETE)
+     * @param dataFactory
+     *             factory setting result
+     * @param strategy Strategy for various RESTCONF operations
+     * @param path unique identifier of a particular node instance in the data tree
+     * @throws RestconfDocumentedException
+     *             if the Future throws an exception
+     */
+    // FIXME: this is a *synchronous operation* and has to die
+    static <T> void addCallback(final ListenableFuture<T> listenableFuture, final String txType,
+                                final FutureDataFactory<? super T> dataFactory,
+                                @Nullable final RestconfStrategy strategy,
+                                final YangInstanceIdentifier path) throws RestconfDocumentedException {
         try {
             final T result = listenableFuture.get();
             dataFactory.setResult(result);
@@ -66,6 +93,9 @@ final class FutureCallbackTx {
             if (cause instanceof DOMRpcException) {
                 dataFactory.setResult((T) new DefaultDOMRpcResult(ImmutableList.of(
                     RpcResultBuilder.newError(RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))));
+            } else if (cause instanceof DOMActionException) {
+                dataFactory.setResult((T) new SimpleDOMActionResult(ImmutableList.of(
+                    RpcResultBuilder.newError(RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))));
             } else if (cause instanceof TransactionCommitFailedException) {
                 /* If device send some error message we want this message to get to client
                    and not just to throw it away or override it with new generic message.
@@ -74,10 +104,23 @@ final class FutureCallbackTx {
                 */
                 final List<Throwable> causalChain = Throwables.getCausalChain(cause);
                 for (Throwable error : causalChain) {
+                    if (error instanceof DocumentedException) {
+                        final DocumentedException.ErrorTag errorTag = ((DocumentedException) error).getErrorTag();
+                        if (errorTag.equals(DocumentedException.ErrorTag.DATA_EXISTS)) {
+                            LOG.trace("Operation via Restconf was not executed because data at {} already exists",
+                                path);
+                            throw new RestconfDocumentedException(e, new RestconfError(ErrorType.PROTOCOL,
+                                RestconfError.ErrorTag.DATA_EXISTS, "Data already exists", path));
+                        } else if (errorTag.equals(DocumentedException.ErrorTag.DATA_MISSING)) {
+                            LOG.trace("Operation via Restconf was not executed because data at {} does not exist",
+                                path);
+                            throw new RestconfDocumentedException(e, new RestconfError(ErrorType.PROTOCOL,
+                                RestconfError.ErrorTag.DATA_MISSING, "Data does not exist", path));
+                        }
+                    }
                     if (error instanceof NetconfDocumentedException) {
                         throw new RestconfDocumentedException(error.getMessage(),
-                                RestconfError.ErrorType.valueOfCaseInsensitive(
-                                        ((NetconfDocumentedException) error).getErrorType().getTypeValue()),
+                                ((NetconfDocumentedException) error).getErrorType(),
                                 RestconfError.ErrorTag.valueOfCaseInsensitive(
                                         ((NetconfDocumentedException) error).getErrorTag().getTagValue()), e);
                     }