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