Sync Integ to Master
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsontitan / operations / GroupsOperation.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.model.jsontitan.operations;
22
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Optional;
27 import java.util.stream.Collectors;
28
29 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
30 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
31 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
32 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
33 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
34 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
35 import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition;
36 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
37 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
38 import org.openecomp.sdc.be.model.Component;
39 import org.openecomp.sdc.be.model.GroupDefinition;
40 import org.openecomp.sdc.be.model.GroupInstance;
41 import org.openecomp.sdc.be.model.GroupInstanceProperty;
42 import org.openecomp.sdc.be.model.GroupProperty;
43 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
44 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
45 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
46 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
47 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
48 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import fj.data.Either;
53
54 @org.springframework.stereotype.Component("groups-operation")
55 public class GroupsOperation extends BaseOperation {
56
57         private static final Logger log = LoggerFactory.getLogger(GroupsOperation.class);
58
59         public Either<List<GroupDefinition>, StorageOperationStatus> createGroups(Component component, Map<String, GroupDataDefinition> groups) {
60
61                 Either<List<GroupDefinition>, StorageOperationStatus> result = null;
62                 Either<GraphVertex, TitanOperationStatus> getComponentVertex = null;
63                 StorageOperationStatus status = null;
64
65                 if (result == null) {
66                         getComponentVertex = titanDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse);
67                         if (getComponentVertex.isRight()) {
68                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value()));
69                         }
70                 }
71                 if (result == null) {
72                         status = topologyTemplateOperation.associateGroupsToComponent(getComponentVertex.left().value(), groups);
73                         if (status != StorageOperationStatus.OK) {
74                                 result = Either.right(status);
75                         }
76                 }
77                 if (result == null) {
78                         result = Either.left(ModelConverter.convertToGroupDefinitions(groups));
79                 }
80                 return result;
81         }
82         
83         public Either<List<GroupDefinition>, StorageOperationStatus> addGroups(Component component, List<GroupDataDefinition> groups) {
84                 Either<List<GroupDefinition>, StorageOperationStatus> result = null;
85                 Either<GraphVertex, TitanOperationStatus> getComponentVertex = null;
86                 StorageOperationStatus status = null;
87
88                 if (result == null) {
89                         getComponentVertex = titanDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse);
90                         if (getComponentVertex.isRight()) {
91                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value()));
92                         }
93                 } 
94                 if (result == null) {
95                         status = addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groups, JsonPresentationFields.NAME);
96                         
97                         if (status != StorageOperationStatus.OK) {
98                                 result = Either.right(status);
99                         }
100                 }
101                 
102                 if (result == null) {
103                         Map<String, GroupDataDefinition> mapGroup = groups.stream().collect(Collectors.toMap( x-> x.getName(), x->x));
104                         result = Either.left(ModelConverter.convertToGroupDefinitions(mapGroup));
105                 }
106                 return result;
107         }
108         
109         public Either<List<GroupDefinition>, StorageOperationStatus> deleteGroups(Component component, List<GroupDataDefinition> groups) {
110                 Either<List<GroupDefinition>, StorageOperationStatus> result = null;
111                 Either<GraphVertex, TitanOperationStatus> getComponentVertex = null;
112                 StorageOperationStatus status = null;
113
114                 if (result == null) {
115                         getComponentVertex = titanDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse);
116                         if (getComponentVertex.isRight()) {
117                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value()));
118                         }
119                 } 
120                 if (result == null) {
121                         List<String> groupName = groups.stream().map(g -> g.getName()).collect(Collectors.toList());
122                         status = deleteToscaDataElements(component.getUniqueId(), EdgeLabelEnum.GROUPS, groupName);
123                                                 
124                         if (status != StorageOperationStatus.OK) {
125                                 result = Either.right(status);
126                         }
127                 }
128                 
129                 if (result == null) {
130                         Map<String, GroupDataDefinition> mapGroup = groups.stream().collect(Collectors.toMap( x-> x.getName(), x->x));
131                         result = Either.left(ModelConverter.convertToGroupDefinitions(mapGroup));
132                 }
133                 return result;
134         }
135         
136         public <T extends GroupDataDefinition> Either<List<GroupDefinition>, StorageOperationStatus> updateGroups(Component component, List<T> groups) {
137                 Either<List<GroupDefinition>, StorageOperationStatus> result = null;
138                 Either<GraphVertex, TitanOperationStatus> getComponentVertex = null;
139                 StorageOperationStatus status = null;
140
141                 if (result == null) {
142                         getComponentVertex = titanDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse);
143                         if (getComponentVertex.isRight()) {
144                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value()));
145                         }
146                 } 
147                 if (result == null) {
148                         groups.forEach(gr -> {
149                                 String version = gr.getVersion();
150                                 String newVersion = increaseMajorVersion(version);
151                                 gr.setVersion(newVersion);
152                                 String groupUUID = UniqueIdBuilder.generateUUID();
153                                 gr.setGroupUUID(groupUUID);
154                         });
155
156                         status = updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groups, JsonPresentationFields.NAME);
157                                                 
158                         if (status != StorageOperationStatus.OK) {
159                                 result = Either.right(status);
160                         }
161                 }
162                 
163                 if (result == null) {
164                         Map<String, GroupDataDefinition> mapGroup = groups.stream().collect(Collectors.toMap( x-> x.getName(), x->x));
165                         result = Either.left(ModelConverter.convertToGroupDefinitions(mapGroup));
166                 }
167                 return result;
168         }
169         
170         
171         public Either<List<GroupProperty>, StorageOperationStatus> updateGroupPropertiesOnComponent(String componentId, GroupDefinition group, List<GroupProperty> newGroupProperties) {
172                 
173                 Either<List<GroupProperty>,StorageOperationStatus> result = null;
174                 Either<GraphVertex, TitanOperationStatus> getComponentVertex = null;
175                 GraphVertex componentVertex = null;
176
177                 if (result == null) {
178                         getComponentVertex = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata);
179                         if (getComponentVertex.isRight()) {
180                                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component {}. Status is {} ", componentId);
181                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value()));
182                         }
183                 } 
184                 if (result == null) {
185                         componentVertex = getComponentVertex.left().value();
186                         //update 
187                         List<PropertyDataDefinition> properties = group.getProperties();
188                         newGroupProperties.forEach(np -> {
189                                 Optional<PropertyDataDefinition> currentProp = properties.stream().filter(p -> p.getName().equals(np.getName())).findAny();
190                                 if (currentProp.isPresent()) {  
191                                         currentProp.get().setValue(np.getValue());
192                                 }
193                         });
194                         
195                         StorageOperationStatus updateDataRes = updateToscaDataOfToscaElement(componentVertex, EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, group, JsonPresentationFields.NAME);
196                         if ( updateDataRes != StorageOperationStatus.OK ){
197                                 log.debug("Failed to update properties for group {} error {}", group.getName(), updateDataRes);
198                                 result = Either.right(updateDataRes);
199                         }
200                 }
201                 if (result == null) {
202                         componentVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
203                         Either<GraphVertex, TitanOperationStatus> updateRes = titanDao.updateVertex(componentVertex);
204                         if (updateRes.isRight()) {
205                                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the component {}. Status is {} ",  componentId, updateRes.right().value());
206                                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateRes.right().value()));
207                         }
208                 }
209                 if (result == null) {
210                         result = Either.left(newGroupProperties);
211                 }
212                 return result;
213         }
214         
215         /**
216          * The version of the group is an integer. In order to support BC, we might get a version in a float format.
217          * 
218          * @param version
219          * @return
220          */
221         private String increaseMajorVersion(String version) {
222
223                 String[] versionParts = version.split(ToscaElementLifecycleOperation.VERSION_DELIMETER_REGEXP);
224                 Integer majorVersion = Integer.parseInt(versionParts[0]);
225
226                 majorVersion++;
227
228                 return String.valueOf(majorVersion);
229
230         }
231
232         public Either<List<GroupInstance>, StorageOperationStatus> updateGroupInstances(Component component, String instanceId, List<GroupInstance> updatedGroupInstances) {
233
234                 Either<List<GroupInstance>, StorageOperationStatus> result = null;
235                 StorageOperationStatus status = null;
236
237                 Either<GraphVertex, TitanOperationStatus> getComponentVertex = titanDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse);
238                 if (getComponentVertex.isRight()) {
239                         result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value()));
240                 }
241                 if (result == null) {
242                         List<String> pathKeys = new ArrayList<>();
243                         pathKeys.add(instanceId);
244                         status = updateToscaDataDeepElementsOfToscaElement(component.getUniqueId(), EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS, updatedGroupInstances, pathKeys,  JsonPresentationFields.NAME);
245                         if (status != StorageOperationStatus.OK) {
246                                 result = Either.right(status);
247                         }
248                 }
249                 if (result == null) {
250                         result = Either.left(updatedGroupInstances);
251                 }
252                 return result;
253         }
254
255         public Either<GroupDefinition, StorageOperationStatus> updateGroup(Component component, GroupDefinition currentGroup) {
256                 StorageOperationStatus status = updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, currentGroup, JsonPresentationFields.NAME);
257                 if(status != StorageOperationStatus.OK){
258                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update group {} of component {}. The status is}. ", currentGroup.getName(), component.getName(), status);
259                         return Either.right(status);
260                 }
261                 return Either.left(currentGroup);
262         }
263
264         public StorageOperationStatus deleteGroup(Component component, String currentGroupName) {
265                 StorageOperationStatus status = deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, currentGroupName, JsonPresentationFields.NAME);
266                 if(status != StorageOperationStatus.OK){
267                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete group {} of component {}. The status is}. ", currentGroupName, component.getName(), status);
268                 }
269                 return status;
270         }
271
272         public Either<GroupDefinition, StorageOperationStatus> addGroup(Component component, GroupDefinition currentGroup) {
273                 StorageOperationStatus status = addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, currentGroup, JsonPresentationFields.NAME);
274                 if(status != StorageOperationStatus.OK){
275                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update group {} of component {}. The status is}. ", currentGroup.getName(), component.getName(), status);
276                         return Either.right(status);
277                 }
278                 return Either.left(currentGroup);
279         }
280         
281         public Either<GroupInstance, StorageOperationStatus> updateGroupInstancePropertyValuesOnGraph(String componentId, String instanceId, GroupInstance oldGroupInstance, List<GroupInstanceProperty> newProperties) {
282
283                 Either<GraphVertex, TitanOperationStatus> getComponentVertex = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata);
284                 if (getComponentVertex.isRight()) {
285                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component {}. Status is {} ", componentId);
286                         return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value()));
287                 }
288
289                 List<PropertyDataDefinition> propertiesOld = oldGroupInstance.getProperties();
290                 newProperties.forEach(np -> {
291                         Optional<PropertyDataDefinition> prop = propertiesOld.stream().filter(p -> p.getName().equals(np.getName())).findFirst();
292                         if (prop.isPresent()) {
293                                 prop.get().setValue(np.getValue());
294                         }
295                 });
296                 GroupInstanceDataDefinition groupInstanceDataDefinition = new GroupInstanceDataDefinition(oldGroupInstance);
297                 List<String> pathKeys = new ArrayList<>();
298                 pathKeys.add(instanceId);
299                 StorageOperationStatus updateDataRes = updateToscaDataDeepElementOfToscaElement(componentId, EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS, groupInstanceDataDefinition, pathKeys, JsonPresentationFields.NAME);
300                 if (updateDataRes != StorageOperationStatus.OK) {
301                         log.debug("Failed to update properties for group instance {} error {}", oldGroupInstance.getName(), updateDataRes);
302                         return Either.right(updateDataRes);
303                 }
304                 return Either.left(oldGroupInstance);
305         }
306
307 }