Sync Integ to Master
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / externalapi / servlet / CrudExternalServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.externalapi.servlet;
22
23 import com.jcabi.aspects.Loggable;
24 import fj.data.Either;
25 import io.swagger.annotations.*;
26 import org.apache.commons.lang3.StringUtils;
27 import com.fasterxml.jackson.databind.ObjectMapper;
28 import org.elasticsearch.common.Strings;
29 import org.json.simple.JSONObject;
30 import org.json.simple.parser.JSONParser;
31 import org.openecomp.sdc.be.components.impl.ElementBusinessLogic;
32 import org.openecomp.sdc.be.components.impl.ImportUtils;
33 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
34 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
35 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoBase;
36 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
37 import org.openecomp.sdc.be.config.BeEcompErrorManager;
38 import org.openecomp.sdc.be.dao.api.ActionStatus;
39 import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum;
40 import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum;
41 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
42 import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum;
43 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
44 import org.openecomp.sdc.be.ecomp.converters.AssetMetadataConverter;
45 import org.openecomp.sdc.be.externalapi.servlet.representation.AssetMetadata;
46 import org.openecomp.sdc.be.model.*;
47 import org.openecomp.sdc.be.model.category.CategoryDefinition;
48 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
49 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
50 import org.openecomp.sdc.be.servlets.AbstractValidationsServlet;
51 import org.openecomp.sdc.be.servlets.RepresentationUtils;
52 import org.openecomp.sdc.be.utils.CommonBeUtils;
53 import org.openecomp.sdc.common.api.Constants;
54 import org.openecomp.sdc.common.config.EcompErrorName;
55 import org.openecomp.sdc.common.datastructure.AuditingFieldsKeysEnum;
56 import org.openecomp.sdc.common.datastructure.Wrapper;
57 import org.openecomp.sdc.common.util.ValidationUtils;
58 import org.openecomp.sdc.exception.ResponseFormat;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 import javax.inject.Singleton;
63 import javax.servlet.ServletContext;
64 import javax.servlet.http.HttpServletRequest;
65 import javax.ws.rs.*;
66 import javax.ws.rs.core.Context;
67 import javax.ws.rs.core.MediaType;
68 import javax.ws.rs.core.Response;
69 import java.io.IOException;
70 import java.util.Arrays;
71 import java.util.EnumMap;
72 import java.util.List;
73 import java.util.Optional;
74 import java.util.stream.Collectors;
75
76 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
77 @Path("/v1/catalog")
78 @Api(value = "CRUD External Servlet", description = "This Servlet serves external users for creating assets and changing their lifecycle state")
79 @Singleton
80 public class CrudExternalServlet extends AbstractValidationsServlet {
81
82     @Context
83     private HttpServletRequest request;
84
85     private static final Logger log = LoggerFactory.getLogger(CrudExternalServlet.class);
86
87     /**
88      * Creates a new Resource
89      *
90      * @param assetType
91      * @param data
92      * @param userId
93      * @param instanceIdHeader
94      * @return
95      */
96     @POST
97     @Path("/{assetType}")
98     @Consumes(MediaType.APPLICATION_JSON)
99     @Produces(MediaType.APPLICATION_JSON)
100     @ApiOperation(value = "creates a resource", httpMethod = "POST", notes = "Creates a resource")
101     @ApiResponses(value = {
102             @ApiResponse(code = 200, message = "ECOMP component is authenticated and Asset created", response = Resource.class),
103             @ApiResponse(code = 400, message = "Missing  X-ECOMP-InstanceID  HTTP header - POL5001"),
104             @ApiResponse(code = 401, message = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic Authentication credentials - POL5002"),
105             @ApiResponse(code = 403, message = "ECOMP component is not authorized - POL5003"),
106             @ApiResponse(code = 404, message = "Error: Requested '%1' (uuid) resource was not found - SVC4063"),
107             @ApiResponse(code = 405, message = "Method  Not Allowed  :  Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"),
108             @ApiResponse(code = 500, message = "The GET request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000"),
109             @ApiResponse(code = 400, message = "The name provided for the newly created resource is already in use for another resource in SDC - SVC4050"),
110             @ApiResponse(code = 400, message = "Invalid field format. One of the provided fields does not comply with the field rules - SVC4126"),
111             @ApiResponse(code = 400, message = "Missing request body. The post request did not contain the expected body - SVC4500"),
112             @ApiResponse(code = 400, message = "The resource name is missing in the request body - SVC4062"),
113             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT description has wrong format - SVC4064"),
114             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT description has wrong format (exceeds limit) - SVC4065"),
115             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT tags exceeds character limit - SVC4066"),
116             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT vendor name exceeds character limit - SVC4067"),
117             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT vendor release exceeds character limit - SVC4068"),
118             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT ATT Contact has wrong format - SVC4069"),
119             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT name has wrong format - SVC4070"),
120             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT vendor name has wrong format - SVC4071"),
121             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT vendor release has wrong format - SVC4072"),
122             @ApiResponse(code = 400, message = "Create VFCMT request: VFCMT name exceeds character limit - SVC4073")})
123     @ApiImplicitParams({@ApiImplicitParam(required = true, dataType = "org.openecomp.sdc.be.model.Resource", paramType = "body", value = "json describe the created resource")})
124     public Response createResourceExternal(
125             @ApiParam(value = "Determines the format of the body of the request", required = true)@HeaderParam(value = Constants.CONTENT_TYPE_HEADER) String contenType,
126             @ApiParam(value = "The user id", required = true)@HeaderParam(value = Constants.USER_ID_HEADER) final String userId,
127             @ApiParam(value = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
128             @ApiParam(value = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
129             @ApiParam(value = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
130             @ApiParam(value = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
131             @ApiParam(value = "The requested asset type", required = true, allowableValues = "resources, services")@PathParam("assetType") final String assetType,
132             String data) {
133
134         init(log);
135
136         Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
137         String requestURI = request.getRequestURI();
138         String url = request.getMethod() + " " + requestURI;
139         log.debug("Start handle request of {}", url);
140         Resource resource = null;
141         User modifier = null;
142         EnumMap<AuditingFieldsKeysEnum, Object> additionalParams = new EnumMap<>(AuditingFieldsKeysEnum.class);
143         ServletContext context = request.getSession().getServletContext();
144         ResourceBusinessLogic resourceBL = getResourceBL(context);
145         try {
146             // Validate X-ECOMP-InstanceID Header
147             if (responseWrapper.isEmpty()) {
148                 validateXECOMPInstanceIDHeader(instanceIdHeader, responseWrapper);
149             }
150             // Validate USER_ID Header
151             if (responseWrapper.isEmpty()) {
152                 validateHttpCspUserIdHeader(userId, responseWrapper);
153             }
154             // Validate assetType
155             if (responseWrapper.isEmpty()) {
156                 if( !AssetTypeEnum.RESOURCES.getValue().equals(assetType) ){
157                     responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
158                 }
159             }
160             //Validate resource type
161             if(responseWrapper.isEmpty()){
162                 JSONParser parser = new JSONParser();
163                 JSONObject jsonObj = (JSONObject) parser.parse(data);
164                 String resourceType = (String) jsonObj.get(FilterKeyEnum.RESOURCE_TYPE.getName());
165                 if( StringUtils.isEmpty(resourceType) || !ResourceTypeEnum.containsName(resourceType) ){
166                     additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, (String) jsonObj.get("name"));
167                     responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
168                 }
169             }
170             // Convert the user json to a resource
171             if (responseWrapper.isEmpty()) {
172                 modifier = new User();
173                 modifier.setUserId(userId);
174                 Either<Resource, ResponseFormat> eitherResource = getComponentsUtils()
175                         .convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class,
176                                 null, ComponentTypeEnum.RESOURCE);
177                 if( eitherResource.isRight() ){
178                     responseWrapper.setInnerElement(eitherResource.right().value());
179                 }
180                 else{
181                     resource = eitherResource.left().value();
182                 }
183
184             }
185             //validate name exist
186             if(responseWrapper.isEmpty()){
187                 if( Strings.isEmpty(resource.getName())){
188                     responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
189                             ActionStatus.MISSING_COMPONENT_NAME, ComponentTypeEnum.RESOURCE.getValue()));
190
191                 }
192             }
193
194             if(responseWrapper.isEmpty()){
195                 resource.setDerivedFrom(Arrays.asList("tosca.nodes.Root"));
196                 resource.setSystemName(ValidationUtils.convertToSystemName(resource.getName()));
197                 resource.setToscaResourceName(CommonBeUtils.generateToscaResourceName(ResourceTypeEnum.VFCMT.name(),
198                         resource.getSystemName()));
199                 handleCategories(context, data, resource, responseWrapper);
200             }
201             // Create the resource in the dataModel
202             if (responseWrapper.isEmpty()) {
203                 Either<Resource, ResponseFormat> eitherCreateResponse = resourceBL.createResource(resource, null,
204                         modifier, null, null);
205                 if (eitherCreateResponse.isRight()) {
206                     responseWrapper.setInnerElement(eitherCreateResponse.right().value());
207                 } else {
208                     resource = eitherCreateResponse.left().value();
209                 }
210             }
211             Response response;
212             //Build Response and store it in the response Wrapper
213             if (responseWrapper.isEmpty()) {
214                 response = buildCreatedResourceResponse(resource, context, responseWrapper);
215             }
216             else{
217                 response = buildErrorResponse(responseWrapper.getInnerElement());
218             }
219             return response;
220
221         } catch (Exception e) {
222             final String message = "failed to create vfc monitoring template resource";
223             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(message);
224             log.debug(message, e);
225             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
226         }
227         finally{
228             prepareAdditionalAudit(resource, additionalParams);
229
230             getComponentsUtils().auditExternalCrudApi(responseWrapper.getInnerElement(),
231                     ComponentTypeEnum.RESOURCE.getValue(), AuditingActionEnum.CREATE_RESOURCE_BY_API.getName(), request,
232                     additionalParams);
233         }
234     }
235
236     /**
237      * Changing the lifecycle of an asset
238      * @param jsonChangeInfo    The description - request body
239      * @param assetType The requested asset type.Valid values are: resources / services (for VFCMT â€“ use "resources")
240      * @param uuid The uuid of the desired resource to be changed
241      * @param lifecycleTransition The lifecycle operation to be performed on the asset.Valid values are:Checkin / Checkout /  CERTIFICATION_REQUEST
242      * @param userId
243      * @return
244      */
245     @POST
246     @Path("/{assetType}/{uuid}/lifecycleState/{lifecycleOperation}")
247     @Consumes(MediaType.APPLICATION_JSON)
248     @Produces(MediaType.APPLICATION_JSON)
249     @ApiOperation(value = "Change Resource lifecycle State", httpMethod = "POST")
250     @ApiResponses(value = {
251             @ApiResponse(code = 200, message = "Resource state changed", response = AssetMetadata.class),
252             @ApiResponse(code = 400, message = "Missing X-ECOMP-InstanceID HTTP header - POL5001"),
253             @ApiResponse(code = 401, message = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic Authentication credentials - POL5002"),
254             @ApiResponse(code = 403, message = "ECOMP component is not authorized - POL5003"),
255             @ApiResponse(code = 404, message = "Error: Requested '%1' (uuid) resource was not found - SVC4063"),
256             @ApiResponse(code = 405, message = "Method  Not Allowed  :  Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"),
257             @ApiResponse(code = 500, message = "The GET request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000"),
258             @ApiResponse(code = 403, message = "Asset is already checked-out by another user - SVC4085"),
259             @ApiResponse(code = 403, message = "Asset is being edited by different user. Only one user can checkout and edit an asset on given time. The asset will be available for checkout after the other user will checkin the asset - SVC4080")})
260     @ApiImplicitParams({@ApiImplicitParam(required = true, dataType = "org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction", paramType = "body", value = "userRemarks - Short description (free text) about the asset version being changed")})
261     public Response changeResourceStateExternal(
262             @ApiParam(value = "Determines the format of the body of the request", required = true)@HeaderParam(value = Constants.CONTENT_TYPE_HEADER) String contenType,
263             @ApiParam(value = "The user id", required = true)@HeaderParam(value = Constants.USER_ID_HEADER) final String userId,
264             @ApiParam(value = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
265             @ApiParam(value = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
266             @ApiParam(value = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
267             @ApiParam(value = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
268             @ApiParam(allowableValues = "checkout, checkin", required = true) @PathParam(value = "lifecycleOperation") final String lifecycleTransition,
269             @ApiParam(value = "id of component to be changed") @PathParam(value = "uuid") final String uuid,
270             @ApiParam(value = "validValues: resources / services ", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam(value = "assetType") final String assetType,
271             String jsonChangeInfo) {
272
273         Response response = null;
274         EnumMap<AuditingFieldsKeysEnum, Object> additionalParams = new EnumMap<>(AuditingFieldsKeysEnum.class);
275
276         init(log);
277
278         String requestURI = request.getRequestURI();
279         String url = request.getMethod() + " " + requestURI;
280         log.debug("Start handle request of {}", url);
281
282         //get the business logic
283         ServletContext context = request.getSession().getServletContext();
284         LifecycleBusinessLogic businessLogic = getLifecycleBL(context);
285
286         Wrapper<ResponseFormat> responseWrapper = runValidations(assetType);
287         ComponentTypeEnum componentType = ComponentTypeEnum.findByParamName(assetType);
288         Component component = null;
289         Component responseObject = null;
290         User modifier = null;
291
292         try{
293             // Validate X-ECOMP-InstanceID Header
294             if (responseWrapper.isEmpty()) {
295                 validateXECOMPInstanceIDHeader(instanceIdHeader, responseWrapper);
296             }
297
298             if (responseWrapper.isEmpty()) {
299                 //get user
300                 Either<User, ResponseFormat> eitherGetUser = getUser(request, userId);
301                 if (eitherGetUser.isRight()) {
302                     ResponseFormat responseFormat = eitherGetUser.right().value();
303                     responseWrapper.setInnerElement(responseFormat);
304                     return buildErrorResponse(responseFormat);
305                 }
306                 modifier = eitherGetUser.left().value();
307
308                 //get the component id from the uuid
309                 Either<Component, ResponseFormat> latestVersion = businessLogic.getLatestComponentByUuid(componentType, uuid);
310                 if (latestVersion.isRight()) {
311                     ResponseFormat responseFormat = latestVersion.right().value();
312                     responseWrapper.setInnerElement(responseFormat);
313                     return buildErrorResponse(responseFormat);
314                 }
315                 component = latestVersion.left().value();
316                 String componentId = component.getUniqueId();
317
318                 //validate the transition is valid
319                 Either<LifeCycleTransitionEnum, ResponseFormat> validateEnum = validateTransitionEnum(lifecycleTransition, modifier);
320                 if (validateEnum.isRight()) {
321                     ResponseFormat responseFormat = validateEnum.right().value();
322                     responseWrapper.setInnerElement(responseFormat);
323                     return buildErrorResponse(responseFormat);
324                 }
325                 LifeCycleTransitionEnum transitionEnum = validateEnum.left().value();
326
327                 //create changeInfo
328                 LifecycleChangeInfoWithAction changeInfo = new LifecycleChangeInfoWithAction();
329                 try {
330                     if (jsonChangeInfo != null && !jsonChangeInfo.isEmpty()) {
331                         ObjectMapper mapper = new ObjectMapper();
332                         changeInfo = new LifecycleChangeInfoWithAction(mapper.readValue(jsonChangeInfo, LifecycleChangeInfoBase.class).getUserRemarks());
333                     }
334                 }
335                 catch (Exception e) {
336                     BeEcompErrorManager.getInstance().logBeInvalidJsonInput("convertJsonToObject");
337                     log.debug("failed to convert from json {}", jsonChangeInfo, e);
338                     ResponseFormat responseFormat = getComponentsUtils().getInvalidContentErrorAndAudit(modifier, componentId, AuditingActionEnum.CHECKOUT_RESOURCE);
339                     responseWrapper.setInnerElement(responseFormat);
340                     return buildErrorResponse(responseFormat);
341                 }
342
343                 //execute business logic
344                 Either<? extends Component, ResponseFormat> actionResponse = businessLogic.changeComponentState(componentType, componentId, modifier, transitionEnum, changeInfo, false, true);
345                 if (actionResponse.isRight()) {
346                     log.info("failed to change resource state");
347                     ResponseFormat responseFormat = actionResponse.right().value();
348                     responseWrapper.setInnerElement(responseFormat);
349                     return buildErrorResponse(responseFormat);
350                 }
351
352                 log.debug("change state successful !!!");
353                 responseObject = actionResponse.left().value();
354                 response = buildCreatedResourceResponse(responseObject, context, responseWrapper);
355             } else {
356                 response = buildErrorResponse(responseWrapper.getInnerElement());
357             }
358
359             return response;
360         } catch (Exception e) {
361             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Change Lifecycle State");
362             log.debug("change lifecycle state failed with exception", e);
363             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
364             responseWrapper.setInnerElement(responseFormat);
365             return buildErrorResponse(responseFormat);
366         } finally{
367             auditChnageLifecycleAction(additionalParams, responseWrapper, componentType, component, responseObject, modifier, userId);
368         }
369     }
370
371     private void prepareAdditionalAudit(Resource resource, EnumMap<AuditingFieldsKeysEnum, Object> additionalParams) {
372         additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_VERSION, StringUtils.EMPTY);
373         additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_STATE, StringUtils.EMPTY);
374
375         if( resource != null ){
376             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_VERSION, ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION);
377             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name());
378             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resource.getName());
379             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_SERVICE_INSTANCE_ID, resource.getUUID());
380             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_INVARIANT_UUID, resource.getInvariantUUID());
381         } else {
382             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_VERSION, StringUtils.EMPTY);
383             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_STATE, StringUtils.EMPTY);
384             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_SERVICE_INSTANCE_ID, StringUtils.EMPTY);
385             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_INVARIANT_UUID, StringUtils.EMPTY);
386         }
387     }
388
389     private Response buildCreatedResourceResponse(Component resource, ServletContext context,
390             Wrapper<ResponseFormat> responseWrapper) throws IOException {
391         ResponseFormat responseFormat;
392         Response response;
393         AssetMetadataConverter assetMetadataUtils = getAssetUtils(context);
394         Either<? extends AssetMetadata, ResponseFormat> resMetadata = assetMetadataUtils
395                 .convertToSingleAssetMetadata(resource, request.getRequestURL().toString(),
396                         true);
397         if (resMetadata.isRight()) {
398             log.debug("Asset conversion Failed");
399             responseFormat = resMetadata.right().value();
400             responseWrapper.setInnerElement(responseFormat);
401             response = buildErrorResponse(responseFormat);
402         }else{
403             final AssetMetadata assetData = resMetadata.left().value();
404             assetData.setToscaModelURL(null);
405
406             responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.CREATED));
407             Object representation = RepresentationUtils.toRepresentation(assetData);
408             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
409         }
410         return response;
411     }
412
413     private void handleCategories(ServletContext context, String data, Resource resource,
414             Wrapper<ResponseFormat> responseWrapper) {
415         try {
416             JSONParser parser = new JSONParser();
417             JSONObject jsonObj = (JSONObject) parser.parse(data);
418             String category = (String) jsonObj.get(CategoryTypeEnum.CATEGORY.getValue());
419             String subcategory = (String) jsonObj.get(CategoryTypeEnum.SUBCATEGORY.getValue());
420             if (Strings.isEmpty(category)) {
421                 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
422                         ActionStatus.COMPONENT_MISSING_CATEGORY, ComponentTypeEnum.RESOURCE.getValue()));
423             }
424             else if (Strings.isEmpty(subcategory)) {
425                 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
426                         ActionStatus.COMPONENT_MISSING_SUBCATEGORY));
427             }
428             if (responseWrapper.isEmpty()) {
429                 ElementBusinessLogic elementLogic = getElementBL(context);
430                 // get All Categories
431                 Either<List<CategoryDefinition>, ActionStatus> allResourceCategories = elementLogic
432                         .getAllResourceCategories();
433                 // Error fetching categories
434                 if (allResourceCategories.isRight()) {
435                     responseWrapper.setInnerElement(
436                             getComponentsUtils().getResponseFormat(allResourceCategories.right().value()));
437                 } else {
438                     addCategories(resource, category, subcategory, allResourceCategories, responseWrapper);
439                 }
440             }
441         } catch (Exception e) {
442             log.debug("Exception occured in addCategories: {}", e.getMessage(), e);
443             responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
444         }
445
446     }
447
448     private void addCategories(Resource resource, String category, String subcategory,
449             Either<List<CategoryDefinition>, ActionStatus> allResourceCategories,
450             Wrapper<ResponseFormat> responseWrapper) {
451         Optional<CategoryDefinition> optionalCategory =
452                 // Stream of all the categories
453                 allResourceCategories.left().value().stream()
454                         // filter in only relevant category
455                         .filter(e -> e.getName().equals(category))
456                         // get the result
457                         .findAny();
458         if (!optionalCategory.isPresent()) {
459             responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
460                     ActionStatus.COMPONENT_INVALID_CATEGORY, ComponentTypeEnum.RESOURCE.getValue()));
461         } else {
462             CategoryDefinition categoryDefinition = optionalCategory.get();
463
464             List<SubCategoryDefinition> subCaregories =
465                     // Stream of all sub-categories of the relevant
466                     // category
467                     categoryDefinition.getSubcategories().stream()
468                             // filter in only relevant sub-category
469                             .filter(e -> e.getName().equals(subcategory))
470                             // get the result
471                             .collect(Collectors.toList());
472
473             if( subCaregories.isEmpty() ){
474                 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
475                         ActionStatus.COMPONENT_INVALID_SUBCATEGORY, ComponentTypeEnum.RESOURCE.getValue()));
476             }
477             else{
478                 categoryDefinition.setSubcategories(subCaregories);
479                 resource.setCategories(Arrays.asList(categoryDefinition));
480             }
481
482         }
483     }
484
485
486
487
488     private void auditChnageLifecycleAction(EnumMap<AuditingFieldsKeysEnum, Object> additionalParams,
489             Wrapper<ResponseFormat> responseWrapper, ComponentTypeEnum componentType, Component component,
490             Component responseObject, User modifier, String userId) {
491         if (modifier!=null){
492             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_NAME, modifier.getFullName());
493             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_UID, modifier.getUserId());
494         } else {
495             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_NAME, "");
496             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_UID, userId);
497         }
498
499         if (component!=null){
500             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName());
501             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_VERSION, component.getVersion());
502             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_STATE, component.getLifecycleState().name());
503         } else {
504             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, "");
505             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_VERSION, "");
506             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_STATE, "");
507         }
508
509         if (responseObject!=null){
510             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_VERSION, responseObject.getVersion());
511             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_SERVICE_INSTANCE_ID, responseObject.getUUID());
512             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_INVARIANT_UUID, responseObject.getInvariantUUID());
513             additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_STATE,responseObject.getLifecycleState().name());
514         } else {
515             if (component!=null){
516                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_VERSION, component.getVersion());
517                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_SERVICE_INSTANCE_ID, component.getUUID());
518                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_INVARIANT_UUID, component.getInvariantUUID());
519                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_STATE,component.getLifecycleState().name());
520             } else {
521                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_VERSION, "");
522                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_SERVICE_INSTANCE_ID, "");
523                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_INVARIANT_UUID, "");
524                 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_CURR_STATE,"");
525             }
526         }
527
528         getComponentsUtils().auditExternalCrudApi(responseWrapper.getInnerElement(),
529                 componentType.getValue(), AuditingActionEnum.CHANGE_LIFECYCLE_BY_API.getName(), request,
530                 additionalParams);
531     }
532
533     private Wrapper<ResponseFormat> runValidations(final String assetType) {
534         Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
535
536         // Validate X-ECOMP-InstanceID Header
537         if (responseWrapper.isEmpty()) {
538             String instanceId = request.getHeader(Constants.X_ECOMP_INSTANCE_ID_HEADER);
539             validateXECOMPInstanceIDHeader(instanceId,responseWrapper);
540         }
541         // Validate USER_ID Header
542         if (responseWrapper.isEmpty()) {
543             validateHttpCspUserIdHeader(request.getHeader(Constants.USER_ID_HEADER),responseWrapper);
544         }
545         // Validate assetType
546         if (responseWrapper.isEmpty()) {
547             if( !AssetTypeEnum.RESOURCES.getValue().equals(assetType) &&  !AssetTypeEnum.SERVICES.getValue().equals(assetType)){
548                 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
549             }
550         }
551
552         return responseWrapper;
553     }
554
555     private Either<LifeCycleTransitionEnum, ResponseFormat> validateTransitionEnum(final String lifecycleTransition, User user) {
556         LifeCycleTransitionEnum transitionEnum = LifeCycleTransitionEnum.CHECKOUT;
557         try {
558             transitionEnum = LifeCycleTransitionEnum.getFromDisplayName(lifecycleTransition);
559         } catch (IllegalArgumentException e) {
560             log.info("state operation is not valid. operations allowed are: {}", LifeCycleTransitionEnum.valuesAsString(), e);
561             ResponseFormat error = getComponentsUtils().getInvalidContentErrorAndAudit(user, "", AuditingActionEnum.CHECKOUT_RESOURCE);
562             return Either.right(error);
563         }
564         return Either.left(transitionEnum);
565     }
566
567 }