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