2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.externalapi.servlet;
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;
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;
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;
85 import com.jcabi.aspects.Loggable;
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;
96 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
98 @Api(value = "CRUD External Servlet", description = "This Servlet serves external users for creating assets and changing their lifecycle state")
100 public class CrudExternalServlet extends AbstractValidationsServlet {
103 private HttpServletRequest request;
105 private static Logger log = LoggerFactory.getLogger(CrudExternalServlet.class.getName());
108 * Creates a new Resource
113 * @param instanceIdHeader
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,
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);
166 // Validate X-ECOMP-InstanceID Header
167 if (responseWrapper.isEmpty()) {
168 validateXECOMPInstanceIDHeader(instanceIdHeader, responseWrapper);
170 // Validate USER_ID Header
171 if (responseWrapper.isEmpty()) {
172 validateHttpCspUserIdHeader(userId, responseWrapper);
174 // Validate assetType
175 if (responseWrapper.isEmpty()) {
176 if( !AssetTypeEnum.RESOURCES.getValue().equals(assetType) ){
177 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
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));
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());
201 resource = eitherResource.left().value();
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()));
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);
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());
228 resource = eitherCreateResponse.left().value();
232 //Build Response and store it in the response Wrapper
233 if (responseWrapper.isEmpty()) {
234 response = buildCreatedResourceResponse(resource, context, responseWrapper);
237 response = buildErrorResponse(responseWrapper.getInnerElement());
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));
248 prepareAdditionalAudit(resource, additionalParams);
250 getComponentsUtils().auditExternalCrudApi(responseWrapper.getInnerElement(),
251 ComponentTypeEnum.RESOURCE.getValue(), AuditingActionEnum.CREATE_RESOURCE_BY_API.getName(), request,
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
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) {
293 Response response = null;
294 EnumMap<AuditingFieldsKeysEnum, Object> additionalParams = new EnumMap<>(AuditingFieldsKeysEnum.class);
298 String requestURI = request.getRequestURI();
299 String url = request.getMethod() + " " + requestURI;
300 log.debug("Start handle request of {}", url);
302 //get the business logic
303 ServletContext context = request.getSession().getServletContext();
304 LifecycleBusinessLogic businessLogic = getLifecycleBL(context);
306 Wrapper<ResponseFormat> responseWrapper = runValidations(assetType);
307 ComponentTypeEnum componentType = ComponentTypeEnum.findByParamName(assetType);
308 Component component = null;
309 Component responseObject = null;
310 User modifier = null;
313 // Validate X-ECOMP-InstanceID Header
314 if (responseWrapper.isEmpty()) {
315 validateXECOMPInstanceIDHeader(instanceIdHeader, responseWrapper);
318 if (responseWrapper.isEmpty()) {
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);
326 modifier = eitherGetUser.left().value();
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);
335 component = latestVersion.left().value();
336 String componentId = component.getUniqueId();
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);
345 LifeCycleTransitionEnum transitionEnum = validateEnum.left().value();
348 LifecycleChangeInfoWithAction changeInfo = new LifecycleChangeInfoWithAction();
350 if (jsonChangeInfo != null && !jsonChangeInfo.isEmpty()) {
351 ObjectMapper mapper = new ObjectMapper();
352 changeInfo = new LifecycleChangeInfoWithAction(mapper.readValue(jsonChangeInfo, LifecycleChangeInfoBase.class).getUserRemarks());
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);
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);
373 log.debug("change state successful !!!");
374 responseObject = actionResponse.left().value();
375 response = buildCreatedResourceResponse(responseObject, context, responseWrapper);
377 response = buildErrorResponse(responseWrapper.getInnerElement());
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);
389 auditChnageLifecycleAction(additionalParams, responseWrapper, componentType, component, responseObject, modifier, userId);
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);
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());
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);
411 private Response buildCreatedResourceResponse(Component resource, ServletContext context,
412 Wrapper<ResponseFormat> responseWrapper) throws IOException, JsonGenerationException, JsonMappingException {
413 ResponseFormat responseFormat;
415 AssetMetadataConverter assetMetadataUtils = getAssetUtils(context);
416 Either<? extends AssetMetadata, ResponseFormat> resMetadata = assetMetadataUtils
417 .convertToSingleAssetMetadata(resource, request.getRequestURL().toString(),
419 if (resMetadata.isRight()) {
420 log.debug("Asset conversion Failed");
421 responseFormat = resMetadata.right().value();
422 responseWrapper.setInnerElement(responseFormat);
423 response = buildErrorResponse(responseFormat);
425 final AssetMetadata assetData = resMetadata.left().value();
426 assetData.setToscaModelURL(null);
428 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.CREATED));
429 Object representation = RepresentationUtils.toRepresentation(assetData);
430 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
435 private void handleCategories(ServletContext context, String data, Resource resource,
436 Wrapper<ResponseFormat> responseWrapper) {
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()));
446 else if (Strings.isEmpty(subcategory)) {
447 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
448 ActionStatus.COMPONENT_MISSING_SUBCATEGORY));
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()));
460 addCategories(resource, category, subcategory, allResourceCategories, responseWrapper);
463 } catch (Exception e) {
464 log.debug("Exception occured in addCategories: {}", e.getMessage(), e);
465 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
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))
480 if (!optionalCategory.isPresent()) {
481 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
482 ActionStatus.COMPONENT_INVALID_CATEGORY, ComponentTypeEnum.RESOURCE.getValue()));
484 CategoryDefinition categoryDefinition = optionalCategory.get();
486 List<SubCategoryDefinition> subCaregories =
487 // Stream of all sub-categories of the relevant
489 categoryDefinition.getSubcategories().stream()
490 // filter in only relevant sub-category
491 .filter(e -> e.getName().equals(subcategory))
493 .collect(Collectors.toList());
495 if( subCaregories.isEmpty() ){
496 responseWrapper.setInnerElement(getComponentsUtils().getResponseFormat(
497 ActionStatus.COMPONENT_INVALID_SUBCATEGORY, ComponentTypeEnum.RESOURCE.getValue()));
500 categoryDefinition.setSubcategories(subCaregories);
501 resource.setCategories(Arrays.asList(categoryDefinition));
510 private void auditChnageLifecycleAction(EnumMap<AuditingFieldsKeysEnum, Object> additionalParams,
511 Wrapper<ResponseFormat> responseWrapper, ComponentTypeEnum componentType, Component component,
512 Component responseObject, User modifier, String userId) {
514 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_NAME, modifier.getFullName());
515 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_UID, modifier.getUserId());
517 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_NAME, "");
518 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_MODIFIER_UID, userId);
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());
526 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, "");
527 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_VERSION, "");
528 additionalParams.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_PREV_STATE, "");
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());
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());
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,"");
550 getComponentsUtils().auditExternalCrudApi(responseWrapper.getInnerElement(),
551 componentType.getValue(), AuditingActionEnum.CHANGE_LIFECYCLE_BY_API.getName(), request,
555 private Wrapper<ResponseFormat> runValidations(final String assetType) {
556 Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
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);
563 // Validate USER_ID Header
564 if (responseWrapper.isEmpty()) {
565 validateHttpCspUserIdHeader(request.getHeader(Constants.USER_ID_HEADER),responseWrapper);
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));
574 return responseWrapper;
577 private Either<LifeCycleTransitionEnum, ResponseFormat> validateTransitionEnum(final String lifecycleTransition, User user) {
578 LifeCycleTransitionEnum transitionEnum = LifeCycleTransitionEnum.CHECKOUT;
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);
586 return Either.left(transitionEnum);