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 java.util.List;
26 import java.util.Objects;
27 import java.util.Optional;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.openecomp.sdc.be.config.BeEcompErrorManager;
30 import org.openecomp.sdc.be.dao.api.ActionStatus;
31 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
32 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
33 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
34 import org.openecomp.sdc.be.model.AttributeDefinition;
35 import org.openecomp.sdc.be.model.Component;
36 import org.openecomp.sdc.be.model.ComponentParametersView;
37 import org.openecomp.sdc.be.model.DataTypeDefinition;
38 import org.openecomp.sdc.be.model.Resource;
39 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
40 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
41 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
42 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
43 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
44 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
45 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
46 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
47 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
48 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
49 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
50 import org.openecomp.sdc.common.log.wrappers.Logger;
51 import org.openecomp.sdc.exception.ResponseFormat;
52 import org.springframework.beans.factory.annotation.Autowired;
55 * This class holds the business logic relevant for attributes manipulation.
59 @org.springframework.stereotype.Component("attributeBusinessLogic")
60 public class AttributeBusinessLogic extends BaseBusinessLogic {
62 private static final String CREATE_ATTRIBUTE = "CreateAttribute";
63 private static final String UPDATE_ATTRIBUTE = "UpdateAttribute";
64 private static final String DELETE_ATTRIBUTE = "DeleteAttribute";
66 private static final Logger log = Logger.getLogger(AttributeBusinessLogic.class);
67 private static final String FAILED_TO_LOCK_COMPONENT_ERROR = "Failed to lock component {}. Error - {}";
70 public AttributeBusinessLogic(IElementOperation elementDao,
71 IGroupOperation groupOperation,
72 IGroupInstanceOperation groupInstanceOperation,
73 IGroupTypeOperation groupTypeOperation,
74 InterfaceOperation interfaceOperation,
75 InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
76 ArtifactsOperations artifactToscaOperation) {
77 super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation,
78 interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation);
82 * Created attribute on the resource with resourceId
85 * @param newAttributeDef
87 * @return AttributeDefinition if created successfully Or ResponseFormat
89 public Either<AttributeDefinition, ResponseFormat> createAttribute(String resourceId,
90 AttributeDefinition newAttributeDef,
92 Either<AttributeDefinition, ResponseFormat> result = null;
93 validateUserExists(userId);
95 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
96 if (lockResult != StorageOperationStatus.OK) {
97 BeEcompErrorManager.getInstance()
98 .logBeFailedLockObjectError(CREATE_ATTRIBUTE, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
99 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
100 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
104 // Get the resource from DB
105 Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId);
106 if (status.isRight()) {
107 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
109 Resource resource = status.left().value();
111 // verify that resource is checked-out and the user is the last updater
112 if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
113 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
116 // verify attribute does not exist in resource
117 if (isAttributeExist(resource.getAttributes(), resourceId, newAttributeDef.getName())) {
119 componentsUtils.getResponseFormat(ActionStatus.ATTRIBUTE_ALREADY_EXIST, newAttributeDef.getName()));
121 Map<String, DataTypeDefinition> eitherAllDataTypes = getAllDataTypes(applicationDataTypeCache);
122 // validate property default values
123 Either<Boolean, ResponseFormat> defaultValuesValidation = validateAttributeDefaultValue(newAttributeDef,
125 if (defaultValuesValidation.isRight()) {
126 return Either.right(defaultValuesValidation.right().value());
129 handleAttributeDefaultValue(newAttributeDef, eitherAllDataTypes);
131 // add the new attribute to resource on graph
132 // need to get StorageOperationStatus and convert to ActionStatus from
134 Either<AttributeDefinition, StorageOperationStatus> either = toscaOperationFacade
135 .addAttributeOfResource(resource, newAttributeDef);
136 if (either.isRight()) {
137 result = Either.right(componentsUtils
138 .getResponseFormat(componentsUtils.convertFromStorageResponse(either.right().value()),
139 resource.getName()));
142 result = Either.left(either.left().value());
146 commitOrRollback(result);
147 graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
151 private Either<Boolean, ResponseFormat> validateAttributeDefaultValue(final AttributeDefinition attributeDefinition,
152 final Map<String, DataTypeDefinition> dataTypes) {
154 if (!attributeOperation.isAttributeTypeValid(attributeDefinition)) {
155 log.info("Invalid type for attribute '{}' type '{}'", attributeDefinition.getName(),
156 attributeDefinition.getType());
157 final ResponseFormat responseFormat = componentsUtils
158 .getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE, attributeDefinition
159 .getType(), attributeDefinition.getName());
160 return Either.right(responseFormat);
162 String type = attributeDefinition.getType();
163 String innerType = null;
164 if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) {
165 final ImmutablePair<String, Boolean> propertyInnerTypeValid = attributeOperation.isAttributeInnerTypeValid(
166 attributeDefinition, dataTypes);
167 innerType = propertyInnerTypeValid.getLeft();
168 if (!Boolean.TRUE.equals(propertyInnerTypeValid.getRight())) {
169 log.info("Invalid inner type for attribute '{}' type '{}', dataTypeCount '{}'",
170 attributeDefinition.getName(), attributeDefinition.getType(), dataTypes.size());
171 final ResponseFormat responseFormat = componentsUtils
172 .getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE, innerType,
173 attributeDefinition.getName());
174 return Either.right(responseFormat);
177 if (!attributeOperation.isAttributeDefaultValueValid(attributeDefinition, dataTypes)) {
178 log.info("Invalid default value for attribute '{}' type '{}'", attributeDefinition.getName(),
179 attributeDefinition.getType());
180 ResponseFormat responseFormat;
181 if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) {
182 responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_COMPLEX_DEFAULT_VALUE,
183 attributeDefinition.getName(), type, innerType,
184 (String) attributeDefinition.get_default());
186 responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_DEFAULT_VALUE,
187 attributeDefinition.getName(), type, (String) attributeDefinition.get_default());
189 return Either.right(responseFormat);
192 return Either.left(true);
195 private void handleAttributeDefaultValue(final AttributeDefinition newAttributeDefinition,
196 final Map<String, DataTypeDefinition> dataTypes) {
197 final ToscaPropertyType type = ToscaPropertyType.isValidType(newAttributeDefinition.getType());
198 final PropertyValueConverter converter = type.getConverter();
200 String innerType = null;
201 final SchemaDefinition schema = newAttributeDefinition.getSchema();
202 if (schema != null) {
203 final PropertyDataDefinition prop = schema.getProperty();
204 if (schema.getProperty() != null) {
205 innerType = prop.getType();
208 if (newAttributeDefinition.get_default() != null) {
209 newAttributeDefinition.set_default(converter
210 .convert((String) newAttributeDefinition.get_default(), innerType, dataTypes));
214 private boolean isAttributeExist(List<AttributeDefinition> attributes, String resourceUid, String propertyName) {
215 boolean isExist = false;
216 if (attributes != null) {
217 isExist = attributes.stream().anyMatch(
218 p -> Objects.equals(p.getName(), propertyName) && Objects.equals(p.getOwnerId(), resourceUid));
230 public Either<AttributeDefinition, ResponseFormat> getAttribute(String resourceId, String attributeId,
233 validateUserExists(userId);
235 // Get the resource from DB
236 Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId);
237 if (status.isRight()) {
238 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
240 Resource resource = status.left().value();
242 List<AttributeDefinition> attributes = resource.getAttributes();
243 if (attributes == null) {
244 return Either.right(componentsUtils.getResponseFormat(ActionStatus.ATTRIBUTE_NOT_FOUND, ""));
246 // verify attribute exist in resource
247 Optional<AttributeDefinition> optionalAtt = attributes.stream().filter(att ->
248 att.getUniqueId().equals(attributeId)).findAny();
249 return optionalAtt.<Either<AttributeDefinition, ResponseFormat>>map(Either::left).orElseGet(() ->
250 Either.right(componentsUtils.getResponseFormat(ActionStatus.ATTRIBUTE_NOT_FOUND, "")));
255 * Updates Attribute on resource
263 public Either<AttributeDefinition, ResponseFormat> updateAttribute(String resourceId, String attributeId,
264 AttributeDefinition newAttDef, String userId) {
265 Either<AttributeDefinition, ResponseFormat> result = null;
267 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
268 if (lockResult != StorageOperationStatus.OK) {
269 BeEcompErrorManager.getInstance()
270 .logBeFailedLockObjectError(UPDATE_ATTRIBUTE, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
271 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
272 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
275 // Get the resource from DB
276 Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(resourceId);
277 if (eitherResource.isRight()) {
278 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
280 Resource resource = eitherResource.left().value();
282 // verify that resource is checked-out and the user is the last updater
283 if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
284 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
287 // verify attribute exist in resource
288 Either<AttributeDefinition, ResponseFormat> eitherAttribute = getAttribute(resourceId, attributeId, userId);
289 if (eitherAttribute.isRight()) {
290 return Either.right(eitherAttribute.right().value());
292 Map<String, DataTypeDefinition> eitherAllDataTypes = getAllDataTypes(applicationDataTypeCache);
294 // validate attribute default values
295 Either<Boolean, ResponseFormat> defaultValuesValidation = validateAttributeDefaultValue(newAttDef,
297 if (defaultValuesValidation.isRight()) {
298 return Either.right(defaultValuesValidation.right().value());
301 // add the new property to resource on graph
302 StorageOperationStatus validateAndUpdateAttribute = attributeOperation
303 .validateAndUpdateAttribute(newAttDef, eitherAllDataTypes);
304 if (validateAndUpdateAttribute != StorageOperationStatus.OK) {
305 log.debug("Problem while updating attribute with id {}. Reason - {}", attributeId,
306 validateAndUpdateAttribute);
307 result = Either.right(componentsUtils
308 .getResponseFormatByResource(componentsUtils.convertFromStorageResponse(validateAndUpdateAttribute),
309 resource.getName()));
312 Either<AttributeDefinition, StorageOperationStatus> eitherAttUpdate = toscaOperationFacade
313 .updateAttributeOfResource(resource, newAttDef);
315 if (eitherAttUpdate.isRight()) {
316 log.debug("Problem while updating attribute with id {}. Reason - {}", attributeId,
317 eitherAttUpdate.right().value());
318 result = Either.right(componentsUtils.getResponseFormatByResource(
319 componentsUtils.convertFromStorageResponse(eitherAttUpdate.right().value()), resource.getName()));
323 result = Either.left(eitherAttUpdate.left().value());
326 commitOrRollback(result);
327 graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
333 * Deletes Attribute on resource
340 public Either<AttributeDefinition, ResponseFormat> deleteAttribute(String resourceId, String attributeId,
343 Either<AttributeDefinition, ResponseFormat> result = null;
345 validateUserExists(userId);
347 StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
348 if (lockResult != StorageOperationStatus.OK) {
349 BeEcompErrorManager.getInstance()
350 .logBeFailedLockObjectError(DELETE_ATTRIBUTE, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
351 log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
352 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
356 // Get the resource from DB
357 Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(resourceId);
358 if (eitherResource.isRight()) {
359 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
361 Resource resource = eitherResource.left().value();
363 // verify that resource is checked-out and the user is the last updater
364 if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
365 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
368 // verify attribute exist in resource
369 Either<AttributeDefinition, ResponseFormat> eitherAttributeExist = getAttribute(resourceId, attributeId,
371 if (eitherAttributeExist.isRight()) {
372 return Either.right(eitherAttributeExist.right().value());
374 String attributeName = eitherAttributeExist.left().value().getName();
376 // delete attribute of resource from graph
377 StorageOperationStatus eitherAttributeDelete = toscaOperationFacade
378 .deleteAttributeOfResource(resource, attributeName);
379 if (eitherAttributeDelete != StorageOperationStatus.OK) {
380 result = Either.right(componentsUtils
381 .getResponseFormat(componentsUtils.convertFromStorageResponse(eitherAttributeDelete),
382 resource.getName()));
386 result = Either.left(eitherAttributeExist.left().value());
389 commitOrRollback(result);
390 graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
394 public Either<List<AttributeDefinition>, ResponseFormat> getAttributesList(final String componentId,
395 final String userId) {
396 validateUserExists(userId);
398 // Get the resource from DB
399 final ComponentParametersView filter = new ComponentParametersView(true);
400 filter.setIgnoreAttributes(false);
401 final Either<Component, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(componentId, filter);
402 if (status.isRight()) {
403 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
406 return Either.left(status.left().value().getAttributes());