Include impacted changes for APPC-346,APPC-348
[appc.git] / appc-dispatcher / appc-request-handler / appc-request-handler-core / src / main / java / org / onap / appc / requesthandler / impl / LocalRequestHandlerImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.appc.requesthandler.impl;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import org.json.JSONObject;
30 import org.onap.appc.domainmodel.lcm.ActionIdentifiers;
31 import org.onap.appc.domainmodel.lcm.RequestStatus;
32 import org.onap.appc.domainmodel.lcm.ResponseContext;
33 import org.onap.appc.domainmodel.lcm.RuntimeContext;
34 import org.onap.appc.domainmodel.lcm.Status;
35 import org.onap.appc.domainmodel.lcm.VNFOperation;
36 import org.onap.appc.exceptions.APPCException;
37 import org.onap.appc.executor.objects.LCMCommandStatus;
38 import org.onap.appc.executor.objects.Params;
39 import org.onap.appc.requesthandler.exceptions.MultipleRecordsRetrievedException;
40 import org.onap.appc.util.JsonUtil;
41
42 import java.io.IOException;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46
47 /**
48  * This class handles the LCM-Requests that don't need communication with the VNF.
49  * The ideal flow is to validate the request, query locally and return data.
50  */
51 public class LocalRequestHandlerImpl extends AbstractRequestHandlerImpl {
52     private final EELFLogger logger = EELFManager.getInstance().getLogger(LocalRequestHandlerImpl.class);
53
54     @Override
55     protected void handleRequest(RuntimeContext runtimeContext) {
56         final VNFOperation action = runtimeContext.getRequestContext().getAction();
57
58         switch (action) {
59             case ActionStatus:
60                 processActionStatus(runtimeContext);
61                 break;
62             default:
63                 logger.error(String.format("Action: %s isn't mapped to a Local Request.", action));
64
65         }
66     }
67
68     /**
69      * Process request of ActionStatus.
70      * The <code>status</code> in the <code>ResponseContext</code> will be set according to
71      * the response from <code>getStatusOfRequest(String,String,String,String</code>
72      * <p>
73      * The MULTIPLE_REQUESTS_FOUND exception is caught when <code>getStatusOfRequest(String,String,String,String</code>
74      * throws MultipleRecordsRetrievedException. Otherwise, all the responses returned from here will be SUCCESS.
75      *
76      * @param runtimeContext an RuntimeContext Object
77      */
78     private void processActionStatus(RuntimeContext runtimeContext) {
79         // Get the input payload and Action Identifier to know the request to query
80         Map<String, String> payloadAttributeMap = getPayloadAttribute(runtimeContext.getRequestContext().getPayload());
81         String requestId = payloadAttributeMap.get("request-id");
82         String vnfId = getVnfId(runtimeContext.getRequestContext().getActionIdentifiers());
83         String originatorId = payloadAttributeMap.get("originator-id");
84         String subRequestId = payloadAttributeMap.get("sub-request-id");
85
86         ResponseContext context = runtimeContext.getResponseContext();
87         RequestStatus requestStatus;
88         String jsonPayload = null;
89         Status status;
90
91         // Use Transaction Recorder to query DB for this Request's status
92         try {
93             requestStatus = getStatusOfRequest(requestId, subRequestId, originatorId, vnfId);
94             jsonPayload = createPayload(requestStatus.getExternalActionStatusName(), requestStatus.name());
95             status = buildStatus(LCMCommandStatus.SUCCESS, null, null);
96         } catch (MultipleRecordsRetrievedException ex) {
97             status = buildStatus(LCMCommandStatus.MULTIPLE_REQUESTS_FOUND, "parameters",
98                 getSearchCriteria(requestId, subRequestId, originatorId, vnfId));
99             logger.debug("RequestStatus is set to MULTIPLE_REQUESTS_FOUND due to MultipleRecordsRetrievedException",
100                 ex.getMessage());
101         } catch (APPCException ex) {
102             jsonPayload = createPayload(RequestStatus.UNKNOWN.getExternalActionStatusName(),
103                 RequestStatus.UNKNOWN.name());
104             status = buildStatus(LCMCommandStatus.SUCCESS, null, null);
105             logger.debug("RequestStatus is set to UNKNOWN due to APPCException:", ex.getMessage());
106         }
107
108         // Create ResponseContext with payload containing ActionStatus with status and status-reason
109         context.setStatus(status);
110         if (jsonPayload != null) {
111             context.setPayload(jsonPayload);
112         }
113     }
114
115     private String getSearchCriteria(String requestId, String subrequestId, String originatorid, String vnfId) {
116         StringBuilder suffix = new StringBuilder();
117         suffix.append(String.format("request-id=%s", requestId));
118         suffix.append(String.format(" AND vnf-id=%s", vnfId));
119         if (subrequestId != null) {
120             suffix.append(String.format(" AND sub-request-id=%s", subrequestId));
121         }
122         if (originatorid != null) {
123             suffix.append(String.format(" AND originator-id=%s", originatorid));
124         }
125
126         return suffix.toString();
127     }
128
129     private Map<String, String> getPayloadAttribute(String payload) {
130         Map<String, String> map;
131         try {
132             map = JsonUtil.convertJsonStringToFlatMap(payload);
133         } catch (IOException e) {
134             logger.error(String.format("Error encountered when converting JSON payload '%s' to map", payload), e);
135             throw new IllegalArgumentException("Search criteria cannot be determined from Payload");
136         }
137
138         if (map == null || !map.containsKey("request-id")) {
139             throw new IllegalArgumentException("request-id is absent in the Payload");
140         }
141
142         return map;
143     }
144
145     private String getVnfId(ActionIdentifiers identifiers) {
146         if (identifiers == null || identifiers.getVnfId() == null) {
147             throw new IllegalArgumentException("vnf-id is absent in Action Identifiers");
148         }
149         return identifiers.getVnfId();
150     }
151
152     /**
153      * Build a Status.
154      *
155      * @param lcmCommandStatus for the Status code and message format
156      * @param key              String for the LCMcommandStatus format
157      * @param message          String for the Status message vaiable
158      * @return the newly build Status
159      */
160     private Status buildStatus(LCMCommandStatus lcmCommandStatus, String key, String message) {
161         Status status = new Status();
162         status.setCode(lcmCommandStatus.getResponseCode());
163
164         if (key != null) {
165             Params params = new Params().addParam(key, message);
166             status.setMessage(lcmCommandStatus.getFormattedMessage(params));
167         } else {
168             status.setMessage(lcmCommandStatus.getResponseMessage());
169         }
170
171         return status;
172     }
173
174     private String createPayload(String status, String statusReason) {
175         Map<String, String> payload = new HashMap<>();
176         payload.put("status", status);
177         payload.put("status-reason", statusReason);
178         return (new JSONObject(payload)).toString();
179     }
180
181     private RequestStatus getStatusOfRequest(String requestId, String subRequestId, String originatorId, String vnfId)
182         throws MultipleRecordsRetrievedException, APPCException {
183         RequestStatus requestStatus = RequestStatus.UNKNOWN;
184
185         List<RequestStatus> records = transactionRecorder.getRecords(requestId, subRequestId, originatorId, vnfId);
186         if (records != null) {
187             final int size = records.size();
188             if (size > 1) {
189                 throw new MultipleRecordsRetrievedException(
190                     String.format("MULTIPLE REQUESTS FOUND USING SEARCH CRITERIA: %s", getSearchCriteria(requestId,
191                         subRequestId, originatorId, vnfId)));
192             }
193
194             if (size == 0) {
195                 requestStatus = RequestStatus.NOT_FOUND;
196             } else {
197                 requestStatus = records.get(0);
198             }
199         }
200
201         return requestStatus;
202     }
203
204     @Override
205     public void onRequestExecutionStart(String vnf_id, boolean readOnlyActivity, boolean forceFlag) {
206         //Do nothing
207     }
208 }