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