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