Update MRI projects for Aluminium
[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.ArrayList;
12 import java.util.List;
13 import java.util.Optional;
14 import java.util.concurrent.CancellationException;
15 import javax.ws.rs.core.Response.Status;
16 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
17 import org.opendaylight.mdsal.dom.api.DOMActionResult;
18 import org.opendaylight.mdsal.dom.api.DOMActionService;
19 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
20 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
21 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
22 import org.opendaylight.mdsal.dom.api.DOMRpcService;
23 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
24 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
25 import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
26 import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
27 import org.opendaylight.restconf.nb.rfc8040.handlers.RpcServiceHandler;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
30 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
32 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Util class for rpc.
38  */
39 public final class RestconfInvokeOperationsUtil {
40     private static final Logger LOG = LoggerFactory.getLogger(RestconfInvokeOperationsUtil.class);
41
42     private RestconfInvokeOperationsUtil() {
43         throw new UnsupportedOperationException("Util class");
44     }
45
46     /**
47      * Invoking rpc via mount point.
48      *
49      * @param mountPoint
50      *             mount point
51      * @param data
52      *             input data
53      * @param schemaPath
54      *             schema path of data
55      * @return {@link DOMRpcResult}
56      */
57     public static DOMRpcResult invokeRpcViaMountPoint(final DOMMountPoint mountPoint, final NormalizedNode<?, ?> data,
58             final SchemaPath schemaPath) {
59         final Optional<DOMRpcService> mountPointService = mountPoint.getService(DOMRpcService.class);
60         if (mountPointService.isPresent()) {
61             return prepareResult(mountPointService.get().invokeRpc(schemaPath, data));
62         }
63         final String errmsg = "RPC service is missing.";
64         LOG.debug(errmsg);
65         throw new RestconfDocumentedException(errmsg);
66     }
67
68     /**
69      * Invoke rpc.
70      *
71      * @param data
72      *             input data
73      * @param schemaPath
74      *             schema path of data
75      * @param rpcServiceHandler
76      *             rpc service handler to invoke rpc
77      * @return {@link DOMRpcResult}
78      */
79     public static DOMRpcResult invokeRpc(final NormalizedNode<?, ?> data, final SchemaPath schemaPath,
80             final RpcServiceHandler rpcServiceHandler) {
81         final DOMRpcService rpcService = rpcServiceHandler.get();
82         if (rpcService == null) {
83             throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE);
84         }
85
86         return prepareResult(rpcService.invokeRpc(schemaPath, data));
87     }
88
89     /**
90      * Check the validity of the result.
91      *
92      * @param response
93      *             response of rpc
94      * @return {@link DOMRpcResult} result
95      */
96     public static DOMRpcResult checkResponse(final DOMRpcResult response) {
97         if (response == null) {
98             return null;
99         }
100         try {
101             if (response.getErrors().isEmpty()) {
102                 return response;
103             }
104             LOG.debug("RpcError message {}", response.getErrors());
105             throw new RestconfDocumentedException("RPCerror message ", null, response.getErrors());
106         } catch (final CancellationException e) {
107             final String errMsg = "The operation was cancelled while executing.";
108             LOG.debug("Cancel RpcExecution: {}", errMsg, e);
109             throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION, e);
110         }
111     }
112
113     private static DOMRpcResult prepareResult(final ListenableFuture<? extends DOMRpcResult> rpc) {
114         final RpcResultFactory dataFactory = new RpcResultFactory();
115         FutureCallbackTx.addCallback(rpc, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
116         return dataFactory.build();
117     }
118
119     /**
120      * Invoking Action via mount point.
121      *
122      * @param mountPoint
123      *             mount point
124      * @param data
125      *             input data
126      * @param schemaPath
127      *             schema path of data
128      * @return {@link DOMActionResult}
129      */
130     public static DOMActionResult invokeActionViaMountPoint(final DOMMountPoint mountPoint, final ContainerNode data,
131             final SchemaPath schemaPath, final YangInstanceIdentifier yangIId) {
132         final Optional<DOMActionService> mountPointService = mountPoint.getService(DOMActionService.class);
133         if (!mountPointService.isPresent()) {
134             throw new RestconfDocumentedException("DomAction service is missing.");
135         }
136
137         return prepareActionResult(mountPointService.get().invokeAction(schemaPath,
138             prepareDataTreeId(yangIId, schemaPath), data));
139     }
140
141     /**
142      * Invoke Action via ActionServiceHandler.
143      *
144      * @param data
145      *             input data
146      * @param schemaPath
147      *             schema path of data
148      * @param actionServiceHandler
149      *             action service handler to invoke action
150      * @return {@link DOMActionResult}
151      */
152     public static DOMActionResult invokeAction(final ContainerNode data, final SchemaPath schemaPath,
153             final ActionServiceHandler actionServiceHandler, final YangInstanceIdentifier yangIId) {
154         return prepareActionResult(actionServiceHandler.get().invokeAction(schemaPath,
155             prepareDataTreeId(yangIId, schemaPath), data));
156     }
157
158     /**
159      * Check the validity of the result.
160      *
161      * @param response
162      *             response of Action
163      * @return {@link DOMActionResult} result
164      */
165     public static DOMActionResult checkActionResponse(final DOMActionResult response) {
166         if (response != null) {
167             try {
168                 if (response.getErrors().isEmpty()) {
169                     return response;
170                 }
171                 LOG.debug("InvokeAction Error Message {}", response.getErrors());
172                 throw new RestconfDocumentedException("InvokeAction Error Message ", null, response.getErrors());
173             } catch (final CancellationException e) {
174                 final String errMsg = "The Action Operation was cancelled while executing.";
175                 LOG.debug("Cancel Execution: {}", errMsg, e);
176                 throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION, e);
177             }
178         }
179         return null;
180     }
181
182     /**
183      * Prepare Action Result.
184      *
185      * @param actionResult
186      *            {@link DOMActionResult} - action result
187      * @return {@link DOMActionResult} result
188      */
189     private static DOMActionResult prepareActionResult(final ListenableFuture<? extends DOMActionResult> actionResult) {
190         final ActionResultFactory dataFactory = new ActionResultFactory();
191         FutureCallbackTx.addCallback(actionResult, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
192         return dataFactory.build();
193     }
194
195     /**
196      * Prepare DOMDataTree Identifier.
197      *
198      * @param yangIId
199      *             {@link YangInstanceIdentifier}
200      * @param schemaPath
201      *              {@link SchemaPath}
202      * @return {@link DOMDataTreeIdentifier} domDataTreeIdentifier
203      */
204     private static DOMDataTreeIdentifier prepareDataTreeId(final YangInstanceIdentifier yangIId,
205             final SchemaPath schemaPath) {
206         final List<PathArgument> pathArg = new ArrayList<>();
207         for (PathArgument path : yangIId.getPathArguments()) {
208             if (path.getNodeType().getLocalName().equals(schemaPath.getLastComponent().getLocalName())) {
209                 break;
210             }
211             pathArg.add(path);
212         }
213         YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().append(pathArg).build();
214         DOMDataTreeIdentifier domDataTreeIdentifier = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL,
215             yangInstanceIdentifier);
216         return domDataTreeIdentifier;
217     }
218 }