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