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