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