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