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.util.ValidationUtils;
48 import org.openecomp.sdc.exception.ResponseFormat;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51 import org.springframework.stereotype.Component;
52 import org.springframework.web.context.WebApplicationContext;
54 import fj.data.Either;
56 @Component("additionalInformationBusinessLogic")
57 public class AdditionalInformationBusinessLogic extends BaseBusinessLogic {
59 private static final String CREATE_ADDITIONAL_INFORMATION = "CreateAdditionalInformation";
61 private static final String UPDATE_ADDITIONAL_INFORMATION = "UpdateAdditionalInformation";
63 private static final String DELETE_ADDITIONAL_INFORMATION = "DeleteAdditionalInformation";
65 private static final String GET_ADDITIONAL_INFORMATION = "GetAdditionalInformation";
67 private static final Logger log = LoggerFactory.getLogger(AdditionalInformationBusinessLogic.class);
69 @javax.annotation.Resource
70 private IAdditionalInformationOperation additionalInformationOperation = null;
72 @javax.annotation.Resource
73 private IGraphLockOperation graphLockOperation;
75 @javax.annotation.Resource
76 private ComponentsUtils componentsUtils;
78 protected static IElementOperation getElementDao(Class<IElementOperation> class1, ServletContext context) {
79 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
81 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
83 return webApplicationContext.getBean(class1);
87 * Create new additional information on resource/service on graph
91 * @param newPropertyDefinition
93 * @return Either<PropertyDefinition, ActionStatus>
95 public Either<AdditionalInfoParameterInfo, ResponseFormat> createAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
97 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
99 return Either.right(resp.right().value());
101 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
103 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
104 if (responseFormat != null) {
105 result = Either.right(responseFormat);
110 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
111 if (!lockResult.equals(StorageOperationStatus.OK)) {
112 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
113 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
114 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
118 responseFormat = validateMaxSizeNotReached(nodeType, resourceId, additionalInfoParameterInfo);
119 if (responseFormat != null) {
120 result = Either.right(responseFormat);
125 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
126 if (responseFormat != null) {
127 result = Either.right(responseFormat);
132 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
133 if (responseFormat != null) {
134 result = Either.right(responseFormat);
138 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.createAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getKey(),
139 additionalInfoParameterInfo.getValue(), true);
141 if (addResult.isRight()) {
142 StorageOperationStatus status = addResult.right().value();
143 BeEcompErrorManager.getInstance().logBeSystemError(CREATE_ADDITIONAL_INFORMATION);
144 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
145 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.Label));
149 AdditionalInformationDefinition informationDefinition = addResult.left().value();
151 AdditionalInfoParameterInfo createdAI = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
152 result = Either.left(createdAI);
157 commitOrRollback(result);
159 graphLockOperation.unlockComponent(resourceId, nodeType);
165 * Validate the value format. Format the value.
167 * @param additionalInfoParameterInfo
168 * @return null in case of success. Otherwise response format.
170 private ResponseFormat validateAndConvertValue(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
171 ResponseFormat result = null;
173 String value = additionalInfoParameterInfo.getValue();
174 log.debug("Going to validate additional information value {}", value);
176 Either<String, ResponseFormat> valueValidRes = validateValue(value);
177 if (valueValidRes.isRight()) {
178 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
179 result = valueValidRes.right().value();
181 String newValue = valueValidRes.left().value();
182 if (log.isTraceEnabled()) {
183 if (value != null && false == value.equals(newValue)) {
184 log.trace("The additional information value was normalized from {} to {}", value, newValue);
187 additionalInfoParameterInfo.setValue(newValue);
193 * @param additionalInfoParameterInfo
196 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
198 String key = additionalInfoParameterInfo.getKey();
199 log.debug("Going to validate additional information key {}", key);
201 ResponseFormat result = null;
202 ResponseFormat responseFormat;
203 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
204 if (validateKeyRes.isRight()) {
205 responseFormat = validateKeyRes.right().value();
206 BeEcompErrorManager.getInstance().logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
207 result = responseFormat;
210 String convertedKey = validateKeyRes.left().value();
212 if (log.isTraceEnabled()) {
213 if (key != null && false == key.equals(convertedKey)) {
214 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
217 additionalInfoParameterInfo.setKey(convertedKey);
223 * verify that the maximal number of additional information properties has not been reached.
227 * @param additionalInfoParameterInfo
228 * @return response format in case the maximal number has been reached.
230 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId, AdditionalInfoParameterInfo additionalInfoParameterInfo) {
232 ResponseFormat result;
233 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration().getAdditionalInformationMaxNumberOfKeys();
235 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation.getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
236 if (checkRes.isRight()) {
237 StorageOperationStatus status = checkRes.right().value();
239 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
240 result = componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
243 Integer currentNumberOfProperties = checkRes.left().value();
244 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
245 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}", currentNumberOfProperties, currentNumberOfProperties);
246 result = componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
254 * validate additional information value
259 private Either<String, ResponseFormat> validateValue(String value) {
261 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(value);
262 if (false == isNonEmptyString) {
263 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED));
266 boolean valid = StringValidator.getInstance().isValid(value, null);
267 if (false == valid) {
268 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS, new AdditionalInfoParameterInfo(null, value), null, AdditionalInformationEnum.Value));
271 String converted = StringConvertor.getInstance().convert(value, null, null);
273 return Either.left(converted);
276 private AdditionalInfoParameterInfo findAdditionInformationKey(List<AdditionalInfoParameterInfo> parameters, String key) {
278 for (AdditionalInfoParameterInfo infoParameterInfo : parameters) {
279 if (infoParameterInfo.getKey().equals(key)) {
280 return infoParameterInfo;
287 * validate and normalize the key
289 * @param additionalInfoParameterInfo
292 private Either<String, ResponseFormat> validateAndNormalizeKey(String key) {
294 AdditionalInfoParameterInfo additionalInfoParameterInfo = new AdditionalInfoParameterInfo();
295 additionalInfoParameterInfo.setKey(key);
297 key = ValidationUtils.normalizeAdditionalInformation(key);
298 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(key);
299 if (false == isNonEmptyString) {
300 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null, AdditionalInformationEnum.Label));
302 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(key);
303 if (false == isValidString) {
304 if (false == ValidationUtils.validateLength(key, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
305 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
307 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo, null, AdditionalInformationEnum.Label));
310 return Either.left(key);
314 * update key and value of a given additional information.
318 * @param additionalInfoParameterInfo
319 * @param additionalInformationUid
324 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
326 Either<User, ResponseFormat> resp = validateUserExists(userId, "create Additional Information", false);
327 if (resp.isRight()) {
328 return Either.right(resp.right().value());
330 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
332 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
333 if (responseFormat != null) {
334 result = Either.right(responseFormat);
338 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
339 if (!lockResult.equals(StorageOperationStatus.OK)) {
340 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
341 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
342 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
348 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
349 if (responseFormat != null) {
350 result = Either.right(responseFormat);
354 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
355 if (responseFormat != null) {
356 result = Either.right(responseFormat);
360 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
361 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
363 if (addResult.isRight()) {
364 StorageOperationStatus status = addResult.right().value();
365 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
366 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
367 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
370 AdditionalInformationDefinition informationDefinition = addResult.left().value();
371 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(), additionalInfoParameterInfo.getKey());
372 result = Either.left(parameterInfo);
377 commitOrRollback(result);
379 graphLockOperation.unlockComponent(resourceId, nodeType);
385 * Delete an additional information label
389 * @param additionalInfoParameterInfo
390 * @param additionalInformationUid
391 * - Null. Future use.
395 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
397 Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Additional Information", false);
398 if (resp.isRight()) {
399 return Either.right(resp.right().value());
401 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
403 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
404 if (responseFormat != null) {
405 return Either.right(responseFormat);
408 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
409 if (!lockResult.equals(StorageOperationStatus.OK)) {
410 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
411 log.info("Failed to lock component {} error - {}", resourceId, lockResult);
412 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
418 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
419 if (findIdRes.isRight()) {
420 StorageOperationStatus status = findIdRes.right().value();
421 if (status != StorageOperationStatus.NOT_FOUND) {
422 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
424 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
425 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
429 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
431 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation.deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
433 if (addResult.isRight()) {
434 StorageOperationStatus status = addResult.right().value();
435 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
436 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
437 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
440 result = Either.left(foundAdditionalInfo);
445 commitOrRollback(result);
447 graphLockOperation.unlockComponent(resourceId, nodeType);
455 * @param additionalInfoParameterInfo
456 * @param additionalInformationUid
460 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId, AdditionalInfoParameterInfo additionalInfoParameterInfo, String additionalInformationUid, String userId) {
462 Either<User, ResponseFormat> resp = validateUserExists(userId, "get Additional Information", false);
463 if (resp.isRight()) {
464 return Either.right(resp.right().value());
466 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
470 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation.getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
472 if (findIdRes.isRight()) {
473 StorageOperationStatus status = findIdRes.right().value();
474 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
475 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
478 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
480 result = Either.left(foundAdditionalInfo);
485 commitOrRollback(result);
491 * Get all additional information properties of a given resource/service
495 * @param additionalInformationUid
500 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId, String additionalInformationUid, String userId) {
502 Either<User, ResponseFormat> resp = validateUserExists(userId, "get All Additional Information", false);
503 if (resp.isRight()) {
504 return Either.right(resp.right().value());
507 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
511 Either<AdditionalInformationDefinition, TitanOperationStatus> findIdRes = additionalInformationOperation.getAllAdditionalInformationParameters(nodeType, resourceId, false);
512 if (findIdRes.isRight()) {
513 StorageOperationStatus status = DaoStatusConverter.convertTitanStatusToStorageStatus(findIdRes.right().value());
514 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
515 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
517 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
518 result = Either.left(informationDefinition);
524 commitOrRollback(result);
529 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
534 // verify that resource is checked-out and the user is the last
536 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
537 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
542 // verify that resource is checked-out and the user is the last
544 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
545 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
549 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());