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 java.util.List;
25 import javax.servlet.ServletContext;
27 import org.openecomp.sdc.be.config.BeEcompErrorManager;
28 import org.openecomp.sdc.be.config.ConfigurationManager;
29 import org.openecomp.sdc.be.dao.api.ActionStatus;
30 import org.openecomp.sdc.be.dao.graph.datatype.AdditionalInformationEnum;
31 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
32 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterInfo;
33 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
34 import org.openecomp.sdc.be.impl.ComponentsUtils;
35 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
36 import org.openecomp.sdc.be.model.AdditionalInformationDefinition;
37 import org.openecomp.sdc.be.model.User;
38 import org.openecomp.sdc.be.model.operations.api.IAdditionalInformationOperation;
39 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
40 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
41 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
42 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
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.config.EcompErrorName;
48 import org.openecomp.sdc.common.util.ValidationUtils;
49 import org.openecomp.sdc.exception.ResponseFormat;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52 import org.springframework.stereotype.Component;
53 import org.springframework.web.context.WebApplicationContext;
55 import fj.data.Either;
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 Logger log = LoggerFactory.getLogger(AdditionalInformationBusinessLogic.class.getName());
70 @javax.annotation.Resource
71 private IAdditionalInformationOperation additionalInformationOperation = null;
73 @javax.annotation.Resource
74 private IGraphLockOperation graphLockOperation;
76 @javax.annotation.Resource
77 private ComponentsUtils componentsUtils;
79 protected static IElementOperation getElementDao(Class<IElementOperation> class1, ServletContext context) {
80 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
82 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
84 return webApplicationContext.getBean(class1);
88 * Create new additional information on resource/service on graph
92 * @param newPropertyDefinition
94 * @return Either<PropertyDefinition, ActionStatus>
96 public Either<AdditionalInfoParameterInfo, ResponseFormat> createAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
98 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
100 return Either.right(resp.right().value());
102 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
104 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
105 if (responseFormat != null) {
106 result = Either.right(responseFormat);
111 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
112 if (!lockResult.equals(StorageOperationStatus.OK)) {
113 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, CREATE_ADDITIONAL_INFORMATION);
114 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
115 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
116 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
120 responseFormat = validateMaxSizeNotReached(nodeType, resourceId, additionalInfoParameterInfo);
121 if (responseFormat != null) {
122 result = Either.right(responseFormat);
127 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
128 if (responseFormat != null) {
129 result = Either.right(responseFormat);
134 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
135 if (responseFormat != null) {
136 result = Either.right(responseFormat);
140 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.createAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getKey(),
141 additionalInfoParameterInfo.getValue(), true);
143 if (addResult.isRight()) {
144 StorageOperationStatus status = addResult.right().value();
145 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, CREATE_ADDITIONAL_INFORMATION);
146 BeEcompErrorManager.getInstance().logBeSystemError(CREATE_ADDITIONAL_INFORMATION);
147 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
148 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.Label));
152 AdditionalInformationDefinition informationDefinition = addResult.left().value();
154 AdditionalInfoParameterInfo createdAI = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
155 result = Either.left(createdAI);
160 commitOrRollback(result);
162 graphLockOperation.unlockComponent(resourceId, nodeType);
168 * Validate the value format. Format the value.
170 * @param additionalInfoParameterInfo
171 * @return null in case of success. Otherwise response format.
173 private ResponseFormat validateAndConvertValue(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
174 ResponseFormat result = null;
176 String value = additionalInfoParameterInfo.getValue();
177 log.debug("Going to validate additional information value {}", value);
179 Either<String, ResponseFormat> valueValidRes = validateValue(value);
180 if (valueValidRes.isRight()) {
181 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeInvalidValueError, context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
182 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
183 result = valueValidRes.right().value();
185 String newValue = valueValidRes.left().value();
186 if (log.isTraceEnabled()) {
187 if (value != null && false == value.equals(newValue)) {
188 log.trace("The additional information value was normalized from {} to {}", value, newValue);
191 additionalInfoParameterInfo.setValue(newValue);
197 * @param additionalInfoParameterInfo
200 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
202 String key = additionalInfoParameterInfo.getKey();
203 log.debug("Going to validate additional information key {}", key);
205 ResponseFormat result = null;
206 ResponseFormat responseFormat;
207 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
208 if (validateKeyRes.isRight()) {
209 responseFormat = validateKeyRes.right().value();
210 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeInvalidValueError, context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
211 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
212 result = responseFormat;
215 String convertedKey = validateKeyRes.left().value();
217 if (log.isTraceEnabled()) {
218 if (key != null && false == key.equals(convertedKey)) {
219 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
222 additionalInfoParameterInfo.setKey(convertedKey);
228 * verify that the maximal number of additional information properties has not been reached.
232 * @param additionalInfoParameterInfo
233 * @return response format in case the maximal number has been reached.
235 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId, AdditionalInfoParameterInfo additionalInfoParameterInfo) {
237 ResponseFormat result;
238 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration().getAdditionalInformationMaxNumberOfKeys();
240 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation.getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
241 if (checkRes.isRight()) {
242 StorageOperationStatus status = checkRes.right().value();
244 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
245 result = componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
248 Integer currentNumberOfProperties = checkRes.left().value();
249 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
250 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}", currentNumberOfProperties, currentNumberOfProperties);
251 result = componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
259 * validate additional information value
264 private Either<String, ResponseFormat> validateValue(String value) {
266 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(value);
267 if (false == isNonEmptyString) {
268 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED));
271 boolean valid = StringValidator.getInstance().isValid(value, null);
272 if (false == valid) {
273 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS, new AdditionalInfoParameterInfo(null, value), null, AdditionalInformationEnum.Value));
276 String converted = StringConvertor.getInstance().convert(value, null, null);
278 return Either.left(converted);
281 private AdditionalInfoParameterInfo findAdditionInformationKey(List<AdditionalInfoParameterInfo> parameters, String key) {
283 for (AdditionalInfoParameterInfo infoParameterInfo : parameters) {
284 if (infoParameterInfo.getKey().equals(key)) {
285 return infoParameterInfo;
292 * validate and normalize the key
294 * @param additionalInfoParameterInfo
297 private Either<String, ResponseFormat> validateAndNormalizeKey(String key) {
299 AdditionalInfoParameterInfo additionalInfoParameterInfo = new AdditionalInfoParameterInfo();
300 additionalInfoParameterInfo.setKey(key);
302 key = ValidationUtils.normalizeAdditionalInformation(key);
303 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(key);
304 if (false == isNonEmptyString) {
305 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null, AdditionalInformationEnum.Label));
307 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(key);
308 if (false == isValidString) {
309 if (false == ValidationUtils.validateLength(key, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
310 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
312 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
315 return Either.left(key);
319 * update key and value of a given additional information.
323 * @param additionalInfoParameterInfo
324 * @param additionalInformationUid
329 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
331 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
332 if (resp.isRight()) {
333 return Either.right(resp.right().value());
335 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
337 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
338 if (responseFormat != null) {
339 result = Either.right(responseFormat);
343 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
344 if (!lockResult.equals(StorageOperationStatus.OK)) {
345 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, UPDATE_ADDITIONAL_INFORMATION);
346 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
347 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
348 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
354 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
355 if (responseFormat != null) {
356 result = Either.right(responseFormat);
360 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
361 if (responseFormat != null) {
362 result = Either.right(responseFormat);
366 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
367 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
369 if (addResult.isRight()) {
370 StorageOperationStatus status = addResult.right().value();
371 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, UPDATE_ADDITIONAL_INFORMATION);
372 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
373 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
374 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
377 AdditionalInformationDefinition informationDefinition = addResult.left().value();
378 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
379 result = Either.left(parameterInfo);
384 commitOrRollback(result);
386 graphLockOperation.unlockComponent(resourceId, nodeType);
392 * Delete an additional information label
396 * @param additionalInfoParameterInfo
397 * @param additionalInformationUid
398 * - Null. Future use.
402 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
404 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Additional Information", false);
405 if (resp.isRight()) {
406 return Either.right(resp.right().value());
408 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
410 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
411 if (responseFormat != null) {
412 return Either.right(responseFormat);
415 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
416 if (!lockResult.equals(StorageOperationStatus.OK)) {
417 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, DELETE_ADDITIONAL_INFORMATION);
418 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
419 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
420 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
426 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
427 if (findIdRes.isRight()) {
428 StorageOperationStatus status = findIdRes.right().value();
429 if (status != StorageOperationStatus.NOT_FOUND) {
430 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, GET_ADDITIONAL_INFORMATION);
431 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
433 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
434 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
438 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
440 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
442 if (addResult.isRight()) {
443 StorageOperationStatus status = addResult.right().value();
444 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, DELETE_ADDITIONAL_INFORMATION);
445 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
446 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
447 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
450 result = Either.left(foundAdditionalInfo);
455 commitOrRollback(result);
457 graphLockOperation.unlockComponent(resourceId, nodeType);
465 * @param additionalInfoParameterInfo
466 * @param additionalInformationUid
470 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
472 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Additional Information", false);
473 if (resp.isRight()) {
474 return Either.right(resp.right().value());
476 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
480 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
482 if (findIdRes.isRight()) {
483 StorageOperationStatus status = findIdRes.right().value();
484 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
485 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
488 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
490 result = Either.left(foundAdditionalInfo);
495 commitOrRollback(result);
501 * Get all additional information properties of a given resource/service
505 * @param additionalInformationUid
510 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId, String additionalInformationUid, String userId) {
512 Either<User, ResponseFormat> resp = validateUserExists(userId, "get All Additional Information", false);
513 if (resp.isRight()) {
514 return Either.right(resp.right().value());
517 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
521 Either<AdditionalInformationDefinition, TitanOperationStatus> findIdRes = additionalInformationOperation.getAllAdditionalInformationParameters(nodeType, resourceId, false);
522 if (findIdRes.isRight()) {
523 StorageOperationStatus status = DaoStatusConverter.convertTitanStatusToStorageStatus(findIdRes.right().value());
524 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
525 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
527 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
528 result = Either.left(informationDefinition);
534 commitOrRollback(result);
539 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
544 // verify that resource is checked-out and the user is the last
546 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
547 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
552 // verify that resource is checked-out and the user is the last
554 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
555 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
559 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());