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;
* 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() {
* @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);
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.
*/
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);
}