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