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.enums.NodeTypeEnum;
33 import org.openecomp.sdc.be.impl.ComponentsUtils;
34 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
35 import org.openecomp.sdc.be.model.AdditionalInfoParameterInfo;
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.IResourceOperation;
42 import org.openecomp.sdc.be.model.operations.api.IServiceOperation;
43 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
44 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
45 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
46 import org.openecomp.sdc.be.model.tosca.converters.StringConvertor;
47 import org.openecomp.sdc.be.model.tosca.validators.StringValidator;
48 import org.openecomp.sdc.common.api.Constants;
49 import org.openecomp.sdc.common.config.EcompErrorName;
50 import org.openecomp.sdc.common.util.ValidationUtils;
51 import org.openecomp.sdc.exception.ResponseFormat;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.stereotype.Component;
55 import org.springframework.web.context.WebApplicationContext;
57 import fj.data.Either;
59 @Component("additionalInformationBusinessLogic")
60 public class AdditionalInformationBusinessLogic extends BaseBusinessLogic {
62 private static final String CREATE_ADDITIONAL_INFORMATION = "CreateAdditionalInformation";
64 private static final String UPDATE_ADDITIONAL_INFORMATION = "UpdateAdditionalInformation";
66 private static final String DELETE_ADDITIONAL_INFORMATION = "DeleteAdditionalInformation";
68 private static final String GET_ADDITIONAL_INFORMATION = "GetAdditionalInformation";
70 private static Logger log = LoggerFactory.getLogger(AdditionalInformationBusinessLogic.class.getName());
72 @javax.annotation.Resource
73 private IAdditionalInformationOperation additionalInformationOperation = null;
75 @javax.annotation.Resource
76 private IResourceOperation resourceOperation;
78 @javax.annotation.Resource
79 private IServiceOperation serviceOperation;
81 @javax.annotation.Resource
82 private IGraphLockOperation graphLockOperation;
84 @javax.annotation.Resource
85 private ComponentsUtils componentsUtils;
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
100 * @param newPropertyDefinition
102 * @return Either<PropertyDefinition, ActionStatus>
104 public Either<AdditionalInfoParameterInfo, ResponseFormat> createAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
106 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
107 if (resp.isRight()) {
108 return Either.right(resp.right().value());
110 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
112 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
113 if (responseFormat != null) {
114 result = Either.right(responseFormat);
119 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
120 if (!lockResult.equals(StorageOperationStatus.OK)) {
121 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, CREATE_ADDITIONAL_INFORMATION);
122 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
123 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
124 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
128 responseFormat = validateMaxSizeNotReached(nodeType, resourceId, additionalInfoParameterInfo);
129 if (responseFormat != null) {
130 result = Either.right(responseFormat);
135 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
136 if (responseFormat != null) {
137 result = Either.right(responseFormat);
142 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
143 if (responseFormat != null) {
144 result = Either.right(responseFormat);
148 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.createAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getKey(),
149 additionalInfoParameterInfo.getValue(), true);
151 if (addResult.isRight()) {
152 StorageOperationStatus status = addResult.right().value();
153 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, CREATE_ADDITIONAL_INFORMATION);
154 BeEcompErrorManager.getInstance().logBeSystemError(CREATE_ADDITIONAL_INFORMATION);
155 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
156 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.Label));
160 AdditionalInformationDefinition informationDefinition = addResult.left().value();
162 AdditionalInfoParameterInfo createdAI = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
163 result = Either.left(createdAI);
168 commitOrRollback(result);
170 graphLockOperation.unlockComponent(resourceId, nodeType);
176 * Validate the value format. Format the value.
178 * @param additionalInfoParameterInfo
179 * @return null in case of success. Otherwise response format.
181 private ResponseFormat validateAndConvertValue(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
182 ResponseFormat result = null;
184 String value = additionalInfoParameterInfo.getValue();
185 log.debug("Going to validate additional information value {}", value);
187 Either<String, ResponseFormat> valueValidRes = validateValue(value);
188 if (valueValidRes.isRight()) {
189 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeInvalidValueError, context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
190 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
191 result = valueValidRes.right().value();
193 String newValue = valueValidRes.left().value();
194 if (log.isTraceEnabled()) {
195 if (value != null && false == value.equals(newValue)) {
196 log.trace("The additional information value was normalized from {} to {}", value, newValue);
199 additionalInfoParameterInfo.setValue(newValue);
205 * @param additionalInfoParameterInfo
208 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
210 String key = additionalInfoParameterInfo.getKey();
211 log.debug("Going to validate additional information key {}", key);
213 ResponseFormat result = null;
214 ResponseFormat responseFormat;
215 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
216 if (validateKeyRes.isRight()) {
217 responseFormat = validateKeyRes.right().value();
218 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeInvalidValueError, context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
219 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
220 result = responseFormat;
223 String convertedKey = validateKeyRes.left().value();
225 if (log.isTraceEnabled()) {
226 if (key != null && false == key.equals(convertedKey)) {
227 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
230 additionalInfoParameterInfo.setKey(convertedKey);
236 * verify that the maximal number of additional information properties has not been reached.
240 * @param additionalInfoParameterInfo
241 * @return response format in case the maximal number has been reached.
243 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId, AdditionalInfoParameterInfo additionalInfoParameterInfo) {
245 ResponseFormat result;
246 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration().getAdditionalInformationMaxNumberOfKeys();
248 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation.getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
249 if (checkRes.isRight()) {
250 StorageOperationStatus status = checkRes.right().value();
252 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
253 result = componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
256 Integer currentNumberOfProperties = checkRes.left().value();
257 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
258 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}", currentNumberOfProperties, currentNumberOfProperties);
259 result = componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
267 * validate additional information value
272 private Either<String, ResponseFormat> validateValue(String value) {
274 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(value);
275 if (false == isNonEmptyString) {
276 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED));
279 boolean valid = StringValidator.getInstance().isValid(value, null);
280 if (false == valid) {
281 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS, new AdditionalInfoParameterInfo(null, value), null, AdditionalInformationEnum.Value));
284 String converted = StringConvertor.getInstance().convert(value, null, null);
286 return Either.left(converted);
289 private AdditionalInfoParameterInfo findAdditionInformationKey(List<AdditionalInfoParameterInfo> parameters, String key) {
291 for (AdditionalInfoParameterInfo infoParameterInfo : parameters) {
292 if (infoParameterInfo.getKey().equals(key)) {
293 return infoParameterInfo;
300 * validate and normalize the key
302 * @param additionalInfoParameterInfo
305 private Either<String, ResponseFormat> validateAndNormalizeKey(String key) {
307 AdditionalInfoParameterInfo additionalInfoParameterInfo = new AdditionalInfoParameterInfo();
308 additionalInfoParameterInfo.setKey(key);
310 key = ValidationUtils.normalizeAdditionalInformation(key);
311 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(key);
312 if (false == isNonEmptyString) {
313 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null, AdditionalInformationEnum.Label));
315 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(key);
316 if (false == isValidString) {
317 if (false == ValidationUtils.validateLength(key, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
318 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
320 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
323 return Either.left(key);
327 * update key and value of a given additional information.
331 * @param additionalInfoParameterInfo
332 * @param additionalInformationUid
337 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
339 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
340 if (resp.isRight()) {
341 return Either.right(resp.right().value());
343 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
345 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
346 if (responseFormat != null) {
347 result = Either.right(responseFormat);
351 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
352 if (!lockResult.equals(StorageOperationStatus.OK)) {
353 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, UPDATE_ADDITIONAL_INFORMATION);
354 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
355 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
356 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
362 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
363 if (responseFormat != null) {
364 result = Either.right(responseFormat);
368 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
369 if (responseFormat != null) {
370 result = Either.right(responseFormat);
374 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
375 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
377 if (addResult.isRight()) {
378 StorageOperationStatus status = addResult.right().value();
379 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, UPDATE_ADDITIONAL_INFORMATION);
380 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
381 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
382 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
385 AdditionalInformationDefinition informationDefinition = addResult.left().value();
386 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
387 result = Either.left(parameterInfo);
392 commitOrRollback(result);
394 graphLockOperation.unlockComponent(resourceId, nodeType);
400 * Delete an additional information label
404 * @param additionalInfoParameterInfo
405 * @param additionalInformationUid
406 * - Null. Future use.
410 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
412 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Additional Information", false);
413 if (resp.isRight()) {
414 return Either.right(resp.right().value());
416 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
418 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
419 if (responseFormat != null) {
420 return Either.right(responseFormat);
423 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
424 if (!lockResult.equals(StorageOperationStatus.OK)) {
425 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, DELETE_ADDITIONAL_INFORMATION);
426 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
427 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
428 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
434 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
435 if (findIdRes.isRight()) {
436 StorageOperationStatus status = findIdRes.right().value();
437 if (status != StorageOperationStatus.NOT_FOUND) {
438 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, GET_ADDITIONAL_INFORMATION);
439 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
441 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
442 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
446 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
448 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
450 if (addResult.isRight()) {
451 StorageOperationStatus status = addResult.right().value();
452 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, DELETE_ADDITIONAL_INFORMATION);
453 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
454 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
455 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
458 result = Either.left(foundAdditionalInfo);
463 commitOrRollback(result);
465 graphLockOperation.unlockComponent(resourceId, nodeType);
473 * @param additionalInfoParameterInfo
474 * @param additionalInformationUid
478 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
480 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Additional Information", false);
481 if (resp.isRight()) {
482 return Either.right(resp.right().value());
484 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
488 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
490 if (findIdRes.isRight()) {
491 StorageOperationStatus status = findIdRes.right().value();
492 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
493 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
496 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
498 result = Either.left(foundAdditionalInfo);
503 commitOrRollback(result);
509 * Get all additional information properties of a given resource/service
513 * @param additionalInformationUid
518 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId, String additionalInformationUid, String userId) {
520 Either<User, ResponseFormat> resp = validateUserExists(userId, "get All Additional Information", false);
521 if (resp.isRight()) {
522 return Either.right(resp.right().value());
525 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
529 Either<AdditionalInformationDefinition, TitanOperationStatus> findIdRes = additionalInformationOperation.getAllAdditionalInformationParameters(nodeType, resourceId, false);
530 if (findIdRes.isRight()) {
531 StorageOperationStatus status = DaoStatusConverter.convertTitanStatusToStorageStatus(findIdRes.right().value());
532 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
533 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
535 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
536 result = Either.left(informationDefinition);
542 commitOrRollback(result);
547 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
552 // verify that resource is checked-out and the user is the last
554 if (!ComponentValidationUtils.canWorkOnResource(resourceId, resourceOperation, userId)) {
555 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
560 // verify that resource is checked-out and the user is the last
562 if (!ComponentValidationUtils.canWorkOnService(resourceId, serviceOperation, userId)) {
563 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
567 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());