BUG 1211 - deletion non existing target returns 500
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / restconf / impl / BrokerFacade.java
index 1cc1f783d676ed69f68c959d1024a58349dc51d9..3d047dd07f53e47a4000a5de137fcc52e3affa75 100644 (file)
@@ -7,21 +7,24 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
 import java.util.concurrent.Future;
-
 import javax.ws.rs.core.Response.Status;
-
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.rest.impl.RestconfProvider;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -53,9 +56,7 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
 
     private void checkPreconditions() {
         if( context == null || dataService == null ) {
-            ResponseException _responseException = new ResponseException( Status.SERVICE_UNAVAILABLE,
-                    RestconfProvider.NOT_INITALIZED_MSG );
-            throw _responseException;
+            throw new RestconfDocumentedException( Status.SERVICE_UNAVAILABLE );
         }
     }
 
@@ -95,17 +96,10 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
         return mountPoint.readOperationalData( path );
     }
 
-    public RpcResult<CompositeNode> invokeRpc( final QName type, final CompositeNode payload ) {
+    public Future<RpcResult<CompositeNode>> invokeRpc( final QName type, final CompositeNode payload ) {
         this.checkPreconditions();
 
-        final Future<RpcResult<CompositeNode>> future = context.rpc( type, payload );
-
-        try {
-            return future.get();
-        }
-        catch( Exception e ) {
-            throw new ResponseException( e, "Error invoking RPC " + type );
-        }
+        return context.rpc( type, payload );
     }
 
     public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut( final InstanceIdentifier path,
@@ -138,9 +132,9 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
         if (availableNode != null) {
             String errMsg = "Post Configuration via Restconf was not executed because data already exists";
             BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
-            // FIXME: return correct ietf-restconf:errors -> follow specification
-            // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
-            throw new ResponseException(Status.CONFLICT, errMsg);
+
+            throw new RestconfDocumentedException(
+                    "Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS );
         }
         BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
         transaction.putConfigurationData( path, payload );
@@ -157,9 +151,9 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
         if (availableNode != null) {
             String errMsg = "Post Configuration via Restconf was not executed because data already exists";
             BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
-            // FIXME: return correct ietf-restconf:errors -> follow specification
-            // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
-            throw new ResponseException(Status.CONFLICT, errMsg);
+
+            throw new RestconfDocumentedException(
+                    "Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS );
         }
         BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
         transaction.putConfigurationData( path, payload );
@@ -168,20 +162,24 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
 
     public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete( final InstanceIdentifier path ) {
         this.checkPreconditions();
-
-        final DataModificationTransaction transaction = dataService.beginTransaction();
-        LOG.info( "Delete Configuration via Restconf: {}", path );
-        transaction.removeConfigurationData( path );
-        return transaction.commit();
+        return deleteDataAtTarget(path,dataService.beginTransaction());
     }
 
     public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
                                           final MountInstance mountPoint, final InstanceIdentifier path ) {
         this.checkPreconditions();
+        return deleteDataAtTarget(path,mountPoint.beginTransaction());
+    }
 
-        final DataModificationTransaction transaction = mountPoint.beginTransaction();
-        LOG.info( "Delete Configuration via Restconf: {}", path );
-        transaction.removeConfigurationData( path );
+    private Future<RpcResult<TransactionStatus>> deleteDataAtTarget(final InstanceIdentifier path,
+            final DataModificationTransaction transaction) {
+        LOG.info("Delete Configuration via Restconf: {}", path);
+        CompositeNode redDataAtPath = transaction.readConfigurationData(path);
+        if (redDataAtPath == null) {
+            return Futures.immediateFuture(Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
+                    Collections.<RpcError> emptyList()));
+        }
+        transaction.removeConfigurationData(path);
         return transaction.commit();
     }