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()) {
160 if (value != null && !value.equals(newValue)) {
161 log.trace("The additional information value was normalized from {} to {}", value, newValue);
164 additionalInfoParameterInfo.setValue(newValue);
170 * @param additionalInfoParameterInfo
173 private ResponseFormat validateAndConvertKey(AdditionalInfoParameterInfo additionalInfoParameterInfo, String context) {
174 String key = additionalInfoParameterInfo.getKey();
175 log.debug("Going to validate additional information key {}", key);
176 ResponseFormat result = null;
177 ResponseFormat responseFormat;
178 Either<String, ResponseFormat> validateKeyRes = validateAndNormalizeKey(key);
179 if (validateKeyRes.isRight()) {
180 responseFormat = validateKeyRes.right().value();
181 BeEcompErrorManager.getInstance()
182 .logBeInvalidValueError(context, additionalInfoParameterInfo.getKey(), "additional information label", "string");
183 result = responseFormat;
185 String convertedKey = validateKeyRes.left().value();
186 if (log.isTraceEnabled() && key != null && !key.equals(convertedKey)) {
187 log.trace("The additional information key {} was normalized to {}", key, convertedKey);
189 additionalInfoParameterInfo.setKey(convertedKey);
195 * verify that the maximal number of additional information properties has not been reached.
199 * @param additionalInfoParameterInfo
200 * @return response format in case the maximal number has been reached.
202 private ResponseFormat validateMaxSizeNotReached(NodeTypeEnum nodeType, String componentId,
203 AdditionalInfoParameterInfo additionalInfoParameterInfo) {
204 ResponseFormat result;
205 Integer additionalInformationMaxNumberOfKeys = ConfigurationManager.getConfigurationManager().getConfiguration()
206 .getAdditionalInformationMaxNumberOfKeys();
207 Either<Integer, StorageOperationStatus> checkRes = additionalInformationOperation
208 .getNumberOfAdditionalInformationParameters(nodeType, componentId, true);
209 if (checkRes.isRight()) {
210 StorageOperationStatus status = checkRes.right().value();
211 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
212 result = componentsUtils
213 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None);
216 Integer currentNumberOfProperties = checkRes.left().value();
217 if (currentNumberOfProperties >= additionalInformationMaxNumberOfKeys) {
218 log.info("The current number of additional information properties is {}. The maximum allowed additional information properties is {}",
219 currentNumberOfProperties, currentNumberOfProperties);
220 result = componentsUtils
221 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, additionalInfoParameterInfo, nodeType,
222 AdditionalInformationEnum.None);
229 * validate additional information value
234 private Either<String, ResponseFormat> validateValue(String value) {
235 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(value);
236 if (!isNonEmptyString) {
237 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED));
239 boolean valid = StringValidator.getInstance().isValid(value, null);
241 return Either.right(componentsUtils.getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS,
242 new AdditionalInfoParameterInfo(null, value), null, AdditionalInformationEnum.Value));
244 String converted = StringConvertor.getInstance().convert(value, null, null);
245 return Either.left(converted);
248 private AdditionalInfoParameterInfo findAdditionInformationKey(List<AdditionalInfoParameterInfo> parameters, String key) {
249 for (AdditionalInfoParameterInfo infoParameterInfo : parameters) {
250 if (infoParameterInfo.getKey().equals(key)) {
251 return infoParameterInfo;
258 * validate and normalize the key
261 * @return Either<String, ResponseFormat>
263 private Either<String, ResponseFormat> validateAndNormalizeKey(String key) {
264 AdditionalInfoParameterInfo additionalInfoParameterInfo = new AdditionalInfoParameterInfo();
265 additionalInfoParameterInfo.setKey(key);
266 String normKey = ValidationUtils.normalizeAdditionalInformation(key);
267 boolean isNonEmptyString = ValidationUtils.validateStringNotEmpty(normKey);
268 if (!isNonEmptyString) {
269 return Either.right(componentsUtils
270 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, null, null,
271 AdditionalInformationEnum.Label));
273 boolean isValidString = ValidationUtils.validateAdditionalInformationKeyName(normKey);
274 if (!isValidString) {
275 if (!ValidationUtils.validateLength(normKey, ValidationUtils.ADDITIONAL_INFORMATION_KEY_MAX_LENGTH)) {
276 return Either.right(componentsUtils
277 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, additionalInfoParameterInfo, null,
278 AdditionalInformationEnum.Label));
280 return Either.right(componentsUtils
281 .getResponseFormatAdditionalProperty(ActionStatus.ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, additionalInfoParameterInfo,
282 null, AdditionalInformationEnum.Label));
284 return Either.left(normKey);
288 * update key and value of a given additional information.
292 * @param additionalInfoParameterInfo
296 public Either<AdditionalInfoParameterInfo, ResponseFormat> updateAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
297 AdditionalInfoParameterInfo additionalInfoParameterInfo,
299 validateUserExists(userId);
300 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
301 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
302 if (responseFormat != null) {
303 result = Either.right(responseFormat);
307 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
308 if (lockResult != StorageOperationStatus.OK) {
309 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
310 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
311 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
316 responseFormat = validateAndConvertKey(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
317 if (responseFormat != null) {
318 result = Either.right(responseFormat);
321 responseFormat = validateAndConvertValue(additionalInfoParameterInfo, UPDATE_ADDITIONAL_INFORMATION);
322 if (responseFormat != null) {
323 result = Either.right(responseFormat);
326 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
327 .updateAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(),
328 additionalInfoParameterInfo.getKey(), additionalInfoParameterInfo.getValue(), true);
329 if (addResult.isRight()) {
330 StorageOperationStatus status = addResult.right().value();
331 BeEcompErrorManager.getInstance().logBeSystemError(UPDATE_ADDITIONAL_INFORMATION);
332 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
333 result = Either.right(componentsUtils
334 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
337 AdditionalInformationDefinition informationDefinition = addResult.left().value();
338 AdditionalInfoParameterInfo parameterInfo = findAdditionInformationKey(informationDefinition.getParameters(),
339 additionalInfoParameterInfo.getKey());
340 result = Either.left(parameterInfo);
344 commitOrRollback(result);
346 graphLockOperation.unlockComponent(resourceId, nodeType);
351 * Delete an additional information label
355 * @param additionalInfoParameterInfo
359 public Either<AdditionalInfoParameterInfo, ResponseFormat> deleteAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
360 AdditionalInfoParameterInfo additionalInfoParameterInfo,
362 validateUserExists(userId);
363 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
364 ResponseFormat responseFormat = verifyCanWorkOnComponent(nodeType, resourceId, userId);
365 if (responseFormat != null) {
366 return Either.right(responseFormat);
369 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, nodeType);
370 if (lockResult != StorageOperationStatus.OK) {
371 BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ADDITIONAL_INFORMATION, nodeType.getName(), resourceId);
372 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
373 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
377 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation
378 .getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
379 if (findIdRes.isRight()) {
380 StorageOperationStatus status = findIdRes.right().value();
381 if (status != StorageOperationStatus.NOT_FOUND) {
382 BeEcompErrorManager.getInstance().logBeSystemError(GET_ADDITIONAL_INFORMATION);
384 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
385 result = Either.right(componentsUtils
386 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
389 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
390 Either<AdditionalInformationDefinition, StorageOperationStatus> addResult = additionalInformationOperation
391 .deleteAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
392 if (addResult.isRight()) {
393 StorageOperationStatus status = addResult.right().value();
394 BeEcompErrorManager.getInstance().logBeDaoSystemError(DELETE_ADDITIONAL_INFORMATION);
395 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
396 result = Either.right(componentsUtils
397 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
400 result = Either.left(foundAdditionalInfo);
404 commitOrRollback(result);
406 graphLockOperation.unlockComponent(resourceId, nodeType);
413 * @param additionalInfoParameterInfo
417 public Either<AdditionalInfoParameterInfo, ResponseFormat> getAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
418 AdditionalInfoParameterInfo additionalInfoParameterInfo,
420 validateUserExists(userId);
421 Either<AdditionalInfoParameterInfo, ResponseFormat> result = null;
423 Either<AdditionalInfoParameterInfo, StorageOperationStatus> findIdRes = additionalInformationOperation
424 .getAdditionalInformationParameter(nodeType, resourceId, additionalInfoParameterInfo.getUniqueId(), true);
425 if (findIdRes.isRight()) {
426 StorageOperationStatus status = findIdRes.right().value();
427 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
428 result = Either.right(componentsUtils
429 .getResponseFormatAdditionalProperty(actionStatus, additionalInfoParameterInfo, nodeType, AdditionalInformationEnum.None));
431 AdditionalInfoParameterInfo foundAdditionalInfo = findIdRes.left().value();
432 result = Either.left(foundAdditionalInfo);
435 commitOrRollback(result);
440 * Get all additional information properties of a given resource/service
447 public Either<AdditionalInformationDefinition, ResponseFormat> getAllAdditionalInformation(NodeTypeEnum nodeType, String resourceId,
449 validateUserExists(userId);
450 Either<AdditionalInformationDefinition, ResponseFormat> result = null;
452 Either<AdditionalInformationDefinition, JanusGraphOperationStatus> findIdRes = additionalInformationOperation
453 .getAllAdditionalInformationParameters(nodeType, resourceId, false);
454 if (findIdRes.isRight()) {
455 StorageOperationStatus status = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(findIdRes.right().value());
456 ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForAdditionalInformation(status);
457 result = Either.right(componentsUtils.getResponseFormatAdditionalProperty(actionStatus));
459 AdditionalInformationDefinition informationDefinition = findIdRes.left().value();
460 result = Either.left(informationDefinition);
464 commitOrRollback(result);
468 private ResponseFormat verifyCanWorkOnComponent(NodeTypeEnum nodeType, String resourceId, String userId) {
471 // verify that resource is checked-out and the user is the last
474 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
475 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
479 // verify that resource is checked-out and the user is the last
482 if (!ComponentValidationUtils.canWorkOnComponent(resourceId, toscaOperationFacade, userId)) {
483 return componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
487 return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT, nodeType.getName());