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