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=========================================================
20 package org.openecomp.sdc.be.components.impl;
22 import fj.data.Either;
23 import java.util.List;
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.model.AdditionalInformationDefinition;
32 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
33 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
34 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
35 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
36 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
37 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
38 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
39 import org.openecomp.sdc.be.model.operations.impl.AdditionalInformationOperation;
40 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
41 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
42 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
43 import org.openecomp.sdc.be.model.tosca.converters.StringConvertor;
44 import org.openecomp.sdc.be.model.tosca.validators.StringValidator;
45 import org.openecomp.sdc.common.log.wrappers.Logger;
46 import org.openecomp.sdc.common.util.ValidationUtils;
47 import org.openecomp.sdc.exception.ResponseFormat;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.stereotype.Component;
51 @Component("additionalInformationBusinessLogic")
52 public class AdditionalInformationBusinessLogic extends BaseBusinessLogic {
54 private static final String CREATE_ADDITIONAL_INFORMATION = "CreateAdditionalInformation";
55 private static final String UPDATE_ADDITIONAL_INFORMATION = "UpdateAdditionalInformation";
56 private static final String DELETE_ADDITIONAL_INFORMATION = "DeleteAdditionalInformation";
57 private static final String GET_ADDITIONAL_INFORMATION = "GetAdditionalInformation";
58 private static final Logger log = Logger.getLogger(AdditionalInformationBusinessLogic.class.getName());
59 private static final String FAILED_TO_LOCK_COMPONENT_ERROR = "Failed to lock component {} error - {}";
60 private final AdditionalInformationOperation additionalInformationOperation;
63 public AdditionalInformationBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation,
64 IGroupInstanceOperation groupInstanceOperation, IGroupTypeOperation groupTypeOperation,
65 InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
66 AdditionalInformationOperation additionalInformationOperation,
67 ArtifactsOperations artifactToscaOperation) {
68 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
69 artifactToscaOperation);
70 this.additionalInformationOperation = additionalInformationOperation;
74 * Create new additional information on resource/service on graph
78 * @param additionalInfoParameterInfo
80 * @return Either<AdditionalInfoParameterInfo, ResponseFormat>
82 public Either<AdditionalInfoParameterInfo, ResponseFormat> createAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
83 AdditionalInfoParameterInfo additionalInfoParameterInfo,
85 validateUserExists(userId);
86 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
87 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
88 if (responseFormat != null) {
89 result = Either.right(responseFormat);
93 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
94 if (lockResult != StorageOperationStatus.OK) {
95 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
96 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
97 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
101 responseFormat = validateMaxSizeNotReached(nodeType, resourceId, additionalInfoParameterInfo);
102 if (responseFormat != null) {
103 result = Either.right(responseFormat);
107 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
108 if (responseFormat != null) {
109 result = Either.right(responseFormat);
113 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
114 if (responseFormat != null) {
115 result = Either.right(responseFormat);
118 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
119 .createAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getKey(),
120 additionalInfoParameterInfo.getValue(), true);
121 if (addResult.isRight()) {
122 StorageOperationStatus status = addResult.right().value();
123 BeEcompErrorManager.getInstance().logBeSystemError(CREATE_ADDITIONAL_INFORMATION);
124 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
125 result = Either.right(componentsUtils
126 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.Label));
129 AdditionalInformationDefinition informationDefinition = addResult.left().value();
130 AdditionalInfoParameterInfo createdAI = findAdditionInformationKey(informationDefinition.getParameters(),
131 additionalInfoParameterInfo.getKey());
132 result = Either.left(createdAI);
136 commitOrRollback(result);
138 graphLockOperation.unlockComponent(resourceId, nodeType);
143 * Validate the value format. Format the value.
145 * @param additionalInfoParameterInfo
146 * @return null in case of success. Otherwise response format.
148 private ResponseFormat validateAndConvertValue(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
149 ResponseFormat result = null;
150 String value = additionalInfoParameterInfo.getValue();
151 log.debug("Going to validate additional information value {}", value);
152 Either<String, ResponseFormat> valueValidRes = validateValue(value);
153 if (valueValidRes.isRight()) {
154 BeEcompErrorManager.getInstance()
155 .logBeInvalidValueError(context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
156 result = valueValidRes.right().value();
158 String newValue = valueValidRes.left().value();
159 if (log.isTraceEnabled() && (value != null && !value.equals(newValue))) {
160 log.trace("The additional information value was normalized from {} to {}", value, newValue);
162 additionalInfoParameterInfo.setValue(newValue);
168 * @param additionalInfoParameterInfo
171 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
172 String key = additionalInfoParameterInfo.getKey();
173 log.debug("Going to validate additional information key {}", key);
174 ResponseFormat result = null;
175 ResponseFormat responseFormat;
176 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
177 if (validateKeyRes.isRight()) {
178 responseFormat = validateKeyRes.right().value();
179 BeEcompErrorManager.getInstance()
180 .logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
181 result = responseFormat;
183 String convertedKey = validateKeyRes.left().value();
184 if (log.isTraceEnabled() && key != null && !key.equals(convertedKey)) {
185 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
187 additionalInfoParameterInfo.setKey(convertedKey);
193 * verify that the maximal number of additional information properties has not been reached.
197 * @param additionalInfoParameterInfo
198 * @return response format in case the maximal number has been reached.
200 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId,
201 AdditionalInfoParameterInfo additionalInfoParameterInfo) {
202 ResponseFormat result;
203 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration()
204 .getAdditionalInformationMaxNumberOfKeys();
205 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation
206 .getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
207 if (checkRes.isRight()) {
208 StorageOperationStatus status = checkRes.right().value();
209 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
210 result = componentsUtils
211 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
214 Integer currentNumberOfProperties = checkRes.left().value();
215 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
216 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}",
217 currentNumberOfProperties, currentNumberOfProperties);
218 result = componentsUtils
219 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType,
220 AdditionalInformationEnum.None);
227 * validate additional information value
232 private Either<String, ResponseFormat> validateValue(String value) {
233 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(value);
234 if (!isNonEmptyString) {
235 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED));
237 boolean valid = StringValidator.getInstance().isValid(value, null);
239 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS,
240 new AdditionalInfoParameterInfo(null, value), null, AdditionalInformationEnum.Value));
242 String converted = StringConvertor.getInstance().convert(value, null, null);
243 return Either.left(converted);
246 private AdditionalInfoParameterInfo findAdditionInformationKey(List<AdditionalInfoParameterInfo> parameters, String key) {
247 for (AdditionalInfoParameterInfo infoParameterInfo : parameters) {
248 if (infoParameterInfo.getKey().equals(key)) {
249 return infoParameterInfo;
256 * validate and normalize the key
259 * @return Either<String, ResponseFormat>
261 private Either<String, ResponseFormat> validateAndNormalizeKey(String key) {
262 AdditionalInfoParameterInfo additionalInfoParameterInfo = new AdditionalInfoParameterInfo();
263 additionalInfoParameterInfo.setKey(key);
264 String normKey = ValidationUtils.normalizeAdditionalInformation(key);
265 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(normKey);
266 if (!isNonEmptyString) {
267 return Either.right(componentsUtils
268 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null,
269 AdditionalInformationEnum.Label));
271 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(normKey);
272 if (!isValidString) {
273 if (!ValidationUtils.validateLength(normKey, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
274 return Either.right(componentsUtils
275 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null,
276 AdditionalInformationEnum.Label));
278 return Either.right(componentsUtils
279 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo,
280 null, AdditionalInformationEnum.Label));
282 return Either.left(normKey);
286 * update key and value of a given additional information.
290 * @param additionalInfoParameterInfo
294 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
295 AdditionalInfoParameterInfo additionalInfoParameterInfo,
297 validateUserExists(userId);
298 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
299 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
300 if (responseFormat != null) {
301 result = Either.right(responseFormat);
305 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
306 if (lockResult != StorageOperationStatus.OK) {
307 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
308 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
309 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
314 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
315 if (responseFormat != null) {
316 result = Either.right(responseFormat);
319 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
320 if (responseFormat != null) {
321 result = Either.right(responseFormat);
324 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
325 .updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
326 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
327 if (addResult.isRight()) {
328 StorageOperationStatus status = addResult.right().value();
329 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
330 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
331 result = Either.right(componentsUtils
332 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
335 AdditionalInformationDefinition informationDefinition = addResult.left().value();
336 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(),
337 additionalInfoParameterInfo.getKey());
338 result = Either.left(parameterInfo);
342 commitOrRollback(result);
344 graphLockOperation.unlockComponent(resourceId, nodeType);
349 * Delete an additional information label
353 * @param additionalInfoParameterInfo
357 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
358 AdditionalInfoParameterInfo additionalInfoParameterInfo,
360 validateUserExists(userId);
361 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
362 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
363 if (responseFormat != null) {
364 return Either.right(responseFormat);
367 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
368 if (lockResult != StorageOperationStatus.OK) {
369 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
370 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
371 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
375 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation
376 .getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
377 if (findIdRes.isRight()) {
378 StorageOperationStatus status = findIdRes.right().value();
379 if (status != StorageOperationStatus.NOT_FOUND) {
380 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
382 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
383 result = Either.right(componentsUtils
384 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
387 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
388 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
389 .deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
390 if (addResult.isRight()) {
391 StorageOperationStatus status = addResult.right().value();
392 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
393 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
394 result = Either.right(componentsUtils
395 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
398 result = Either.left(foundAdditionalInfo);
402 commitOrRollback(result);
404 graphLockOperation.unlockComponent(resourceId, nodeType);
411 * @param additionalInfoParameterInfo
415 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
416 AdditionalInfoParameterInfo additionalInfoParameterInfo,
418 validateUserExists(userId);
419 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
421 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation
422 .getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
423 if (findIdRes.isRight()) {
424 StorageOperationStatus status = findIdRes.right().value();
425 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
426 result = Either.right(componentsUtils
427 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
429 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
430 result = Either.left(foundAdditionalInfo);
433 commitOrRollback(result);
438 * Get all additional information properties of a given resource/service
445 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
447 validateUserExists(userId);
448 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
450 Either<AdditionalInformationDefinition, JanusGraphOperationStatus> findIdRes = additionalInformationOperation
451 .getAllAdditionalInformationParameters(nodeType, resourceId, false);
452 if (findIdRes.isRight()) {
453 StorageOperationStatus status = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(findIdRes.right().value());
454 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
455 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
457 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
458 result = Either.left(informationDefinition);
462 commitOrRollback(result);
466 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
469 // verify that resource is checked-out and the user is the last
472 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
473 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
477 // verify that resource is checked-out and the user is the last
480 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
481 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
485 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());