re base code
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / AttributeBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.be.components.impl;
22
23 import fj.data.Either;
24 import org.openecomp.sdc.be.config.BeEcompErrorManager;
25 import org.openecomp.sdc.be.dao.api.ActionStatus;
26 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
27 import org.openecomp.sdc.be.model.DataTypeDefinition;
28 import org.openecomp.sdc.be.model.PropertyDefinition;
29 import org.openecomp.sdc.be.model.Resource;
30 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
31 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
32 import org.openecomp.sdc.common.log.wrappers.Logger;
33 import org.openecomp.sdc.exception.ResponseFormat;
34 import org.springframework.stereotype.Component;
35
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Objects;
39 import java.util.Optional;
40
41 /**
42  * This class holds the business logic relevant for attributes manipulation.
43  * 
44  * @author mshitrit
45  *
46  */
47 @Component("attributeBusinessLogic")
48 public class AttributeBusinessLogic extends BaseBusinessLogic {
49
50     private static final String CREATE_ATTRIBUTE = "CreateAttribute";
51     private static final String UPDATE_ATTRIBUTE = "UpdateAttribute";
52     private static final String DELETE_ATTRIBUTE = "DeleteAttribute";
53
54     private static final Logger log = Logger.getLogger(AttributeBusinessLogic.class.getName());
55     private static final String FAILED_TO_LOCK_COMPONENT_ERROR = "Failed to lock component {}. Error - {}";
56
57     /**
58      * Created attribute on the resource with resourceId
59      *
60      * @param resourceId
61      * @param newAttributeDef
62      * @param userId
63      * @return AttributeDefinition if created successfully Or ResponseFormat
64      */
65     public Either<PropertyDefinition, ResponseFormat> createAttribute(String resourceId, PropertyDefinition newAttributeDef, String userId) {
66         Either<PropertyDefinition, ResponseFormat> result = null;
67         validateUserExists(userId, "create Attribute", false);
68
69         StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
70         if (lockResult != StorageOperationStatus.OK) {
71             BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_ATTRIBUTE, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
72             log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
73             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
74         }
75
76         try {
77             // Get the resource from DB
78             Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId);
79             if (status.isRight()) {
80                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
81             }
82             Resource resource = status.left().value();
83
84             // verify that resource is checked-out and the user is the last updater
85             if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
86                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
87             }
88
89             // verify attribute does not exist in resource
90             if (isAttributeExist(resource.getAttributes(), resourceId, newAttributeDef.getName())) {
91                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.ATTRIBUTE_ALREADY_EXIST, newAttributeDef.getName()));
92             }
93             Either<Map<String, DataTypeDefinition>, ResponseFormat> eitherAllDataTypes = getAllDataTypes(applicationDataTypeCache);
94             if (eitherAllDataTypes.isRight()) {
95                 return Either.right(eitherAllDataTypes.right().value());
96             }
97             // validate property default values
98             Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newAttributeDef, eitherAllDataTypes.left().value());
99             if (defaultValuesValidation.isRight()) {
100                 return Either.right(defaultValuesValidation.right().value());
101             }
102
103             handleDefaultValue(newAttributeDef, eitherAllDataTypes.left().value());
104
105             // add the new attribute to resource on graph
106             // need to get StorageOpaerationStatus and convert to ActionStatus from
107             // componentsUtils
108             Either<PropertyDefinition, StorageOperationStatus> either = toscaOperationFacade.addAttributeOfResource(resource, newAttributeDef);
109             if (either.isRight()) {
110                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName()));
111                 return result;
112             }
113             result = Either.left(either.left().value());
114
115             return result;
116         } finally {
117             commitOrRollback(result);
118             graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
119         }
120
121     }
122
123     private boolean isAttributeExist(List<PropertyDefinition> attributes, String resourceUid, String propertyName) {
124         boolean isExist = false;
125         if (attributes != null) {
126             isExist = attributes.stream().anyMatch(p -> Objects.equals(p.getName(), propertyName) && Objects.equals(p.getParentUniqueId(), resourceUid));
127         }
128         return isExist;
129
130     }
131
132     /**
133      * @param resourceId
134      * @param attributeId
135      * @param userId
136      * @return
137      */
138     public Either<PropertyDefinition, ResponseFormat> getAttribute(String resourceId, String attributeId, String userId) {
139
140         validateUserExists(userId, "get Attribute", false);
141
142         // Get the resource from DB
143         Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId);
144         if (status.isRight()) {
145             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
146         }
147         Resource resource = status.left().value();
148
149         List<PropertyDefinition> attributes = resource.getAttributes();
150         if (attributes == null) {
151             return Either.right(componentsUtils.getResponseFormat(ActionStatus.ATTRIBUTE_NOT_FOUND, ""));
152         } else {
153             // verify attribute exist in resource
154             Optional<PropertyDefinition> optionalAtt = attributes.stream().filter(att -> att.getUniqueId().equals(attributeId) && att.getParentUniqueId().equals(resourceId)).findAny();
155             return optionalAtt.<Either<PropertyDefinition, ResponseFormat>>map(Either::left).orElseGet(() -> Either.right(componentsUtils.getResponseFormat(ActionStatus.ATTRIBUTE_NOT_FOUND, "")));
156         }
157
158     }
159
160     /**
161      * Updates Attribute on resource
162      *
163      * @param resourceId
164      * @param attributeId
165      * @param newAttDef
166      * @param userId
167      * @return
168      */
169     public Either<PropertyDefinition, ResponseFormat> updateAttribute(String resourceId, String attributeId, PropertyDefinition newAttDef, String userId) {
170         Either<PropertyDefinition, ResponseFormat> result = null;
171
172         StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
173         if (lockResult != StorageOperationStatus.OK) {
174             BeEcompErrorManager.getInstance().logBeFailedLockObjectError(UPDATE_ATTRIBUTE, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
175             log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
176             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
177         }
178         try {
179             // Get the resource from DB
180             Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(resourceId);
181             if (eitherResource.isRight()) {
182                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
183             }
184             Resource resource = eitherResource.left().value();
185
186             // verify that resource is checked-out and the user is the last updater
187             if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
188                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
189             }
190
191             // verify attribute exist in resource
192             Either<PropertyDefinition, ResponseFormat> eitherAttribute = getAttribute(resourceId, attributeId, userId);
193             if (eitherAttribute.isRight()) {
194                 return Either.right(eitherAttribute.right().value());
195             }
196             Either<Map<String, DataTypeDefinition>, ResponseFormat> eitherAllDataTypes = getAllDataTypes(applicationDataTypeCache);
197             if (eitherAllDataTypes.isRight()) {
198                 return Either.right(eitherAllDataTypes.right().value());
199             }
200
201             // validate attribute default values
202             Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newAttDef, eitherAllDataTypes.left().value());
203             if (defaultValuesValidation.isRight()) {
204                 return Either.right(defaultValuesValidation.right().value());
205             }
206             // add the new property to resource on graph
207
208             StorageOperationStatus validateAndUpdateAttribute = propertyOperation.validateAndUpdateProperty(newAttDef, eitherAllDataTypes.left().value());
209             if (validateAndUpdateAttribute != StorageOperationStatus.OK) {
210                 log.debug("Problem while updating attribute with id {}. Reason - {}", attributeId, validateAndUpdateAttribute);
211                 result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(validateAndUpdateAttribute), resource.getName()));
212             }
213
214
215             Either<PropertyDefinition, StorageOperationStatus> eitherAttUpdate = toscaOperationFacade.updateAttributeOfResource(resource, newAttDef);
216
217             if (eitherAttUpdate.isRight()) {
218                 log.debug("Problem while updating attribute with id {}. Reason - {}", attributeId, eitherAttUpdate.right().value());
219                 result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(eitherAttUpdate.right().value()), resource.getName()));
220                 return result;
221             }
222
223             result = Either.left(eitherAttUpdate.left().value());
224             return result;
225         } finally {
226             commitOrRollback(result);
227             graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
228         }
229
230     }
231
232     /**
233      * Deletes Attribute on resource
234      *
235      * @param resourceId
236      * @param attributeId
237      * @param userId
238      * @return
239      */
240     public Either<PropertyDefinition, ResponseFormat> deleteAttribute(String resourceId, String attributeId, String userId) {
241
242         Either<PropertyDefinition, ResponseFormat> result = null;
243
244         validateUserExists(userId, "delete Attribute", false);
245
246         StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
247         if (lockResult != StorageOperationStatus.OK) {
248             BeEcompErrorManager.getInstance().logBeFailedLockObjectError(DELETE_ATTRIBUTE, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
249             log.info(FAILED_TO_LOCK_COMPONENT_ERROR, resourceId, lockResult);
250             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
251         }
252
253         try {
254             // Get the resource from DB
255             Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade.getToscaElement(resourceId);
256             if (eitherResource.isRight()) {
257                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
258             }
259             Resource resource = eitherResource.left().value();
260
261             // verify that resource is checked-out and the user is the last updater
262             if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
263                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
264             }
265
266             // verify attribute exist in resource
267             Either<PropertyDefinition, ResponseFormat> eitherAttributeExist = getAttribute(resourceId, attributeId, userId);
268             if (eitherAttributeExist.isRight()) {
269                 return Either.right(eitherAttributeExist.right().value());
270             }
271             String attributeName = eitherAttributeExist.left().value().getName();
272
273             // delete attribute of resource from graph
274             StorageOperationStatus eitherAttributeDelete = toscaOperationFacade.deleteAttributeOfResource(resource, attributeName);
275             if (eitherAttributeDelete != StorageOperationStatus.OK) {
276                 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(eitherAttributeDelete), resource.getName()));
277                 return result;
278             }
279
280             result = Either.left(eitherAttributeExist.left().value());
281             return result;
282         } finally {
283             commitOrRollback(result);
284             graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
285         }
286     }
287 }