Reformat catalog-model
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / GroupInstanceOperation.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 package org.openecomp.sdc.be.model.operations.impl;
21
22 import fj.data.Either;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.UUID;
29 import java.util.function.Supplier;
30 import java.util.stream.Collectors;
31 import org.apache.commons.collections.MapUtils;
32 import org.apache.commons.lang3.tuple.ImmutablePair;
33 import org.apache.tinkerpop.gremlin.structure.Vertex;
34 import org.janusgraph.core.JanusGraph;
35 import org.janusgraph.core.JanusGraphVertex;
36 import org.openecomp.sdc.be.config.BeEcompErrorManager;
37 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
38 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
39 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
40 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
41 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
42 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
43 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
44 import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition;
45 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
47 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
48 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
49 import org.openecomp.sdc.be.model.DataTypeDefinition;
50 import org.openecomp.sdc.be.model.GroupDefinition;
51 import org.openecomp.sdc.be.model.GroupInstance;
52 import org.openecomp.sdc.be.model.GroupInstanceProperty;
53 import org.openecomp.sdc.be.model.GroupProperty;
54 import org.openecomp.sdc.be.model.IComponentInstanceConnectedElement;
55 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
56 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
57 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
58 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
59 import org.openecomp.sdc.be.resources.data.ArtifactData;
60 import org.openecomp.sdc.be.resources.data.GroupInstanceData;
61 import org.openecomp.sdc.be.resources.data.PropertyData;
62 import org.openecomp.sdc.be.resources.data.PropertyValueData;
63 import org.openecomp.sdc.be.resources.data.UniqueIdData;
64 import org.openecomp.sdc.common.datastructure.Wrapper;
65 import org.openecomp.sdc.common.log.wrappers.Logger;
66 import org.springframework.beans.factory.annotation.Autowired;
67
68 @org.springframework.stereotype.Component("group-instance-operation")
69 public class GroupInstanceOperation extends AbstractOperation implements IGroupInstanceOperation {
70
71     private static final String UPDATE_PROPERTY_VALUE_ON_COMPONENT_INSTANCE = "UpdatePropertyValueOnComponentInstance";
72     private static final String FAILED_TO_UPDATE_PROPERTY_VALUE_ON_INSTANCE_STATUS_IS = "Failed to update property value on instance. Status is ";
73     private static final Logger log = Logger.getLogger(GroupInstanceOperation.class.getName());
74     @Autowired
75     GroupOperation groupOperation;
76     @Autowired
77     PropertyOperation propertyOperation;
78     @javax.annotation.Resource
79     private ApplicationDataTypeCache dataTypeCache;
80
81     public Either<List<GroupInstance>, StorageOperationStatus> getAllGroupInstances(String parentId, NodeTypeEnum parentType) {
82         Either<List<GroupInstance>, StorageOperationStatus> result = null;
83         List<GroupInstance> groupInstanceRes = new ArrayList<>();
84         Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphGenericDao.getGraph();
85         if (graph.isRight()) {
86             log.debug("Failed to work with graph {}", graph.right().value());
87             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graph.right().value()));
88         }
89         JanusGraph tGraph = graph.left().value();
90         @SuppressWarnings("unchecked") Iterable<JanusGraphVertex> vertices = tGraph.query()
91             .has(UniqueIdBuilder.getKeyByNodeType(parentType), parentId).vertices();
92         if (vertices == null || vertices.iterator() == null || !vertices.iterator().hasNext()) {
93             log.debug("No nodes for type {}  for id = {}", parentType, parentId);
94             result = Either.right(StorageOperationStatus.NOT_FOUND);
95             return result;
96         }
97         Iterator<JanusGraphVertex> iterator = vertices.iterator();
98         Vertex vertex = iterator.next();
99         Map<String, Object> edgeProperties = null;
100         Either<List<ImmutablePair<GroupInstanceData, GraphEdge>>, JanusGraphOperationStatus> childrenByEdgeCriteria = janusGraphGenericDao
101             .getChildrenByEdgeCriteria(vertex, parentId, GraphEdgeLabels.GROUP_INST, NodeTypeEnum.GroupInstance, GroupInstanceData.class,
102                 edgeProperties);
103         if (childrenByEdgeCriteria.isRight()) {
104             JanusGraphOperationStatus status = childrenByEdgeCriteria.right().value();
105             log.debug("Failed to find group instance {} on graph", childrenByEdgeCriteria.right().value());
106             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
107         }
108         List<ImmutablePair<GroupInstanceData, GraphEdge>> list = childrenByEdgeCriteria.left().value();
109         for (ImmutablePair<GroupInstanceData, GraphEdge> pair : list) {
110             GroupInstanceData groupInstData = pair.getLeft();
111             GroupInstance groupInstance = new GroupInstance(groupInstData.getGroupDataDefinition());
112             String instOriginGroupId = groupInstance.getGroupUid();
113             Either<GroupDefinition, StorageOperationStatus> groupRes = groupOperation.getGroupFromGraph(instOriginGroupId, false, true, false);
114             if (groupRes.isRight()) {
115                 return Either.right(groupRes.right().value());
116             }
117             GroupDefinition groupDefinition = groupRes.left().value();
118             Either<Map<String, PropertyValueData>, JanusGraphOperationStatus> groupInstancePropertyValuesRes = getAllGroupInstancePropertyValuesData(
119                 groupInstData);
120             if (groupInstancePropertyValuesRes.isRight()) {
121                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(groupInstancePropertyValuesRes.right().value()));
122             }
123             buildGroupInstanceFromGroup(groupInstance, groupDefinition, groupInstancePropertyValuesRes.left().value());
124             Either<List<ImmutablePair<String, String>>, JanusGraphOperationStatus> artifactsRes = getGroupArtifactsPairs(groupInstance.getUniqueId());
125             if (artifactsRes.isRight()) {
126                 JanusGraphOperationStatus status = artifactsRes.right().value();
127                 if (status != JanusGraphOperationStatus.OK) {
128                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
129                     return result;
130                 }
131             } else {
132                 List<String> artifactsUid = new ArrayList<>();
133                 List<String> artifactsUUID = new ArrayList<>();
134                 List<ImmutablePair<String, String>> list1 = artifactsRes.left().value();
135                 if (list != null) {
136                     for (ImmutablePair<String, String> pair1 : list1) {
137                         String uid = pair1.left;
138                         String UUID = pair1.right;
139                         artifactsUid.add(uid);
140                         artifactsUUID.add(UUID);
141                     }
142                     groupInstance.setGroupInstanceArtifacts(artifactsUid);
143                     groupInstance.setGroupInstanceArtifactsUuid(artifactsUUID);
144                 }
145             }
146             groupInstanceRes.add(groupInstance);
147             log.debug("GroupInstance {} was added to list ", groupInstance.getUniqueId());
148         }
149         result = Either.left(groupInstanceRes);
150         return result;
151     }
152
153     public Either<Integer, StorageOperationStatus> increaseAndGetGroupInstancePropertyCounter(String instanceId) {
154         return propertyOperation.increaseAndGetObjInstancePropertyCounter(instanceId, NodeTypeEnum.GroupInstance);
155     }
156
157     public Either<ComponentInstanceProperty, StorageOperationStatus> addPropertyValueToGroupInstance(ComponentInstanceProperty groupInstanceProperty,
158                                                                                                      String groupInstanceId, Integer index,
159                                                                                                      boolean inTransaction) {
160         /// #RULES SUPPORT
161
162         /// Ignore rules received from client till support
163         groupInstanceProperty.setRules(null);
164         ///
165
166         ///
167         Either<ComponentInstanceProperty, StorageOperationStatus> result = null;
168         try {
169             Either<PropertyValueData, JanusGraphOperationStatus> eitherStatus = addPropertyToGroupInstance(groupInstanceProperty, groupInstanceId,
170                 index);
171             if (eitherStatus.isRight()) {
172                 log.error("Failed to add property value {} to resource instance {} in Graph. status is {}", groupInstanceProperty, groupInstanceId,
173                     eitherStatus.right().value().name());
174                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherStatus.right().value()));
175                 return result;
176             } else {
177                 PropertyValueData propertyValueData = eitherStatus.left().value();
178                 ComponentInstanceProperty propertyValueResult = propertyOperation
179                     .buildResourceInstanceProperty(propertyValueData, groupInstanceProperty);
180                 log.debug("The returned GroupInstanceProperty is {}", propertyValueResult);
181                 Either<String, JanusGraphOperationStatus> findDefaultValue = propertyOperation
182                     .findDefaultValueFromSecondPosition(groupInstanceProperty.getPath(), groupInstanceProperty.getUniqueId(),
183                         groupInstanceProperty.getDefaultValue());
184                 if (findDefaultValue.isRight()) {
185                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(findDefaultValue.right().value()));
186                     return result;
187                 }
188                 String defaultValue = findDefaultValue.left().value();
189                 propertyValueResult.setDefaultValue(defaultValue);
190                 log.debug("The returned default value in ResourceInstanceProperty is {}", defaultValue);
191                 result = Either.left(propertyValueResult);
192                 return result;
193             }
194         } finally {
195             if (!inTransaction) {
196                 if (result == null || result.isRight()) {
197                     log.error("Going to execute rollback on graph.");
198                     janusGraphGenericDao.rollback();
199                 } else {
200                     log.debug("Going to execute commit on graph.");
201                     janusGraphGenericDao.commit();
202                 }
203             }
204         }
205     }
206
207     public Either<ComponentInstanceProperty, StorageOperationStatus> updatePropertyValueInGroupInstance(
208         ComponentInstanceProperty gropuInstanceProperty, String groupInstanceId, boolean inTransaction) {
209         // TODO Auto-generated method stub
210
211         // change Propety class
212         return null;
213     }
214
215     public void generateCustomizationUUID(GroupInstance groupInstance) {
216         UUID uuid = UUID.randomUUID();
217         groupInstance.setCustomizationUUID(uuid.toString());
218     }
219
220     /**
221      * add property to resource instance
222      *
223      * @param index
224      * @return
225      */
226     public Either<PropertyValueData, JanusGraphOperationStatus> addPropertyToGroupInstance(ComponentInstanceProperty groupInstanceProperty,
227                                                                                            String groupInstanceId, Integer index) {
228         Either<GroupInstanceData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
229             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.GroupInstance), groupInstanceId, GroupInstanceData.class);
230         if (findResInstanceRes.isRight()) {
231             JanusGraphOperationStatus status = findResInstanceRes.right().value();
232             if (status == JanusGraphOperationStatus.NOT_FOUND) {
233                 status = JanusGraphOperationStatus.INVALID_ID;
234             }
235             return Either.right(status);
236         }
237         String propertyId = groupInstanceProperty.getUniqueId();
238         Either<PropertyData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
239             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Property), propertyId, PropertyData.class);
240         if (findPropertyDefRes.isRight()) {
241             JanusGraphOperationStatus status = findPropertyDefRes.right().value();
242             if (status == JanusGraphOperationStatus.NOT_FOUND) {
243                 status = JanusGraphOperationStatus.INVALID_ID;
244             }
245             return Either.right(status);
246         }
247         String valueUniqueUid = groupInstanceProperty.getValueUniqueUid();
248         if (valueUniqueUid == null) {
249             PropertyData propertyData = findPropertyDefRes.left().value();
250             GroupInstanceData resourceInstanceData = findResInstanceRes.left().value();
251             ImmutablePair<JanusGraphOperationStatus, String> isPropertyValueExists = propertyOperation.findPropertyValue(groupInstanceId, propertyId);
252             if (isPropertyValueExists.getLeft() == JanusGraphOperationStatus.ALREADY_EXIST) {
253                 log.debug("The property {} already added to the resource instance {}", propertyId, groupInstanceId);
254                 groupInstanceProperty.setValueUniqueUid(isPropertyValueExists.getRight());
255                 Either<PropertyValueData, JanusGraphOperationStatus> updatePropertyOfResourceInstance = updatePropertyOfGroupInstance(
256                     groupInstanceProperty, groupInstanceId);
257                 if (updatePropertyOfResourceInstance.isRight()) {
258                     BeEcompErrorManager.getInstance().logInternalFlowError(UPDATE_PROPERTY_VALUE_ON_COMPONENT_INSTANCE,
259                         FAILED_TO_UPDATE_PROPERTY_VALUE_ON_INSTANCE_STATUS_IS + updatePropertyOfResourceInstance.right().value(),
260                         ErrorSeverity.ERROR);
261                     return Either.right(updatePropertyOfResourceInstance.right().value());
262                 }
263                 return Either.left(updatePropertyOfResourceInstance.left().value());
264             }
265             if (isPropertyValueExists.getLeft() != JanusGraphOperationStatus.NOT_FOUND) {
266                 log.debug("After finding property value of {} on componenet instance {}", propertyId, groupInstanceId);
267                 return Either.right(isPropertyValueExists.getLeft());
268             }
269             String innerType = null;
270             PropertyDataDefinition propDataDef = propertyData.getPropertyDataDefinition();
271             String propertyType = propDataDef.getType();
272             String value = groupInstanceProperty.getValue();
273             ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
274             if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
275                 SchemaDefinition def = propDataDef.getSchema();
276                 if (def == null) {
277                     log.debug("Schema doesn't exists for property of type {}", type);
278                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
279                 }
280                 PropertyDataDefinition propDef = def.getProperty();
281                 if (propDef == null) {
282                     log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
283                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
284                 }
285                 innerType = propDef.getType();
286             }
287             log.debug("Before validateAndUpdatePropertyValue");
288             Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes = dataTypeCache.getAll();
289             if (allDataTypes.isRight()) {
290                 JanusGraphOperationStatus status = allDataTypes.right().value();
291                 BeEcompErrorManager.getInstance()
292                     .logInternalFlowError(UPDATE_PROPERTY_VALUE_ON_COMPONENT_INSTANCE, FAILED_TO_UPDATE_PROPERTY_VALUE_ON_INSTANCE_STATUS_IS + status,
293                         ErrorSeverity.ERROR);
294                 return Either.right(status);
295             }
296             Either<Object, Boolean> isValid = propertyOperation
297                 .validateAndUpdatePropertyValue(propertyType, value, innerType, allDataTypes.left().value());
298             log.debug("After validateAndUpdatePropertyValue. isValid = {}", isValid);
299             String newValue = value;
300             if (isValid.isRight()) {
301                 Boolean res = isValid.right().value();
302                 if (!res) {
303                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
304                 }
305             } else {
306                 Object object = isValid.left().value();
307                 if (object != null) {
308                     newValue = object.toString();
309                 }
310             }
311             String uniqueId = UniqueIdBuilder.buildResourceInstancePropertyValueUid(resourceInstanceData.getUniqueId(), index);
312             PropertyValueData propertyValueData = new PropertyValueData();
313             propertyValueData.setUniqueId(uniqueId);
314             propertyValueData.setValue(newValue);
315             log.debug("Before validateAndUpdateRules");
316             ImmutablePair<String, Boolean> pair = propertyOperation
317                 .validateAndUpdateRules(propertyType, groupInstanceProperty.getRules(), innerType, allDataTypes.left().value(), false);
318             log.debug("After validateAndUpdateRules. pair = {}", pair);
319             if (pair.getRight() != null && !pair.getRight()) {
320                 BeEcompErrorManager.getInstance()
321                     .logBeInvalidValueError("Add property value", pair.getLeft(), groupInstanceProperty.getName(), propertyType);
322                 return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
323             }
324             propertyOperation.addRulesToNewPropertyValue(propertyValueData, groupInstanceProperty, groupInstanceId);
325             log.debug("Before adding property value to graph {}", propertyValueData);
326             Either<PropertyValueData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
327                 .createNode(propertyValueData, PropertyValueData.class);
328             log.debug("After adding property value to graph {}", propertyValueData);
329             if (createNodeResult.isRight()) {
330                 JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
331                 return Either.right(operationStatus);
332             }
333             propertyValueData = createNodeResult.left().value();
334             Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao
335                 .createRelation(propertyValueData, propertyData, GraphEdgeLabels.PROPERTY_IMPL, null);
336             if (createRelResult.isRight()) {
337                 JanusGraphOperationStatus operationStatus = createRelResult.right().value();
338                 log.error("Failed to associate property value {} to property {} in graph. status is {}", uniqueId, propertyId, operationStatus);
339                 return Either.right(operationStatus);
340             }
341             createRelResult = janusGraphGenericDao.createRelation(resourceInstanceData, propertyValueData, GraphEdgeLabels.PROPERTY_VALUE, null);
342             if (createRelResult.isRight()) {
343                 JanusGraphOperationStatus operationStatus = createRelResult.right().value();
344                 log.error("Failed to associate resource instance {} property value {} in graph. status is {}", groupInstanceId, uniqueId,
345                     operationStatus);
346                 return Either.right(operationStatus);
347             }
348             return Either.left(propertyValueData);
349         } else {
350             log.error("property value already exists.");
351             return Either.right(JanusGraphOperationStatus.ALREADY_EXIST);
352         }
353     }
354
355     /**
356      * update value of attribute on resource instance
357      *
358      * @return
359      */
360     public Either<PropertyValueData, JanusGraphOperationStatus> updatePropertyOfGroupInstance(ComponentInstanceProperty groupInstanceProerty,
361                                                                                               String groupInstanceId) {
362         Wrapper<JanusGraphOperationStatus> errorWrapper = new Wrapper<>();
363         UpdateDataContainer<PropertyData, PropertyValueData> updateDataContainer = new UpdateDataContainer<>(GraphEdgeLabels.PROPERTY_IMPL,
364             (() -> PropertyData.class), (() -> PropertyValueData.class), NodeTypeEnum.Property, NodeTypeEnum.PropertyValue);
365         preUpdateElementOfResourceInstanceValidations(updateDataContainer, groupInstanceProerty, groupInstanceId, errorWrapper);
366         if (!errorWrapper.isEmpty()) {
367             return Either.right(errorWrapper.getInnerElement());
368         } else {
369             String value = groupInstanceProerty.getValue();
370             // Specific Validation Logic
371             PropertyData propertyData = updateDataContainer.getDataWrapper().getInnerElement();
372             String innerType = null;
373             PropertyDataDefinition propDataDef = propertyData.getPropertyDataDefinition();
374             String propertyType = propDataDef.getType();
375             ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
376             log.debug("The type of the property {} is {}", propertyData.getUniqueId(), propertyType);
377             if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
378                 SchemaDefinition def = propDataDef.getSchema();
379                 if (def == null) {
380                     log.debug("Schema doesn't exists for property of type {}", type);
381                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
382                 }
383                 PropertyDataDefinition propDef = def.getProperty();
384                 if (propDef == null) {
385                     log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
386                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
387                 }
388                 innerType = propDef.getType();
389             }
390             // Specific Update Logic
391             Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes = dataTypeCache.getAll();
392             if (allDataTypes.isRight()) {
393                 JanusGraphOperationStatus status = allDataTypes.right().value();
394                 BeEcompErrorManager.getInstance()
395                     .logInternalFlowError(UPDATE_PROPERTY_VALUE_ON_COMPONENT_INSTANCE, FAILED_TO_UPDATE_PROPERTY_VALUE_ON_INSTANCE_STATUS_IS + status,
396                         ErrorSeverity.ERROR);
397                 return Either.right(status);
398             }
399             Either<Object, Boolean> isValid = propertyOperation
400                 .validateAndUpdatePropertyValue(propertyType, value, innerType, allDataTypes.left().value());
401             String newValue = value;
402             if (isValid.isRight()) {
403                 Boolean res = isValid.right().value();
404                 if (!res) {
405                     return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
406                 }
407             } else {
408                 Object object = isValid.left().value();
409                 if (object != null) {
410                     newValue = object.toString();
411                 }
412             }
413             PropertyValueData propertyValueData = updateDataContainer.getValueDataWrapper().getInnerElement();
414             log.debug("Going to update property value from {} to {}", propertyValueData.getValue(), newValue);
415             propertyValueData.setValue(newValue);
416             ImmutablePair<String, Boolean> pair = propertyOperation
417                 .validateAndUpdateRules(propertyType, groupInstanceProerty.getRules(), innerType, allDataTypes.left().value(), true);
418             if (pair.getRight() != null && !pair.getRight()) {
419                 BeEcompErrorManager.getInstance()
420                     .logBeInvalidValueError("Add property value", pair.getLeft(), groupInstanceProerty.getName(), propertyType);
421                 return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT);
422             }
423             propertyOperation.updateRulesInPropertyValue(propertyValueData, groupInstanceProerty, groupInstanceId);
424             Either<PropertyValueData, JanusGraphOperationStatus> updateRes = janusGraphGenericDao
425                 .updateNode(propertyValueData, PropertyValueData.class);
426             if (updateRes.isRight()) {
427                 JanusGraphOperationStatus status = updateRes.right().value();
428                 return Either.right(status);
429             } else {
430                 return Either.left(updateRes.left().value());
431             }
432         }
433     }
434
435     private <SomeData extends GraphNode, SomeValueData extends GraphNode> void preUpdateElementOfResourceInstanceValidations(
436         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceProerty,
437         String resourceInstanceId, Wrapper<JanusGraphOperationStatus> errorWrapper) {
438         if (errorWrapper.isEmpty()) {
439             // Verify VFC instance Exist
440             validateGIExist(resourceInstanceId, errorWrapper);
441         }
442         if (errorWrapper.isEmpty()) {
443             // Example: Verify Property connected to VFC exist
444             validateElementConnectedToComponentExist(updateDataContainer, resourceInstanceProerty, errorWrapper);
445         }
446         if (errorWrapper.isEmpty()) {
447             // Example: Verify PropertyValue connected to VFC Instance exist
448             validateElementConnectedToComponentInstanceExist(updateDataContainer, resourceInstanceProerty, errorWrapper);
449         }
450         if (errorWrapper.isEmpty()) {
451             // Example: Verify PropertyValue connected Property
452             validateElementConnectedToInstance(updateDataContainer, resourceInstanceProerty, errorWrapper);
453         }
454     }
455
456     private <SomeData extends GraphNode, SomeValueData extends GraphNode> void validateElementConnectedToInstance(
457         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceProerty,
458         Wrapper<JanusGraphOperationStatus> errorWrapper) {
459         Either<ImmutablePair<SomeData, GraphEdge>, JanusGraphOperationStatus> child = janusGraphGenericDao
460             .getChild(UniqueIdBuilder.getKeyByNodeType(updateDataContainer.getNodeTypeValue()), resourceInstanceProerty.getValueUniqueUid(),
461                 updateDataContainer.getGraphEdge(), updateDataContainer.getNodeType(), updateDataContainer.getSomeDataClassGen().get());
462         if (child.isRight()) {
463             JanusGraphOperationStatus status = child.right().value();
464             if (status == JanusGraphOperationStatus.NOT_FOUND) {
465                 status = JanusGraphOperationStatus.INVALID_ID;
466             }
467             errorWrapper.setInnerElement(status);
468         } else {
469             updateDataContainer.getDataWrapper().setInnerElement(child.left().value().left);
470         }
471     }
472
473     private <SomeValueData extends GraphNode, SomeData extends GraphNode> void validateElementConnectedToComponentInstanceExist(
474         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceProerty,
475         Wrapper<JanusGraphOperationStatus> errorWrapper) {
476         String valueUniqueUid = resourceInstanceProerty.getValueUniqueUid();
477         if (valueUniqueUid == null) {
478             errorWrapper.setInnerElement(JanusGraphOperationStatus.INVALID_ID);
479         } else {
480             Either<SomeValueData, JanusGraphOperationStatus> findPropertyValueRes = janusGraphGenericDao
481                 .getNode(UniqueIdBuilder.getKeyByNodeType(updateDataContainer.getNodeTypeValue()), valueUniqueUid,
482                     updateDataContainer.getSomeValueDataClassGen().get());
483             if (findPropertyValueRes.isRight()) {
484                 JanusGraphOperationStatus status = findPropertyValueRes.right().value();
485                 if (status == JanusGraphOperationStatus.NOT_FOUND) {
486                     status = JanusGraphOperationStatus.INVALID_ID;
487                 }
488                 errorWrapper.setInnerElement(status);
489             } else {
490                 updateDataContainer.getValueDataWrapper().setInnerElement(findPropertyValueRes.left().value());
491             }
492         }
493     }
494
495     private <SomeData extends GraphNode, SomeValueData extends GraphNode> void validateElementConnectedToComponentExist(
496         UpdateDataContainer<SomeData, SomeValueData> updateDataContainer, IComponentInstanceConnectedElement resourceInstanceElementConnected,
497         Wrapper<JanusGraphOperationStatus> errorWrapper) {
498         String uniqueId = resourceInstanceElementConnected.getUniqueId();
499         Either<SomeData, JanusGraphOperationStatus> findPropertyDefRes = janusGraphGenericDao
500             .getNode(UniqueIdBuilder.getKeyByNodeType(updateDataContainer.getNodeType()), uniqueId, updateDataContainer.getSomeDataClassGen().get());
501         if (findPropertyDefRes.isRight()) {
502             JanusGraphOperationStatus status = findPropertyDefRes.right().value();
503             errorWrapper.setInnerElement(status);
504         }
505     }
506
507     private void validateGIExist(String resourceInstanceId, Wrapper<JanusGraphOperationStatus> errorWrapper) {
508         validateGIExist(resourceInstanceId, null, errorWrapper);
509     }
510
511     private void validateGIExist(String resourceInstanceId, Wrapper<GroupInstanceData> compInsDataWrapper,
512                                  Wrapper<JanusGraphOperationStatus> errorWrapper) {
513         validateElementExistInGraph(resourceInstanceId, NodeTypeEnum.GroupInstance, () -> GroupInstanceData.class, compInsDataWrapper, errorWrapper);
514     }
515
516     public <ElementData extends GraphNode> void validateElementExistInGraph(String elementUniqueId, NodeTypeEnum elementNodeType,
517                                                                             Supplier<Class<ElementData>> elementClassGen,
518                                                                             Wrapper<ElementData> elementDataWrapper,
519                                                                             Wrapper<JanusGraphOperationStatus> errorWrapper) {
520         Either<ElementData, JanusGraphOperationStatus> findResInstanceRes = janusGraphGenericDao
521             .getNode(UniqueIdBuilder.getKeyByNodeType(elementNodeType), elementUniqueId, elementClassGen.get());
522         if (findResInstanceRes.isRight()) {
523             JanusGraphOperationStatus status = findResInstanceRes.right().value();
524             if (status == JanusGraphOperationStatus.NOT_FOUND) {
525                 status = JanusGraphOperationStatus.INVALID_ID;
526             }
527             errorWrapper.setInnerElement(status);
528         } else {
529             if (elementDataWrapper != null) {
530                 elementDataWrapper.setInnerElement(findResInstanceRes.left().value());
531             }
532         }
533     }
534
535     private void buildGroupInstanceFromGroup(GroupInstance groupInstance, GroupDefinition groupDefinition,
536                                              Map<String, PropertyValueData> groupInstancePropertyValues) {
537         groupInstance.setGroupName(groupDefinition.getName());
538         groupInstance.setInvariantUUID(groupDefinition.getInvariantUUID());
539         groupInstance.setDescription(groupDefinition.getDescription());
540         groupInstance.setVersion(groupDefinition.getVersion());
541         groupInstance.setArtifacts(groupDefinition.getArtifacts());
542         groupInstance.setArtifactsUuid(groupDefinition.getArtifactsUuid());
543         groupInstance.setType(groupDefinition.getType());
544         groupInstance.setGroupUUID(groupDefinition.getGroupUUID());
545         List<GroupInstanceProperty> groupInstanceProperties = groupDefinition.convertToGroupProperties()
546             //converts List of GroupProperties to List of GroupInstanceProperties and updates it with group instance property data
547             .stream().map(p -> getUpdatedConvertedProperty(p, groupInstancePropertyValues)).collect(Collectors.toList());
548         groupInstance.convertFromGroupInstancesProperties(groupInstanceProperties);
549     }
550
551     private GroupInstanceProperty getUpdatedConvertedProperty(GroupProperty groupProperty,
552                                                               Map<String, PropertyValueData> groupInstancePropertyValues) {
553         GroupInstanceProperty updatedProperty = new GroupInstanceProperty(groupProperty, groupProperty.getValue());
554         if (!MapUtils.isEmpty(groupInstancePropertyValues) && groupInstancePropertyValues.containsKey(groupProperty.getName())) {
555             PropertyValueData groupInstancePropertyValue = groupInstancePropertyValues.get(groupProperty.getName());
556             updatedProperty.setValue(groupInstancePropertyValue.getValue());
557             updatedProperty.setValueUniqueUid(groupInstancePropertyValue.getUniqueId());
558         }
559         return updatedProperty;
560     }
561
562     private Either<List<ImmutablePair<String, String>>, JanusGraphOperationStatus> getGroupArtifactsPairs(String groupUniqueId) {
563         Either<List<ImmutablePair<String, String>>, JanusGraphOperationStatus> result = null;
564         Either<List<ImmutablePair<ArtifactData, GraphEdge>>, JanusGraphOperationStatus> childrenNodes = janusGraphGenericDao
565             .getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.GroupInstance), groupUniqueId, GraphEdgeLabels.GROUP_ARTIFACT_REF,
566                 NodeTypeEnum.ArtifactRef, ArtifactData.class);
567         if (childrenNodes.isRight()) {
568             JanusGraphOperationStatus status = childrenNodes.right().value();
569             if (status == JanusGraphOperationStatus.NOT_FOUND) {
570                 status = JanusGraphOperationStatus.OK;
571             }
572             result = Either.right(status);
573         } else {
574             List<ImmutablePair<String, String>> artifactsList = new ArrayList<>();
575             List<ImmutablePair<ArtifactData, GraphEdge>> list = childrenNodes.left().value();
576             if (list != null) {
577                 for (ImmutablePair<ArtifactData, GraphEdge> pair : list) {
578                     ArtifactData artifactData = pair.getKey();
579                     String uniqueId = artifactData.getArtifactDataDefinition().getUniqueId();
580                     String UUID = artifactData.getArtifactDataDefinition().getArtifactUUID();
581                     ImmutablePair<String, String> artifact = new ImmutablePair<>(uniqueId, UUID);
582                     artifactsList.add(artifact);
583                 }
584             }
585             log.debug("The artifacts list related to group {} is {}", groupUniqueId, artifactsList);
586             result = Either.left(artifactsList);
587         }
588         return result;
589     }
590
591     public StorageOperationStatus dissociateAndAssociateGroupsInstanceFromArtifact(String componentId, NodeTypeEnum componentTypeEnum,
592                                                                                    String oldArtifactId, ArtifactData newArtifact) {
593         return this.dissociateAndAssociateGroupsInstanceFromArtifactOnGraph(componentId, componentTypeEnum, oldArtifactId, newArtifact);
594     }
595
596     private StorageOperationStatus dissociateAndAssociateGroupsInstanceFromArtifactOnGraph(String componentId, NodeTypeEnum componentTypeEnum,
597                                                                                            String oldArtifactId, ArtifactData newArtifact) {
598         Either<List<GroupInstance>, StorageOperationStatus> allGroupsFromGraph = getAllGroupInstances(componentId, componentTypeEnum);
599         if (allGroupsFromGraph.isRight()) {
600             return allGroupsFromGraph.right().value();
601         }
602         List<GroupInstance> allGroups = allGroupsFromGraph.left().value();
603         if (allGroups == null || allGroups.isEmpty()) {
604             return StorageOperationStatus.OK;
605         }
606         // Find all groups which contains this artifact id
607         List<GroupInstance> associatedGroups = allGroups.stream()
608             .filter(p -> p.getGroupInstanceArtifacts() != null && p.getGroupInstanceArtifacts().contains(oldArtifactId)).collect(Collectors.toList());
609         if (associatedGroups != null && !associatedGroups.isEmpty()) {
610             log.debug("The groups {} contains the artifact {}",
611                 associatedGroups.stream().map(GroupInstanceDataDefinition::getName).collect(Collectors.toList()), oldArtifactId);
612             UniqueIdData oldArtifactData = new UniqueIdData(NodeTypeEnum.ArtifactRef, oldArtifactId);
613             UniqueIdData newArtifactData = new UniqueIdData(NodeTypeEnum.ArtifactRef, newArtifact.getArtifactDataDefinition().getUniqueId());
614             Map<String, Object> props = new HashMap<>();
615             props.put(GraphPropertiesDictionary.NAME.getProperty(), newArtifactData.getLabel());
616             for (GroupInstance groupDefinition : associatedGroups) {
617                 UniqueIdData groupData = new UniqueIdData(NodeTypeEnum.GroupInstance, groupDefinition.getUniqueId());
618                 Either<GraphRelation, JanusGraphOperationStatus> deleteRelation = janusGraphGenericDao
619                     .deleteRelation(groupData, oldArtifactData, GraphEdgeLabels.GROUP_ARTIFACT_REF);
620                 log.trace("After dissociate group {} from artifact {}", groupDefinition.getName(), oldArtifactId);
621                 if (deleteRelation.isRight()) {
622                     JanusGraphOperationStatus status = deleteRelation.right().value();
623                     if (status == JanusGraphOperationStatus.NOT_FOUND) {
624                         status = JanusGraphOperationStatus.INVALID_ID;
625                     }
626                     return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
627                 }
628                 Either<GraphRelation, JanusGraphOperationStatus> createRelation = janusGraphGenericDao
629                     .createRelation(groupData, newArtifactData, GraphEdgeLabels.GROUP_ARTIFACT_REF, props);
630                 log.trace("After associate group {} to artifact {}", groupDefinition.getName(), newArtifact.getUniqueIdKey());
631                 if (createRelation.isRight()) {
632                     JanusGraphOperationStatus status = createRelation.right().value();
633                     if (status == JanusGraphOperationStatus.NOT_FOUND) {
634                         status = JanusGraphOperationStatus.INVALID_ID;
635                     }
636                     return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
637                 }
638             }
639         }
640         return StorageOperationStatus.OK;
641     }
642
643     private Either<Map<String, PropertyValueData>, JanusGraphOperationStatus> getAllGroupInstancePropertyValuesData(GroupInstanceData groupInstData) {
644         Either<Map<String, PropertyValueData>, JanusGraphOperationStatus> result = null;
645         try {
646             Either<List<ImmutablePair<PropertyValueData, GraphEdge>>, JanusGraphOperationStatus> getPropertyValueChildrenRes = janusGraphGenericDao
647                 .getChildrenNodes(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), groupInstData.getUniqueId(), GraphEdgeLabels.PROPERTY_VALUE,
648                     NodeTypeEnum.PropertyValue, PropertyValueData.class, true);
649             if (getPropertyValueChildrenRes.isRight()) {
650                 JanusGraphOperationStatus status = getPropertyValueChildrenRes.right().value();
651                 log.debug("Failed to fetch property value nodes for group instance {}. Status is {}. ", groupInstData.getName(), status);
652                 if (status == JanusGraphOperationStatus.NOT_FOUND) {
653                     result = Either.left(null);
654                 } else {
655                     result = Either.right(status);
656                 }
657             } else {
658                 result = Either.left(getPropertyValueChildrenRes.left().value().stream().collect(Collectors
659                     .toMap(pair -> (String) (pair.getRight().getProperties().get(GraphPropertiesDictionary.PROPERTY_NAME.getProperty())),
660                         ImmutablePair::getLeft)));
661             }
662         } catch (Exception e) {
663             log.debug("The Exception occured during fetch group instance () property values. The message is {}. ", groupInstData.getName(),
664                 e.getMessage(), e);
665             if (result == null) {
666                 result = Either.right(JanusGraphOperationStatus.GENERAL_ERROR);
667             }
668         }
669         return result;
670     }
671
672     private static final class UpdateDataContainer<SomeData, SomeValueData> {
673
674         final Wrapper<SomeValueData> valueDataWrapper;
675         final Wrapper<SomeData> dataWrapper;
676         final GraphEdgeLabels graphEdge;
677         final Supplier<Class<SomeData>> someDataClassGen;
678         final Supplier<Class<SomeValueData>> someValueDataClassGen;
679         final NodeTypeEnum nodeType;
680         final NodeTypeEnum nodeTypeValue;
681
682         private UpdateDataContainer(GraphEdgeLabels graphEdge, Supplier<Class<SomeData>> someDataClassGen,
683                                     Supplier<Class<SomeValueData>> someValueDataClassGen, NodeTypeEnum nodeType, NodeTypeEnum nodeTypeValue) {
684             super();
685             this.valueDataWrapper = new Wrapper<>();
686             this.dataWrapper = new Wrapper<>();
687             this.graphEdge = graphEdge;
688             this.someDataClassGen = someDataClassGen;
689             this.someValueDataClassGen = someValueDataClassGen;
690             this.nodeType = nodeType;
691             this.nodeTypeValue = nodeTypeValue;
692         }
693
694         public Wrapper<SomeValueData> getValueDataWrapper() {
695             return valueDataWrapper;
696         }
697
698         public Wrapper<SomeData> getDataWrapper() {
699             return dataWrapper;
700         }
701
702         public GraphEdgeLabels getGraphEdge() {
703             return graphEdge;
704         }
705
706         public Supplier<Class<SomeData>> getSomeDataClassGen() {
707             return someDataClassGen;
708         }
709
710         public Supplier<Class<SomeValueData>> getSomeValueDataClassGen() {
711             return someValueDataClassGen;
712         }
713
714         public NodeTypeEnum getNodeType() {
715             return nodeType;
716         }
717
718         public NodeTypeEnum getNodeTypeValue() {
719             return nodeTypeValue;
720         }
721     }
722 }