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