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