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.apache.commons.lang3.StringUtils;
25 import org.openecomp.sdc.be.config.BeEcompErrorManager;
26 import org.openecomp.sdc.be.config.ConfigurationManager;
27 import org.openecomp.sdc.be.dao.api.ActionStatus;
28 import org.openecomp.sdc.be.dao.graph.datatype.AdditionalInformationEnum;
29 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
30 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterInfo;
31 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
32 import org.openecomp.sdc.be.model.AdditionalInformationDefinition;
33 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
34 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
35 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
36 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
37 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
38 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
39 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
40 import org.openecomp.sdc.be.model.operations.impl.AdditionalInformationOperation;
41 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
42 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
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.log.wrappers.Logger;
47 import org.openecomp.sdc.common.util.ValidationUtils;
48 import org.openecomp.sdc.exception.ResponseFormat;
49 import org.springframework.beans.factory.annotation.Autowired;
50 import org.springframework.stereotype.Component;
52 @Component("additionalInformationBusinessLogic")
53 public class AdditionalInformationBusinessLogic extends BaseBusinessLogic {
55 private static final String CREATE_ADDITIONAL_INFORMATION = "CreateAdditionalInformation";
56 private static final String UPDATE_ADDITIONAL_INFORMATION = "UpdateAdditionalInformation";
57 private static final String DELETE_ADDITIONAL_INFORMATION = "DeleteAdditionalInformation";
58 private static final String GET_ADDITIONAL_INFORMATION = "GetAdditionalInformation";
59 private static final Logger log = Logger.getLogger(AdditionalInformationBusinessLogic.class.getName());
60 private static final String FAILED_TO_LOCK_COMPONENT_ERROR = "Failed to lock component {} error - {}";
61 private final AdditionalInformationOperation additionalInformationOperation;
64 public AdditionalInformationBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation,
65 IGroupInstanceOperation groupInstanceOperation, IGroupTypeOperation groupTypeOperation,
66 InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
67 AdditionalInformationOperation additionalInformationOperation,
68 ArtifactsOperations artifactToscaOperation) {
69 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
70 artifactToscaOperation);
71 this.additionalInformationOperation = additionalInformationOperation;
75 * Create new additional information on resource/service on graph
79 * @param additionalInfoParameterInfo
81 * @return Either<AdditionalInfoParameterInfo, ResponseFormat>
83 public Either<AdditionalInfoParameterInfo, ResponseFormat> createAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
84 AdditionalInfoParameterInfo additionalInfoParameterInfo,
86 validateUserExists(userId);
87 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
88 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
89 if (responseFormat != null) {
90 result = Either.right(responseFormat);
94 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
95 if (lockResult != StorageOperationStatus.OK) {
96 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
97 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
98 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
102 responseFormat = validateMaxSizeNotReached(nodeType, resourceId, additionalInfoParameterInfo);
103 if (responseFormat != null) {
104 result = Either.right(responseFormat);
108 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
109 if (responseFormat != null) {
110 result = Either.right(responseFormat);
114 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, CREATE_ADDITIONAL_INFORMATION);
115 if (responseFormat != null) {
116 result = Either.right(responseFormat);
119 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
120 .createAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getKey(),
121 additionalInfoParameterInfo.getValue(), true);
122 if (addResult.isRight()) {
123 StorageOperationStatus status = addResult.right().value();
124 BeEcompErrorManager.getInstance().logBeSystemError(CREATE_ADDITIONAL_INFORMATION);
125 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
126 result = Either.right(componentsUtils
127 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.Label));
130 AdditionalInformationDefinition informationDefinition = addResult.left().value();
131 AdditionalInfoParameterInfo createdAI = findAdditionInformationKey(informationDefinition.getParameters(),
132 additionalInfoParameterInfo.getKey());
133 result = Either.left(createdAI);
137 commitOrRollback(result);
139 graphLockOperation.unlockComponent(resourceId, nodeType);
144 * Validate the value format. Format the value.
146 * @param additionalInfoParameterInfo
147 * @return null in case of success. Otherwise response format.
149 private ResponseFormat validateAndConvertValue(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
150 ResponseFormat result = null;
151 String value = additionalInfoParameterInfo.getValue();
152 log.debug("Going to validate additional information value {}", value);
153 Either<String, ResponseFormat> valueValidRes = validateValue(value);
154 if (valueValidRes.isRight()) {
155 BeEcompErrorManager.getInstance()
156 .logBeInvalidValueError(context, additionalInfoParameterInfo.getValue(), "additional information value", "string");
157 result = valueValidRes.right().value();
159 String newValue = valueValidRes.left().value();
160 if (log.isTraceEnabled() && (value != null && !value.equals(newValue))) {
161 log.trace("The additional information value was normalized from {} to {}", value, newValue);
163 additionalInfoParameterInfo.setValue(newValue);
169 * @param additionalInfoParameterInfo
172 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
173 String key = additionalInfoParameterInfo.getKey();
174 log.debug("Going to validate additional information key {}", key);
175 ResponseFormat result = null;
176 ResponseFormat responseFormat;
177 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
178 if (validateKeyRes.isRight()) {
179 responseFormat = validateKeyRes.right().value();
180 BeEcompErrorManager.getInstance()
181 .logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
182 result = responseFormat;
184 String convertedKey = validateKeyRes.left().value();
185 if (log.isTraceEnabled() && key != null && !key.equals(convertedKey)) {
186 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
188 additionalInfoParameterInfo.setKey(convertedKey);
194 * verify that the maximal number of additional information properties has not been reached.
198 * @param additionalInfoParameterInfo
199 * @return response format in case the maximal number has been reached.
201 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId,
202 AdditionalInfoParameterInfo additionalInfoParameterInfo) {
203 ResponseFormat result;
204 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration()
205 .getAdditionalInformationMaxNumberOfKeys();
206 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation
207 .getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
208 if (checkRes.isRight()) {
209 StorageOperationStatus status = checkRes.right().value();
210 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
211 result = componentsUtils
212 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
215 Integer currentNumberOfProperties = checkRes.left().value();
216 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
217 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}",
218 currentNumberOfProperties, currentNumberOfProperties);
219 result = componentsUtils
220 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType,
221 AdditionalInformationEnum.None);
228 * validate additional information value
233 private Either<String, ResponseFormat> validateValue(String value) {
234 if (StringUtils.isEmpty(value)) {
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 if (StringUtils.isEmpty(normKey)) {
266 return Either.right(componentsUtils
267 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null,
268 AdditionalInformationEnum.Label));
270 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(normKey);
271 if (!isValidString) {
272 if (!ValidationUtils.validateLength(normKey, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
273 return Either.right(componentsUtils
274 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null,
275 AdditionalInformationEnum.Label));
277 return Either.right(componentsUtils
278 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo,
279 null, AdditionalInformationEnum.Label));
281 return Either.left(normKey);
285 * update key and value of a given additional information.
289 * @param additionalInfoParameterInfo
293 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
294 AdditionalInfoParameterInfo additionalInfoParameterInfo,
296 validateUserExists(userId);
297 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
298 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
299 if (responseFormat != null) {
300 result = Either.right(responseFormat);
304 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
305 if (lockResult != StorageOperationStatus.OK) {
306 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
307 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
308 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
313 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
314 if (responseFormat != null) {
315 result = Either.right(responseFormat);
318 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
319 if (responseFormat != null) {
320 result = Either.right(responseFormat);
323 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
324 .updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
325 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
326 if (addResult.isRight()) {
327 StorageOperationStatus status = addResult.right().value();
328 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
329 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
330 result = Either.right(componentsUtils
331 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
334 AdditionalInformationDefinition informationDefinition = addResult.left().value();
335 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(),
336 additionalInfoParameterInfo.getKey());
337 result = Either.left(parameterInfo);
341 commitOrRollback(result);
343 graphLockOperation.unlockComponent(resourceId, nodeType);
348 * Delete an additional information label
352 * @param additionalInfoParameterInfo
356 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
357 AdditionalInfoParameterInfo additionalInfoParameterInfo,
359 validateUserExists(userId);
360 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
361 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
362 if (responseFormat != null) {
363 return Either.right(responseFormat);
366 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
367 if (lockResult != StorageOperationStatus.OK) {
368 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
369 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
370 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
374 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation
375 .getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
376 if (findIdRes.isRight()) {
377 StorageOperationStatus status = findIdRes.right().value();
378 if (status != StorageOperationStatus.NOT_FOUND) {
379 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
381 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
382 result = Either.right(componentsUtils
383 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
386 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
387 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
388 .deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
389 if (addResult.isRight()) {
390 StorageOperationStatus status = addResult.right().value();
391 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
392 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
393 result = Either.right(componentsUtils
394 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
397 result = Either.left(foundAdditionalInfo);
401 commitOrRollback(result);
403 graphLockOperation.unlockComponent(resourceId, nodeType);
410 * @param additionalInfoParameterInfo
414 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
415 AdditionalInfoParameterInfo additionalInfoParameterInfo,
417 validateUserExists(userId);
418 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
420 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation
421 .getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
422 if (findIdRes.isRight()) {
423 StorageOperationStatus status = findIdRes.right().value();
424 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
425 result = Either.right(componentsUtils
426 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
428 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
429 result = Either.left(foundAdditionalInfo);
432 commitOrRollback(result);
437 * Get all additional information properties of a given resource/service
444 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
446 validateUserExists(userId);
447 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
449 Either<AdditionalInformationDefinition, JanusGraphOperationStatus> findIdRes = additionalInformationOperation
450 .getAllAdditionalInformationParameters(nodeType, resourceId, false);
451 if (findIdRes.isRight()) {
452 StorageOperationStatus status = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(findIdRes.right().value());
453 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
454 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
456 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
457 result = Either.left(informationDefinition);
461 commitOrRollback(result);
465 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
468 // verify that resource is checked-out and the user is the last
471 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
472 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
476 // verify that resource is checked-out and the user is the last
479 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
480 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
484 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());