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.titan.TitanOperationStatus;
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.ComponentsUtils;
32 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
33 import org.openecomp.sdc.be.model.AdditionalInformationDefinition;
34 import org.openecomp.sdc.be.model.User;
35 import org.openecomp.sdc.be.model.operations.api.IAdditionalInformationOperation;
36 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
37 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
38 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
39 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
40 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
41 import org.openecomp.sdc.be.model.tosca.converters.StringConvertor;
42 import org.openecomp.sdc.be.model.tosca.validators.StringValidator;
43 import org.openecomp.sdc.common.api.Constants;
44 import org.openecomp.sdc.common.config.EcompErrorName;
45 import org.openecomp.sdc.common.util.ValidationUtils;
46 import org.openecomp.sdc.exception.ResponseFormat;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.stereotype.Component;
50 import org.springframework.web.context.WebApplicationContext;
52 import javax.servlet.ServletContext;
53 import java.util.List;
55 @Component("additionalInformationBusinessLogic")
56 public class AdditionalInformationBusinessLogic extends BaseBusinessLogic {
58 private static final String CREATE_ADDITIONAL_INFORMATION = "CreateAdditionalInformation";
60 private static final String UPDATE_ADDITIONAL_INFORMATION = "UpdateAdditionalInformation";
62 private static final String DELETE_ADDITIONAL_INFORMATION = "DeleteAdditionalInformation";
64 private static final String GET_ADDITIONAL_INFORMATION = "GetAdditionalInformation";
66 private static final Logger log = LoggerFactory.getLogger(AdditionalInformationBusinessLogic.class);
68 @javax.annotation.Resource
69 private IAdditionalInformationOperation additionalInformationOperation = null;
71 @javax.annotation.Resource
72 private IGraphLockOperation graphLockOperation;
74 @javax.annotation.Resource
75 private ComponentsUtils componentsUtils;
77 protected static IElementOperation getElementDao(Class<IElementOperation> class1, ServletContext context) {
78 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
80 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
82 return webApplicationContext.getBean(class1);
86 * Create new additional information on resource/service on graph
90 * @param newPropertyDefinition
92 * @return Either<PropertyDefinition, ActionStatus>
94 public Either<AdditionalInfoParameterInfo, ResponseFormat> createAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
96 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
98 return Either.right(resp.right().value());
100 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
102 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
103 if (responseFormat != null) {
104 result = Either.right(responseFormat);
109 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
110 if (!lockResult.equals(StorageOperationStatus.OK)) {
111 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
112 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
113 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
117 responseFormat = validateMaxSizeNotReached(nodeType, resourceId, additionalInfoParameterInfo);
118 if (responseFormat != null) {
119 result = Either.right(responseFormat);
124 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
125 if (responseFormat != null) {
126 result = Either.right(responseFormat);
131 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
132 if (responseFormat != null) {
133 result = Either.right(responseFormat);
137 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.createAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getKey(),
138 additionalInfoParameterInfo.getValue(), true);
140 if (addResult.isRight()) {
141 StorageOperationStatus status = addResult.right().value();
142 BeEcompErrorManager.getInstance().logBeSystemError(CREATE_ADDITIONAL_INFORMATION);
143 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
144 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.Label));
148 AdditionalInformationDefinition informationDefinition = addResult.left().value();
150 AdditionalInfoParameterInfo createdAI = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
151 result = Either.left(createdAI);
156 commitOrRollback(result);
158 graphLockOperation.unlockComponent(resourceId, nodeType);
164 * Validate the value format. Format the value.
166 * @param additionalInfoParameterInfo
167 * @return null in case of success. Otherwise response format.
169 private ResponseFormat validateAndConvertValue(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
170 ResponseFormat result = null;
172 String value = additionalInfoParameterInfo.getValue();
173 log.debug("Going to validate additional information value {}", value);
175 Either<String, ResponseFormat> valueValidRes = validateValue(value);
176 if (valueValidRes.isRight()) {
177 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
178 result = valueValidRes.right().value();
180 String newValue = valueValidRes.left().value();
181 if (log.isTraceEnabled()) {
182 if (value != null && false == value.equals(newValue)) {
183 log.trace("The additional information value was normalized from {} to {}", value, newValue);
186 additionalInfoParameterInfo.setValue(newValue);
192 * @param additionalInfoParameterInfo
195 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
197 String key = additionalInfoParameterInfo.getKey();
198 log.debug("Going to validate additional information key {}", key);
200 ResponseFormat result = null;
201 ResponseFormat responseFormat;
202 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
203 if (validateKeyRes.isRight()) {
204 responseFormat = validateKeyRes.right().value();
205 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
206 result = responseFormat;
209 String convertedKey = validateKeyRes.left().value();
211 if (log.isTraceEnabled()) {
212 if (key != null && false == key.equals(convertedKey)) {
213 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
216 additionalInfoParameterInfo.setKey(convertedKey);
222 * verify that the maximal number of additional information properties has not been reached.
226 * @param additionalInfoParameterInfo
227 * @return response format in case the maximal number has been reached.
229 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId, AdditionalInfoParameterInfo additionalInfoParameterInfo) {
231 ResponseFormat result;
232 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration().getAdditionalInformationMaxNumberOfKeys();
234 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation.getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
235 if (checkRes.isRight()) {
236 StorageOperationStatus status = checkRes.right().value();
238 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
239 result = componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
242 Integer currentNumberOfProperties = checkRes.left().value();
243 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
244 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}", currentNumberOfProperties, currentNumberOfProperties);
245 result = componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
253 * validate additional information value
258 private Either<String, ResponseFormat> validateValue(String value) {
260 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(value);
261 if (false == isNonEmptyString) {
262 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED));
265 boolean valid = StringValidator.getInstance().isValid(value, null);
266 if (false == valid) {
267 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS, new AdditionalInfoParameterInfo(null, value), null, AdditionalInformationEnum.Value));
270 String converted = StringConvertor.getInstance().convert(value, null, null);
272 return Either.left(converted);
275 private AdditionalInfoParameterInfo findAdditionInformationKey(List<AdditionalInfoParameterInfo> parameters, String key) {
277 for (AdditionalInfoParameterInfo infoParameterInfo : parameters) {
278 if (infoParameterInfo.getKey().equals(key)) {
279 return infoParameterInfo;
286 * validate and normalize the key
288 * @param additionalInfoParameterInfo
291 private Either<String, ResponseFormat> validateAndNormalizeKey(String key) {
293 AdditionalInfoParameterInfo additionalInfoParameterInfo = new AdditionalInfoParameterInfo();
294 additionalInfoParameterInfo.setKey(key);
296 key = ValidationUtils.normalizeAdditionalInformation(key);
297 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(key);
298 if (false == isNonEmptyString) {
299 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null, AdditionalInformationEnum.Label));
301 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(key);
302 if (false == isValidString) {
303 if (false == ValidationUtils.validateLength(key, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
304 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
306 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
309 return Either.left(key);
313 * update key and value of a given additional information.
317 * @param additionalInfoParameterInfo
318 * @param additionalInformationUid
323 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
325 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
326 if (resp.isRight()) {
327 return Either.right(resp.right().value());
329 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
331 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
332 if (responseFormat != null) {
333 result = Either.right(responseFormat);
337 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
338 if (!lockResult.equals(StorageOperationStatus.OK)) {
339 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
340 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
341 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
347 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
348 if (responseFormat != null) {
349 result = Either.right(responseFormat);
353 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
354 if (responseFormat != null) {
355 result = Either.right(responseFormat);
359 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
360 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
362 if (addResult.isRight()) {
363 StorageOperationStatus status = addResult.right().value();
364 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
365 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
366 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
369 AdditionalInformationDefinition informationDefinition = addResult.left().value();
370 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
371 result = Either.left(parameterInfo);
376 commitOrRollback(result);
378 graphLockOperation.unlockComponent(resourceId, nodeType);
384 * Delete an additional information label
388 * @param additionalInfoParameterInfo
389 * @param additionalInformationUid
390 * - Null. Future use.
394 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
396 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Additional Information", false);
397 if (resp.isRight()) {
398 return Either.right(resp.right().value());
400 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
402 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
403 if (responseFormat != null) {
404 return Either.right(responseFormat);
407 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
408 if (!lockResult.equals(StorageOperationStatus.OK)) {
409 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
410 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
411 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
417 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
418 if (findIdRes.isRight()) {
419 StorageOperationStatus status = findIdRes.right().value();
420 if (status != StorageOperationStatus.NOT_FOUND) {
421 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
423 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
424 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
428 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
430 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
432 if (addResult.isRight()) {
433 StorageOperationStatus status = addResult.right().value();
434 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
435 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
436 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
439 result = Either.left(foundAdditionalInfo);
444 commitOrRollback(result);
446 graphLockOperation.unlockComponent(resourceId, nodeType);
454 * @param additionalInfoParameterInfo
455 * @param additionalInformationUid
459 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
461 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Additional Information", false);
462 if (resp.isRight()) {
463 return Either.right(resp.right().value());
465 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
469 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
471 if (findIdRes.isRight()) {
472 StorageOperationStatus status = findIdRes.right().value();
473 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
474 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
477 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
479 result = Either.left(foundAdditionalInfo);
484 commitOrRollback(result);
490 * Get all additional information properties of a given resource/service
494 * @param additionalInformationUid
499 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId, String additionalInformationUid, String userId) {
501 Either<User, ResponseFormat> resp = validateUserExists(userId, "get All Additional Information", false);
502 if (resp.isRight()) {
503 return Either.right(resp.right().value());
506 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
510 Either<AdditionalInformationDefinition, TitanOperationStatus> findIdRes = additionalInformationOperation.getAllAdditionalInformationParameters(nodeType, resourceId, false);
511 if (findIdRes.isRight()) {
512 StorageOperationStatus status = DaoStatusConverter.convertTitanStatusToStorageStatus(findIdRes.right().value());
513 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
514 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
516 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
517 result = Either.left(informationDefinition);
523 commitOrRollback(result);
528 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
533 // verify that resource is checked-out and the user is the last
535 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
536 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
541 // verify that resource is checked-out and the user is the last
543 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
544 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
548 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());