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