0c58a6fbfa1dcb12097c990d74c0eb5881e78c92
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Modifications Copyright (c) 2020 Nordix
10  * ================================================================================
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  * ============LICENSE_END=========================================================
23  */
24 package org.onap.so.apihandlerinfra;
25
26 import com.fasterxml.jackson.core.JsonProcessingException;
27 import com.fasterxml.jackson.databind.ObjectMapper;
28 import io.swagger.v3.oas.annotations.OpenAPIDefinition;
29 import io.swagger.v3.oas.annotations.Operation;
30 import io.swagger.v3.oas.annotations.info.Info;
31 import io.swagger.v3.oas.annotations.media.ArraySchema;
32 import io.swagger.v3.oas.annotations.media.Content;
33 import io.swagger.v3.oas.annotations.media.Schema;
34 import io.swagger.v3.oas.annotations.responses.ApiResponse;
35 import org.apache.http.HttpStatus;
36 import org.onap.so.apihandler.common.ErrorNumbers;
37 import org.onap.so.apihandler.common.ResponseBuilder;
38 import org.onap.so.apihandlerinfra.exceptions.ValidateException;
39 import org.onap.so.apihandlerinfra.logging.ErrorLoggerInfo;
40 import org.onap.so.apihandlerinfra.workflowspecificationbeans.*;
41 import org.onap.so.db.catalog.beans.*;
42 import org.onap.so.db.catalog.client.CatalogDbClient;
43 import org.onap.logging.filter.base.ErrorCode;
44 import org.onap.so.logger.MessageEnum;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.stereotype.Component;
49 import javax.transaction.Transactional;
50 import javax.ws.rs.GET;
51 import javax.ws.rs.Path;
52 import javax.ws.rs.PathParam;
53 import javax.ws.rs.QueryParam;
54 import javax.ws.rs.core.Response;
55 import java.util.*;
56 import java.util.stream.Collectors;
57
58
59 @Path("onap/so/infra/workflowSpecifications")
60 @OpenAPIDefinition(info = @Info(title = "onap/so/infra/workflowSpecifications",
61         description = "Queries of Workflow Specifications"))
62 @Component
63 public class WorkflowSpecificationsHandler {
64
65     private static final ObjectMapper mapper = new ObjectMapper();
66
67     @Autowired
68     private ResponseBuilder builder;
69
70     @Autowired
71     private CatalogDbClient catalogDbClient;
72
73     private static Logger logger = LoggerFactory.getLogger(WorkflowSpecificationsHandler.class);
74     private static final String ARTIFACT_TYPE_WORKFLOW = "workflow";
75     private static final String NATIVE_WORKFLOW = "native";
76     private static final String EMPTY_BODY = "";
77
78     @Path("/{version:[vV]1}/workflows")
79     @GET
80     @Operation(description = "Finds Workflow Specifications", responses = @ApiResponse(
81             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
82     @Transactional
83
84     public Response queryWorkflowSpecifications(@QueryParam("vnfModelVersionId") String vnfModelVersionId,
85             @QueryParam("pnfModelVersionId") String pnfModelVersionId,
86             @QueryParam("resourceTarget") String resourceTarget, @PathParam("version") String version)
87             throws Exception {
88         String apiVersion = version.substring(1);
89
90         List<Workflow> workflows = new ArrayList<>();
91         if (vnfModelVersionId == null && pnfModelVersionId == null && resourceTarget == null) {
92             workflows.addAll(queryWorkflowSpecificationsForAll());
93         } else {
94             // 1. query workflow specifications for given vnfModelVersionId if need.
95             if (vnfModelVersionId != null) {
96                 List<Workflow> vnfWorkflows = queryWorkflowSpecificationsForVnf(vnfModelVersionId);
97                 logger.debug("Retrieved " + vnfWorkflows.size() + " workflows for given vnfModelVersionId.");
98                 if (vnfWorkflows.size() > 0) {
99                     workflows.addAll(vnfWorkflows);
100                 }
101             }
102
103             // 2. query workflow specifications for given pnfModelVersionId if need.
104             if (pnfModelVersionId != null) {
105                 List<Workflow> pnfWorkflows = queryWorkflowSpecificationsForPnf(pnfModelVersionId);
106                 logger.debug("Retrieved " + pnfWorkflows.size() + " workflows for given pnfModelVerionId.");
107                 if (pnfWorkflows.size() > 0) {
108                     workflows.addAll(pnfWorkflows);
109                 }
110             }
111
112             // 3. query workflow specifications for given resourceTarget
113             if (resourceTarget != null) {
114                 List<Workflow> workflowsForResourceTarget = queryWorkflowsForResourceTarget(resourceTarget);
115                 logger.debug(
116                         "Retrieved " + workflowsForResourceTarget.size() + " workflows for given resource target.");
117                 if (workflowsForResourceTarget.size() > 0) {
118                     workflows.addAll(workflowsForResourceTarget);
119                 }
120             }
121         }
122
123         // Deduplication
124         List<Workflow> retWorkflows = workflows.stream()
125                 .collect(Collectors.collectingAndThen(
126                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Workflow::getArtifactUUID))),
127                         ArrayList::new));
128
129         Optional<String> optional = getResponseByWorkflowSpec(retWorkflows);
130         return builder.buildResponse(HttpStatus.SC_OK, "", optional.isPresent() ? optional.get() : EMPTY_BODY,
131                 apiVersion);
132     }
133
134     /**
135      * @deprecated As of G release, workflows for all resource types (pnf,vnf,service) can be fetched using
136      *             /workflowSpecifications/{version:[vV]1}/workflows?resourceTarget={resourceType} API
137      */
138     @Path("/{version:[vV]1}/pnfWorkflows")
139     @GET
140     @Operation(description = "Finds pnf workflow specifications", responses = @ApiResponse(
141             content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
142     @Transactional
143     @Deprecated
144     public Response getWorkflowsSpecForPnf(@PathParam("version") String version) throws Exception {
145
146         final String pnf_resource = "pnf";
147         String apiVersion = version.substring(1);
148
149         List<Workflow> workflows = queryWorkflowsForResourceTarget(pnf_resource);
150
151         Optional<String> optional = getResponseByWorkflowSpec(workflows);
152         return builder.buildResponse(HttpStatus.SC_OK, "", optional.isPresent() ? optional.get() : EMPTY_BODY,
153                 apiVersion);
154     }
155
156     protected WorkflowSpecifications mapWorkflowsToWorkflowSpecifications(List<Workflow> workflows) {
157         if (workflows == null || workflows.isEmpty()) {
158             return null;
159         }
160         WorkflowSpecifications workflowSpecifications = new WorkflowSpecifications();
161         List<WorkflowSpecificationList> workflowSpecificationList = new ArrayList<>();
162
163         for (Workflow workflow : workflows) {
164             WorkflowSpecificationList workflowSpecificationListItem = new WorkflowSpecificationList();
165             WorkflowSpecification workflowSpecification = new WorkflowSpecification();
166             workflowSpecification.setArtifactInfo(buildArtifactInfo(workflow));
167             workflowSpecification.setActivitySequence(buildActivitySequence(workflow));
168             workflowSpecification.setWorkflowInputParameters(buildWorkflowInputParameters(workflow));
169             workflowSpecificationListItem.setWorkflowSpecification(workflowSpecification);
170             workflowSpecificationList.add(workflowSpecificationListItem);
171         }
172         workflowSpecifications.setWorkflowSpecificationList(workflowSpecificationList);
173         return workflowSpecifications;
174     }
175
176     private Optional<String> getResponseByWorkflowSpec(List<Workflow> workflows) throws ValidateException {
177         WorkflowSpecifications workflowSpecifications = mapWorkflowsToWorkflowSpecifications(workflows);
178
179         try {
180             return Optional.of(mapper.writeValueAsString(workflowSpecifications));
181         } catch (JsonProcessingException e) {
182             catchAndThrowValidationEx(e);
183         }
184         return Optional.empty();
185     }
186
187     private Response catchAndThrowValidationEx(JsonProcessingException e) throws ValidateException {
188         ErrorLoggerInfo errorLoggerInfo =
189                 new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError).build();
190         ValidateException validateException =
191                 new ValidateException.Builder("Mapping of request to JSON object failed : " + e.getMessage(),
192                         HttpStatus.SC_BAD_REQUEST, ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo)
193                                 .build();
194         throw validateException;
195     }
196
197     private ArtifactInfo buildArtifactInfo(Workflow workflow) {
198         ArtifactInfo artifactInfo = new ArtifactInfo();
199         artifactInfo.setArtifactType(ARTIFACT_TYPE_WORKFLOW);
200         artifactInfo.setArtifactUuid(workflow.getArtifactUUID());
201         artifactInfo.setArtifactName(workflow.getArtifactName());
202         if (workflow.getVersion() != null) {
203             artifactInfo.setArtifactVersion(workflow.getVersion().toString());
204         }
205         artifactInfo.setArtifactDescription(workflow.getDescription());
206         artifactInfo.setWorkflowName(workflow.getName());
207         artifactInfo.setOperationName(workflow.getOperationName());
208         artifactInfo.setWorkflowSource(workflow.getSource());
209         artifactInfo.setWorkflowResourceTarget(workflow.getResourceTarget());
210         return artifactInfo;
211     }
212
213     private List<ActivitySequence> buildActivitySequence(Workflow workflow) {
214         List<WorkflowActivitySpecSequence> workflowActivitySpecSequences = workflow.getWorkflowActivitySpecSequence();
215         if (workflowActivitySpecSequences == null || workflowActivitySpecSequences.isEmpty()) {
216             return null;
217         }
218         List<ActivitySequence> activitySequences = new ArrayList<>();
219         for (WorkflowActivitySpecSequence workflowActivitySpecSequence : workflowActivitySpecSequences) {
220             if (workflowActivitySpecSequence != null) {
221                 ActivitySpec activitySpec = workflowActivitySpecSequence.getActivitySpec();
222                 if (activitySpec != null) {
223                     ActivitySequence activitySequence = new ActivitySequence();
224                     activitySequence.setName(activitySpec.getName());
225                     logger.debug("Adding activity: " + activitySpec.getName());
226                     activitySequence.setDescription(activitySpec.getDescription());
227                     activitySequences.add(activitySequence);
228                 }
229             }
230         }
231         return activitySequences;
232     }
233
234     private List<WorkflowInputParameter> buildWorkflowInputParameters(Workflow workflow) {
235         List<WorkflowActivitySpecSequence> workflowActivitySpecSequences = workflow.getWorkflowActivitySpecSequence();
236         if (workflowActivitySpecSequences == null || workflowActivitySpecSequences.isEmpty()) {
237             return new ArrayList<>();
238         }
239         Map<String, WorkflowInputParameter> workflowInputParameterMap = new HashMap<>();
240         for (WorkflowActivitySpecSequence workflowActivitySpecSequence : workflowActivitySpecSequences) {
241             if (workflowActivitySpecSequence != null) {
242                 ActivitySpec activitySpec = workflowActivitySpecSequence.getActivitySpec();
243                 if (activitySpec != null) {
244                     List<ActivitySpecUserParameters> activitySpecUserParameters =
245                             activitySpec.getActivitySpecUserParameters();
246                     if (activitySpecUserParameters != null && !activitySpecUserParameters.isEmpty()) {
247                         for (ActivitySpecUserParameters activitySpecUserParameter : activitySpecUserParameters) {
248                             UserParameters userParameter = activitySpecUserParameter.getUserParameters();
249                             if (userParameter != null) {
250                                 WorkflowInputParameter workflowInputParameter =
251                                         buildWorkflowInputParameter(userParameter);
252                                 workflowInputParameterMap.put(userParameter.getName(), workflowInputParameter);
253                             }
254                         }
255                     }
256                 }
257             }
258         }
259
260         if (workflowInputParameterMap.size() == 0) {
261             return new ArrayList<>();
262         }
263         List<WorkflowInputParameter> workflowInputParameterList =
264                 workflowInputParameterMap.values().stream().collect(Collectors.toList());
265         return workflowInputParameterList;
266     }
267
268     private WorkflowInputParameter buildWorkflowInputParameter(UserParameters userParameter) {
269         WorkflowInputParameter workflowInputParameter = new WorkflowInputParameter();
270         workflowInputParameter.setLabel(userParameter.getLabel());
271         workflowInputParameter.setInputType(userParameter.getType());
272         workflowInputParameter.setRequired(userParameter.getIsRequried());
273         workflowInputParameter.setSoFieldName(userParameter.getName());
274         workflowInputParameter.setSoPayloadLocation(userParameter.getPayloadLocation());
275         workflowInputParameter.setValidation(buildValidationList(userParameter));
276         return workflowInputParameter;
277     }
278
279     private List<Validation> buildValidationList(UserParameters userParameter) {
280         List<Validation> validationList = null;
281         if (userParameter.getMaxLength() != null || userParameter.getAllowableChars() != null) {
282             validationList = new ArrayList<>();
283             Validation validation = new Validation();
284             if (userParameter.getMaxLength() != null) {
285                 validation.setMaxLength(userParameter.getMaxLength().toString());
286             }
287             validation.setAllowableChars(userParameter.getAllowableChars());
288             validationList.add(validation);
289         }
290         return validationList;
291     }
292
293     private List<Workflow> queryWorkflowSpecificationsForAll() {
294         List<Workflow> workflows = catalogDbClient.findWorkflowBySource(NATIVE_WORKFLOW);
295         return workflows;
296     }
297
298     private List<Workflow> queryWorkflowSpecificationsForVnf(String vnfModelVersionId) {
299         List<Workflow> workflows = catalogDbClient.findWorkflowByVnfModelUUID(vnfModelVersionId);
300
301         List<Workflow> nativeWorkflows = catalogDbClient.findWorkflowBySource(NATIVE_WORKFLOW);
302         if (!nativeWorkflows.isEmpty()) {
303             workflows.addAll(nativeWorkflows);
304         }
305         return workflows;
306     }
307
308     private List<Workflow> queryWorkflowSpecificationsForPnf(String pnfModelVersionId) {
309         List<Workflow> workflows = catalogDbClient.findWorkflowByPnfModelUUID(pnfModelVersionId);
310         return workflows;
311     }
312
313     private List<Workflow> queryWorkflowsForResourceTarget(String resourceTarget) {
314         List<Workflow> workflows = catalogDbClient.findWorkflowByResourceTarget(resourceTarget);
315         return workflows;
316     }
317
318
319 }