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.components.impl;
23 import fj.data.Either;
24 import org.openecomp.sdc.be.config.BeEcompErrorManager;
25 import org.openecomp.sdc.be.config.ConfigurationManager;
26 import org.openecomp.sdc.be.dao.api.ActionStatus;
27 import org.openecomp.sdc.be.dao.graph.datatype.AdditionalInformationEnum;
28 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
29 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterInfo;
30 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
31 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
32 import org.openecomp.sdc.be.model.AdditionalInformationDefinition;
33 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
34 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
35 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
36 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
37 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
38 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
39 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
40 import org.openecomp.sdc.be.model.operations.impl.AdditionalInformationOperation;
41 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
42 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
43 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
44 import org.openecomp.sdc.be.model.tosca.converters.StringConvertor;
45 import org.openecomp.sdc.be.model.tosca.validators.StringValidator;
46 import org.openecomp.sdc.common.api.Constants;
47 import org.openecomp.sdc.common.log.wrappers.Logger;
48 import org.openecomp.sdc.common.util.ValidationUtils;
49 import org.openecomp.sdc.exception.ResponseFormat;
50 import org.springframework.beans.factory.annotation.Autowired;
51 import org.springframework.stereotype.Component;
52 import org.springframework.web.context.WebApplicationContext;
54 import javax.servlet.ServletContext;
55 import java.util.List;
57 @Component("additionalInformationBusinessLogic")
58 public class AdditionalInformationBusinessLogic extends BaseBusinessLogic {
60 private static final String CREATE_ADDITIONAL_INFORMATION = "CreateAdditionalInformation";
62 private static final String UPDATE_ADDITIONAL_INFORMATION = "UpdateAdditionalInformation";
64 private static final String DELETE_ADDITIONAL_INFORMATION = "DeleteAdditionalInformation";
66 private static final String GET_ADDITIONAL_INFORMATION = "GetAdditionalInformation";
68 private static final Logger log = Logger.getLogger(AdditionalInformationBusinessLogic.class.getName());
69 private static final String FAILED_TO_LOCK_COMPONENT_ERROR = "Failed to lock component {} error - {}";
71 private final AdditionalInformationOperation additionalInformationOperation;
74 public AdditionalInformationBusinessLogic(IElementOperation elementDao,
75 IGroupOperation groupOperation,
76 IGroupInstanceOperation groupInstanceOperation,
77 IGroupTypeOperation groupTypeOperation,
78 InterfaceOperation interfaceOperation,
79 InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
80 AdditionalInformationOperation additionalInformationOperation,
81 ArtifactsOperations artifactToscaOperation) {
82 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation,
83 interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation);
84 this.additionalInformationOperation = additionalInformationOperation;
87 protected static IElementOperation getElementDao(Class<IElementOperation> class1, ServletContext context) {
88 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
90 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
92 return webApplicationContext.getBean(class1);
96 * Create new additional information on resource/service on graph
99 * @param additionalInfoParameterInfo
101 * @return Either<AdditionalInfoParameterInfo, ResponseFormat>
103 public Either<AdditionalInfoParameterInfo, ResponseFormat> createAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String userId) {
105 validateUserExists(userId);
106 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
108 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
109 if (responseFormat != null) {
110 result = Either.right(responseFormat);
115 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
116 if (lockResult != StorageOperationStatus.OK) {
117 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
118 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
119 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
123 responseFormat = validateMaxSizeNotReached(nodeType, resourceId, additionalInfoParameterInfo);
124 if (responseFormat != null) {
125 result = Either.right(responseFormat);
130 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
131 if (responseFormat != null) {
132 result = Either.right(responseFormat);
137 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
138 if (responseFormat != null) {
139 result = Either.right(responseFormat);
143 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.createAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getKey(),
144 additionalInfoParameterInfo.getValue(), true);
146 if (addResult.isRight()) {
147 StorageOperationStatus status = addResult.right().value();
148 BeEcompErrorManager.getInstance().logBeSystemError(CREATE_ADDITIONAL_INFORMATION);
149 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
150 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.Label));
154 AdditionalInformationDefinition informationDefinition = addResult.left().value();
156 AdditionalInfoParameterInfo createdAI = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
157 result = Either.left(createdAI);
162 commitOrRollback(result);
164 graphLockOperation.unlockComponent(resourceId, nodeType);
170 * Validate the value format. Format the value.
172 * @param additionalInfoParameterInfo
173 * @return null in case of success. Otherwise response format.
175 private ResponseFormat validateAndConvertValue(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
176 ResponseFormat result = null;
178 String value = additionalInfoParameterInfo.getValue();
179 log.debug("Going to validate additional information value {}", value);
181 Either<String, ResponseFormat> valueValidRes = validateValue(value);
182 if (valueValidRes.isRight()) {
183 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
184 result = valueValidRes.right().value();
186 String newValue = valueValidRes.left().value();
187 if (log.isTraceEnabled()) {
188 if (value != null && !value.equals(newValue)) {
189 log.trace("The additional information value was normalized from {} to {}", value, newValue);
192 additionalInfoParameterInfo.setValue(newValue);
198 * @param additionalInfoParameterInfo
201 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
203 String key = additionalInfoParameterInfo.getKey();
204 log.debug("Going to validate additional information key {}", key);
206 ResponseFormat result = null;
207 ResponseFormat responseFormat;
208 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
209 if (validateKeyRes.isRight()) {
210 responseFormat = validateKeyRes.right().value();
211 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
212 result = responseFormat;
215 String convertedKey = validateKeyRes.left().value();
217 if (log.isTraceEnabled() && key != null && !key.equals(convertedKey)) {
218 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
220 additionalInfoParameterInfo.setKey(convertedKey);
226 * verify that the maximal number of additional information properties has not been reached.
230 * @param additionalInfoParameterInfo
231 * @return response format in case the maximal number has been reached.
233 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId, AdditionalInfoParameterInfo additionalInfoParameterInfo) {
235 ResponseFormat result;
236 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration().getAdditionalInformationMaxNumberOfKeys();
238 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation.getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
239 if (checkRes.isRight()) {
240 StorageOperationStatus status = checkRes.right().value();
242 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
243 result = componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
246 Integer currentNumberOfProperties = checkRes.left().value();
247 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
248 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}", currentNumberOfProperties, currentNumberOfProperties);
249 result = componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
257 * validate additional information value
262 private Either<String, ResponseFormat> validateValue(String value) {
264 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(value);
265 if (!isNonEmptyString) {
266 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED));
269 boolean valid = StringValidator.getInstance().isValid(value, null);
271 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS, new AdditionalInfoParameterInfo(null, value), null, AdditionalInformationEnum.Value));
274 String converted = StringConvertor.getInstance().convert(value, null, null);
276 return Either.left(converted);
279 private AdditionalInfoParameterInfo findAdditionInformationKey(List<AdditionalInfoParameterInfo> parameters, String key) {
281 for (AdditionalInfoParameterInfo infoParameterInfo : parameters) {
282 if (infoParameterInfo.getKey().equals(key)) {
283 return infoParameterInfo;
290 * validate and normalize the key
292 * @return Either<String, ResponseFormat>
294 private Either<String, ResponseFormat> validateAndNormalizeKey(String key) {
296 AdditionalInfoParameterInfo additionalInfoParameterInfo = new AdditionalInfoParameterInfo();
297 additionalInfoParameterInfo.setKey(key);
299 String normKey = ValidationUtils.normalizeAdditionalInformation(key);
300 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(normKey);
301 if (!isNonEmptyString) {
302 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null, AdditionalInformationEnum.Label));
304 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(normKey);
305 if (!isValidString) {
306 if (!ValidationUtils.validateLength(normKey, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
307 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
309 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
312 return Either.left(normKey);
316 * update key and value of a given additional information.
320 * @param additionalInfoParameterInfo
324 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String userId) {
326 validateUserExists(userId);
327 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
329 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
330 if (responseFormat != null) {
331 result = Either.right(responseFormat);
335 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
336 if (lockResult != StorageOperationStatus.OK) {
337 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
338 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
339 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
345 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
346 if (responseFormat != null) {
347 result = Either.right(responseFormat);
351 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
352 if (responseFormat != null) {
353 result = Either.right(responseFormat);
357 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
358 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
360 if (addResult.isRight()) {
361 StorageOperationStatus status = addResult.right().value();
362 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
363 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
364 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
367 AdditionalInformationDefinition informationDefinition = addResult.left().value();
368 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
369 result = Either.left(parameterInfo);
374 commitOrRollback(result);
376 graphLockOperation.unlockComponent(resourceId, nodeType);
382 * Delete an additional information label
386 * @param additionalInfoParameterInfo
390 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String userId) {
392 validateUserExists(userId);
393 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
395 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
396 if (responseFormat != null) {
397 return Either.right(responseFormat);
400 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
401 if (lockResult != StorageOperationStatus.OK) {
402 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
403 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
404 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
410 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
411 if (findIdRes.isRight()) {
412 StorageOperationStatus status = findIdRes.right().value();
413 if (status != StorageOperationStatus.NOT_FOUND) {
414 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
416 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
417 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
421 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
423 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
425 if (addResult.isRight()) {
426 StorageOperationStatus status = addResult.right().value();
427 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
428 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
429 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
432 result = Either.left(foundAdditionalInfo);
437 commitOrRollback(result);
439 graphLockOperation.unlockComponent(resourceId, nodeType);
447 * @param additionalInfoParameterInfo
451 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String userId) {
453 validateUserExists(userId);
454 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
458 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
460 if (findIdRes.isRight()) {
461 StorageOperationStatus status = findIdRes.right().value();
462 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
463 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
466 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
468 result = Either.left(foundAdditionalInfo);
473 commitOrRollback(result);
479 * Get all additional information properties of a given resource/service
486 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId, String userId) {
488 validateUserExists(userId);
490 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
494 Either<AdditionalInformationDefinition, JanusGraphOperationStatus> findIdRes = additionalInformationOperation.getAllAdditionalInformationParameters(nodeType, resourceId, false);
495 if (findIdRes.isRight()) {
496 StorageOperationStatus status = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(findIdRes.right().value());
497 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
498 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
500 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
501 result = Either.left(informationDefinition);
507 commitOrRollback(result);
512 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
517 // verify that resource is checked-out and the user is the last
519 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
520 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
525 // verify that resource is checked-out and the user is the last
527 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
528 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
532 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());