a0bee88262c155278fa97a56e524de27211d9961
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / RestconfInvokeOperationsUtil.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.util.concurrent.CancellationException;
12 import org.eclipse.jdt.annotation.NonNull;
13 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
14 import org.opendaylight.mdsal.dom.api.DOMActionResult;
15 import org.opendaylight.mdsal.dom.api.DOMActionService;
16 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
17 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
18 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
19 import org.opendaylight.mdsal.dom.api.DOMRpcService;
20 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
21 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
22 import org.opendaylight.yangtools.yang.common.ErrorType;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.YangConstants;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
28 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
29 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Util class for rpc.
35  */
36 public final class RestconfInvokeOperationsUtil {
37     private static final Logger LOG = LoggerFactory.getLogger(RestconfInvokeOperationsUtil.class);
38
39     private RestconfInvokeOperationsUtil() {
40         // Hidden on purpose
41     }
42
43     /**
44      * Invoking rpc via mount point.
45      *
46      * @param mountPoint
47      *             mount point
48      * @param data
49      *             input data
50      * @param rpc
51      *             RPC type
52      * @return {@link DOMRpcResult}
53      */
54     public static DOMRpcResult invokeRpc(final NormalizedNode data, final QName rpc, final DOMMountPoint mountPoint) {
55         return invokeRpc(data, rpc, mountPoint.getService(DOMRpcService.class).orElseThrow(() -> {
56             final String errmsg = "RPC service is missing.";
57             LOG.debug(errmsg);
58             return new RestconfDocumentedException(errmsg);
59         }));
60     }
61
62     /**
63      * Invoke rpc.
64      *
65      * @param data
66      *             input data
67      * @param rpc
68      *             RPC type
69      * @param rpcService
70      *             rpc service to invoke rpc
71      * @return {@link DOMRpcResult}
72      */
73     public static DOMRpcResult invokeRpc(final NormalizedNode data, final QName rpc, final DOMRpcService rpcService) {
74         final ListenableFuture<? extends DOMRpcResult> future = rpcService.invokeRpc(rpc, nonnullInput(rpc, data));
75         final RpcResultFactory dataFactory = new RpcResultFactory();
76         FutureCallbackTx.addCallback(future, PostDataTransactionUtil.POST_TX_TYPE, dataFactory);
77         return dataFactory.build();
78     }
79
80     private static @NonNull NormalizedNode nonnullInput(final QName type, final NormalizedNode input) {
81         return input != null ? input
82                 : ImmutableNodes.containerNode(YangConstants.operationInputQName(type.getModule()));
83     }
84
85     /**
86      * Check the validity of the result.
87      *
88      * @param response
89      *             response of rpc
90      * @return {@link DOMRpcResult} result
91      */
92     public static DOMRpcResult checkResponse(final DOMRpcResult response) {
93         if (response == null) {
94             return null;
95         }
96         try {
97             if (response.getErrors().isEmpty()) {
98                 return response;
99             }
100             LOG.debug("RpcError message {}", response.getErrors());
101             throw new RestconfDocumentedException("RPCerror message ", null, response.getErrors());
102         } catch (final CancellationException e) {
103             final String errMsg = "The operation was cancelled while executing.";
104             LOG.debug("Cancel RpcExecution: {}", errMsg, e);
105             throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION, e);
106         }
107     }
108
109     /**
110      * Invoking Action via mount point.
111      *
112      * @param mountPoint
113      *             mount point
114      * @param data
115      *             input data
116      * @param schemaPath
117      *             schema path of data
118      * @return {@link DOMActionResult}
119      */
120     public static DOMActionResult invokeAction(final ContainerNode data,
121             final Absolute schemaPath, final YangInstanceIdentifier yangIId, final DOMMountPoint mountPoint) {
122         return invokeAction(data, schemaPath, yangIId, mountPoint.getService(DOMActionService.class)
123             .orElseThrow(() -> new RestconfDocumentedException("DomAction service is missing.")));
124     }
125
126     /**
127      * Invoke Action via ActionServiceHandler.
128      *
129      * @param data
130      *             input data
131      * @param schemaPath
132      *             schema path of data
133      * @param actionService
134      *             action service to invoke action
135      * @return {@link DOMActionResult}
136      */
137     public static DOMActionResult invokeAction(final ContainerNode data, final Absolute schemaPath,
138             final YangInstanceIdentifier yangIId, final DOMActionService actionService) {
139         final ListenableFuture<? extends DOMActionResult> future = actionService.invokeAction(schemaPath,
140             new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, yangIId.getParent()), data);
141         final ActionResultFactory dataFactory = new ActionResultFactory();
142         FutureCallbackTx.addCallback(future, PostDataTransactionUtil.POST_TX_TYPE, dataFactory);
143         return dataFactory.build();
144     }
145
146     /**
147      * Check the validity of the result.
148      *
149      * @param response
150      *             response of Action
151      * @return {@link DOMActionResult} result
152      */
153     public static DOMActionResult checkActionResponse(final DOMActionResult response) {
154         if (response != null) {
155             try {
156                 if (response.getErrors().isEmpty()) {
157                     return response;
158                 }
159                 LOG.debug("InvokeAction Error Message {}", response.getErrors());
160                 throw new RestconfDocumentedException("InvokeAction Error Message ", null, response.getErrors());
161             } catch (final CancellationException e) {
162                 final String errMsg = "The Action Operation was cancelled while executing.";
163                 LOG.debug("Cancel Execution: {}", errMsg, e);
164                 throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION, e);
165             }
166         }
167         return null;
168     }
169 }