Bug 5528 - Invoke RPC impl 88/39888/18
authorJakub Toth <jatoth@cisco.com>
Mon, 6 Jun 2016 14:00:49 +0000 (16:00 +0200)
committerJakub Toth <jatoth@cisco.com>
Tue, 28 Jun 2016 12:24:02 +0000 (12:24 +0000)
  *create RpcServiceHandler for handling service of rpc
  *create factory of rpc result

Change-Id: I2b2fff5558887e8c6f5e370b36d197dbde271955
Signed-off-by: Jakub Toth <jatoth@cisco.com>
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/RpcServiceHandler.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfInvokeOperationsServiceImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureCallbackTx.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PutDataTransactionUtil.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RestconfInvokeOperationsUtil.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RpcResultFactory.java [new file with mode: 0644]

diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/RpcServiceHandler.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/RpcServiceHandler.java
new file mode 100644 (file)
index 0000000..a2477cc
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.handlers;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+
+/**
+ * Implementation of {@link RpcServiceHandler}
+ *
+ */
+public class RpcServiceHandler implements Handler<DOMRpcService> {
+
+    private final DOMRpcService rpcService;
+
+    public RpcServiceHandler(final DOMRpcService rpcService) {
+        this.rpcService = rpcService;
+    }
+
+    @Override
+    public DOMRpcService get() {
+        return this.rpcService;
+    }
+
+
+}
index d7f955c3197c31834db4c92131397fa2f57173b5..e31939323d1c610951ab77b95ebd88dd3ed52181 100644 (file)
@@ -8,13 +8,49 @@
 package org.opendaylight.restconf.restful.services.impl;
 
 import javax.ws.rs.core.UriInfo;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.restconf.common.references.SchemaContextRef;
+import org.opendaylight.restconf.handlers.RpcServiceHandler;
+import org.opendaylight.restconf.handlers.SchemaContextHandler;
 import org.opendaylight.restconf.restful.services.api.RestconfInvokeOperationsService;
+import org.opendaylight.restconf.restful.utils.RestconfInvokeOperationsUtil;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
+/**
+ * Implementation of {@link RestconfInvokeOperationsService}
+ *
+ */
 public class RestconfInvokeOperationsServiceImpl implements RestconfInvokeOperationsService {
 
+    private RpcServiceHandler rpcServiceHandler;
+    private SchemaContextHandler schemaContextHandler;
+
     @Override
     public NormalizedNodeContext invokeRpc(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) {
-        throw new UnsupportedOperationException("Not yet impemented.");
+        final SchemaPath schemaPath = payload.getInstanceIdentifierContext().getSchemaNode().getPath();
+        final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
+        DOMRpcResult response;
+        SchemaContextRef schemaContextRef;
+        if (mountPoint == null) {
+            response = RestconfInvokeOperationsUtil.invokeRpc(payload.getData(), schemaPath, this.rpcServiceHandler);
+            schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
+        } else {
+            response = RestconfInvokeOperationsUtil.invokeRpcViaMountPoint(mountPoint, payload.getData(), schemaPath);
+            schemaContextRef = new SchemaContextRef(mountPoint.getSchemaContext());
+        }
+        final DOMRpcResult result = RestconfInvokeOperationsUtil.checkResponse(response);
+
+        RpcDefinition resultNodeSchema = null;
+        final NormalizedNode<?, ?> resultData = result.getResult();
+        if ((result != null) && (result.getResult() != null)) {
+            resultNodeSchema = (RpcDefinition) payload.getInstanceIdentifierContext().getSchemaNode();
+        }
+        return new NormalizedNodeContext(new InstanceIdentifierContext<RpcDefinition>(null, resultNodeSchema,
+                mountPoint, schemaContextRef.get()), resultData);
     }
 }
index 9cc7d0fe9eb4ad98e39f5a515a296985b9620d7d..d23f6927234599d1c9d4d4f08048e729c7c5220d 100644 (file)
@@ -37,8 +37,7 @@ public final class DeleteDataTransactionUtil {
         final CheckedFuture<Void, TransactionCommitFailedException> future = submitData(
                 transactionNode.getTransaction(), transactionNode.getInstanceIdentifier().getInstanceIdentifier());
         final ResponseFactory response = new ResponseFactory();
-        FutureCallbackTx.addCallback(future, transactionNode.getTransaction(),
-                RestconfDataServiceConstant.DeleteData.DELETE_TX_TYPE, response);
+        FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.DeleteData.DELETE_TX_TYPE, response);
         return response.build();
     }
 
index 26f97df2beb405dd2d8feac770a1f0d01ce288ea..a3fe0a8a3d78abe27c66ffb8b6e93ee4eb4dd82b 100644 (file)
@@ -11,9 +11,7 @@ import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import javax.annotation.Nullable;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -34,26 +32,23 @@ final class FutureCallbackTx {
      *
      * @param listenableFuture
      *            - future object
-     * @param transaction
-     *            - transaction used for read of future object
      * @param txType
      *            - type of operation (READ, POST, PUT, DELETE)
      * @param dataFactory
      *            - factory setting result
      */
-    static <T, X extends Exception> void addCallback(final CheckedFuture<T, X> listenableFuture,
-            final AsyncTransaction<YangInstanceIdentifier, NormalizedNode<?, ?>> transaction, final String txType,
+    static <T, X extends Exception> void addCallback(final CheckedFuture<T, X> listenableFuture, final String txType,
             final FutureDataFactory<T> dataFactory) {
         Futures.addCallback(listenableFuture, new FutureCallback<T>() {
 
             @Override
             public void onFailure(final Throwable t) {
-                handlingLoggerAndValues(t, txType, transaction, null, null);
+                handlingLoggerAndValues(t, txType, null, null);
             }
 
             @Override
             public void onSuccess(final T result) {
-                handlingLoggerAndValues(null, txType, transaction, result, dataFactory);
+                handlingLoggerAndValues(null, txType, result, dataFactory);
             }
 
         });
@@ -70,21 +65,18 @@ final class FutureCallbackTx {
      *            - exception - if callback is onFailure
      * @param txType
      *            - type of operation (READ, POST, PUT, DELETE)
-     * @param transaction
-     *            - transaction used for read of future object
-     * @param optionalNN
-     *            - result - if callback is on Success
+     * @param result
+     *            - result of future - if callback is on Success
      * @param dataFactory
      *            - setter for result - in callback is onSuccess
      */
     protected static <T> void handlingLoggerAndValues(@Nullable final Throwable t, final String txType,
-            final AsyncTransaction<YangInstanceIdentifier, NormalizedNode<?, ?>> transaction,
             final T result, final FutureDataFactory<T> dataFactory) {
         if (t != null) {
-            LOG.info("Transaction({}) {} FAILED!", txType, transaction.getIdentifier(), t);
-            throw new IllegalStateException("  Transaction(" + txType + ") not committed correctly", t);
+            LOG.info("Transaction({}) FAILED!", txType, t);
+            throw new RestconfDocumentedException("  Transaction(" + txType + ") not committed correctly", t);
         } else {
-            LOG.trace("Transaction({}) {} SUCCESSFUL!", txType, transaction.getIdentifier());
+            LOG.trace("Transaction({}) SUCCESSFUL!", txType);
             dataFactory.setResult(result);
         }
     }
index 2d9c246ac256af6300f4f44436d792e1fb23f91c..5a762ebb7b2878fccaaa3addcb780c31145d2b7d 100644 (file)
@@ -74,8 +74,7 @@ public final class PostDataTransactionUtil {
         final ResponseFactory dataFactory = new ResponseFactory(
                 ReadDataTransactionUtil.readData(RestconfDataServiceConstant.ReadData.CONFIG, transactionNode),
                 location);
-        FutureCallbackTx.addCallback(future, transactionNode.getTransaction(),
-                RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
+        FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
         return dataFactory.build();
     }
 
index 698a4787cb559ea5ef5ce8ffd9b5e50b2e633b08..d0302cfcd3488e32ffc91d9e6b847e4edf4363d6 100644 (file)
@@ -140,8 +140,7 @@ public final class PutDataTransactionUtil {
                 ReadDataTransactionUtil.readData(RestconfDataServiceConstant.ReadData.CONFIG, transactionNode));
         final CheckedFuture<Void, TransactionCommitFailedException> submitData = submitData(path, schemaCtxRef.get(),
                 transactionNode.getTransaction(), payload.getData());
-        FutureCallbackTx.addCallback(submitData, transactionNode.getTransaction(),
-                RestconfDataServiceConstant.PutData.PUT_TX_TYPE, responseFactory);
+        FutureCallbackTx.addCallback(submitData, RestconfDataServiceConstant.PutData.PUT_TX_TYPE, responseFactory);
         return responseFactory.build();
     }
 
index 344db30a8d491f49ac739e609b580d2ec4e6b5b9..3c82c207e2325523c2152755e5fe1c1a630fcd5b 100644 (file)
@@ -92,8 +92,8 @@ public final class ReadDataTransactionUtil {
                     .getTransaction().read(transactionNode.getLogicalDatastoreType(),
                             transactionNode.getInstanceIdentifier().getInstanceIdentifier());
             final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
-            FutureCallbackTx.addCallback(listenableFuture, transactionNode.getTransaction(),
-                    RestconfDataServiceConstant.ReadData.READ_TYPE_TX, dataFactory);
+            FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
+                    dataFactory);
             return dataFactory.build();
         } else {
             return readAllData(transactionNode);
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RestconfInvokeOperationsUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RestconfInvokeOperationsUtil.java
new file mode 100644 (file)
index 0000000..39f5890
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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.restful.utils;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.concurrent.CancellationException;
+import javax.ws.rs.core.Response.Status;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.restconf.handlers.RpcServiceHandler;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Util class for rpc
+ *
+ */
+public class RestconfInvokeOperationsUtil {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RestconfInvokeOperationsUtil.class);
+
+    private RestconfInvokeOperationsUtil() {
+        throw new UnsupportedOperationException("Util class");
+    }
+
+    /**
+     * Invoking rpc via mount point
+     *
+     * @param mountPoint
+     *            - mount point
+     * @param data
+     *            - input data
+     * @param schemaPath
+     *            - schema path of data
+     * @return {@link CheckedFuture}
+     */
+    public static DOMRpcResult invokeRpcViaMountPoint(final DOMMountPoint mountPoint, final NormalizedNode<?, ?> data,
+            final SchemaPath schemaPath) {
+        final Optional<DOMRpcService> mountPointService = mountPoint.getService(DOMRpcService.class);
+        if (mountPointService.isPresent()) {
+            final CheckedFuture<DOMRpcResult, DOMRpcException> rpc = mountPointService.get().invokeRpc(schemaPath,
+                    data);
+            return prepareResult(rpc);
+        }
+        final String errmsg = "RPC service is missing.";
+        LOG.debug(errmsg);
+        throw new RestconfDocumentedException(errmsg);
+    }
+
+    /**
+     * Invoke rpc
+     *
+     * @param data
+     *            - input data
+     * @param schemaPath
+     *            - schema path of data
+     * @param rpcServiceHandler
+     *            - rpc service handler to invoke rpc
+     * @return {@link CheckedFuture}
+     */
+    public static DOMRpcResult invokeRpc(final NormalizedNode<?, ?> data, final SchemaPath schemaPath,
+            final RpcServiceHandler rpcServiceHandler) {
+        final DOMRpcService rpcService = rpcServiceHandler.get();
+        if (rpcService == null) {
+            throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE);
+        }
+
+        final CheckedFuture<DOMRpcResult, DOMRpcException> rpc = rpcService.invokeRpc(schemaPath, data);
+        return prepareResult(rpc);
+    }
+
+    /**
+     * Check the validity of the result
+     *
+     * @param response
+     *            - response of rpc
+     * @return {@link DOMRpcResult} result
+     */
+    public static DOMRpcResult checkResponse(final DOMRpcResult response) {
+        if (response == null) {
+            return null;
+        }
+        try {
+            if ((response.getErrors() == null) || response.getErrors().isEmpty()) {
+                return response;
+            }
+            LOG.debug("RpcError message", response.getErrors());
+            throw new RestconfDocumentedException("RPCerror message ", null, response.getErrors());
+        } catch (final CancellationException e) {
+            final String errMsg = "The operation was cancelled while executing.";
+            LOG.debug("Cancel RpcExecution: " + errMsg, e);
+            throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION);
+        }
+    }
+
+    private static DOMRpcResult prepareResult(final CheckedFuture<DOMRpcResult, DOMRpcException> rpc) {
+        final RpcResultFactory dataFactory = new RpcResultFactory();
+        FutureCallbackTx.addCallback(rpc, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
+        return dataFactory.build();
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RpcResultFactory.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RpcResultFactory.java
new file mode 100644 (file)
index 0000000..313748b
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.restful.utils;
+
+import org.apache.commons.lang3.builder.Builder;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+
+public class RpcResultFactory extends FutureDataFactory<DOMRpcResult> implements Builder<DOMRpcResult> {
+
+    @Override
+    public DOMRpcResult build() {
+        return this.result;
+    }
+
+}