af8414dc8117ee644eba8fbdd38c0641b3227f98
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsonjanusgraph / operations / BaseOperation.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.jsonjanusgraph.operations;
21
22 import fj.data.Either;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.UUID;
30 import java.util.stream.Collectors;
31 import org.apache.commons.collections.CollectionUtils;
32 import org.apache.commons.collections.MapUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.apache.commons.lang3.tuple.ImmutablePair;
35 import org.apache.commons.lang3.tuple.Pair;
36 import org.apache.tinkerpop.gremlin.structure.Direction;
37 import org.apache.tinkerpop.gremlin.structure.Edge;
38 import org.apache.tinkerpop.gremlin.structure.Vertex;
39 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
40 import org.janusgraph.core.JanusGraphVertex;
41 import org.openecomp.sdc.be.dao.impl.HealingPipelineDao;
42 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
43 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
44 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
45 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
46 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
47 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
48 import org.openecomp.sdc.be.dao.jsongraph.utils.IdBuilderUtils;
49 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
50 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
51 import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition;
52 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
53 import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition;
54 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
55 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
56 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
57 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
58 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
59 import org.openecomp.sdc.be.model.User;
60 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum;
61 import org.openecomp.sdc.be.model.operations.StorageException;
62 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
63 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
64 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
65 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
66 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
67 import org.openecomp.sdc.common.log.wrappers.Logger;
68 import org.openecomp.sdc.common.util.ValidationUtils;
69 import org.springframework.beans.factory.annotation.Autowired;
70
71 /**
72  * public abstract class BaseOperation provides base operation functionality and common fields
73  */
74 public abstract class BaseOperation {
75
76     public static final String VF_MODULE = "org.openecomp.groups.VfModule";
77     private static final String FAILED_REMOVE_TOSCA_DATA_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS = "Failed remove tosca data vertex of the tosca element {} by label {}. Status is {}. ";
78     private static final String FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS = "Failed to get child vertex of the tosca element {} by label {}. Status is {}. ";
79     private static final String FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS = "Failed to get tosca element {} upon adding the properties. Status is {}. ";
80     private static final Logger log = Logger.getLogger(BaseOperation.class.getName());
81     @Autowired
82     protected JanusGraphDao janusGraphDao;
83     @Autowired
84     protected NodeTypeOperation nodeTypeOperation;
85     @Autowired
86     protected TopologyTemplateOperation topologyTemplateOperation;
87     //    @Autowired
88     protected HealingPipelineDao healingPipelineDao;
89
90     public void setJanusGraphDao(JanusGraphDao janusGraphDao) {
91         this.janusGraphDao = janusGraphDao;
92     }
93
94     /**
95      * Returns reference to appropriate toscaTemplateOperation
96      *
97      * @param componentType
98      * @return
99      */
100     public ToscaElementOperation getToscaElementOperation(ComponentTypeEnum componentType) {
101         ToscaElementOperation operation;
102         switch (componentType) {
103             case SERVICE:
104             case RESOURCE:
105                 operation = topologyTemplateOperation;
106                 break;
107             default:
108                 operation = nodeTypeOperation;
109                 break;
110         }
111         return operation;
112     }
113
114     /**
115      * Returns reference to appropriate toscaTemplateOperation
116      *
117      * @param toscaElementType
118      * @return
119      */
120     public ToscaElementOperation getToscaElementOperation(ToscaElementTypeEnum toscaElementType) {
121         ToscaElementOperation operation;
122         switch (toscaElementType) {
123             case TOPOLOGY_TEMPLATE:
124                 operation = topologyTemplateOperation;
125                 break;
126             case NODE_TYPE:
127                 operation = nodeTypeOperation;
128                 break;
129             default:
130                 operation = null;
131                 break;
132         }
133         return operation;
134     }
135
136     /**
137      * Returns reference to appropriate toscaTemplateOperation
138      *
139      * @param toscaElementType
140      * @return
141      */
142     public ToscaElementOperation getToscaElementOperation(VertexTypeEnum toscaElementType) {
143         ToscaElementOperation operation;
144         switch (toscaElementType) {
145             case TOPOLOGY_TEMPLATE:
146                 operation = topologyTemplateOperation;
147                 break;
148             case NODE_TYPE:
149                 operation = nodeTypeOperation;
150                 break;
151             default:
152                 operation = null;
153                 break;
154         }
155         return operation;
156     }
157
158     /**
159      * Converts received vertex to User object
160      *
161      * @param ownerV
162      * @return
163      */
164     public User convertToUser(Vertex ownerV) {
165         User owner = new User();
166         owner.setUserId((String) ownerV.property(GraphPropertyEnum.USERID.getProperty()).value());
167         VertexProperty<Object> property = ownerV.property(GraphPropertyEnum.ROLE.getProperty());
168         if (property != null && property.isPresent()) {
169             owner.setRole((String) property.value());
170         }
171         property = ownerV.property(GraphPropertyEnum.FIRST_NAME.getProperty());
172         if (property != null && property.isPresent()) {
173             owner.setFirstName((String) ownerV.property(GraphPropertyEnum.FIRST_NAME.getProperty()).value());
174         }
175         property = ownerV.property(GraphPropertyEnum.LAST_NAME.getProperty());
176         if (property != null && property.isPresent()) {
177             owner.setLastName((String) ownerV.property(GraphPropertyEnum.LAST_NAME.getProperty()).value());
178         }
179         property = ownerV.property(GraphPropertyEnum.EMAIL.getProperty());
180         if (property != null && property.isPresent()) {
181             owner.setEmail((String) ownerV.property(GraphPropertyEnum.EMAIL.getProperty()).value());
182         }
183         property = ownerV.property(GraphPropertyEnum.LAST_LOGIN_TIME.getProperty());
184         if (property != null && property.isPresent()) {
185             owner.setLastLoginTime((Long) ownerV.property(GraphPropertyEnum.LAST_LOGIN_TIME.getProperty()).value());
186         }
187         return owner;
188     }
189
190     protected <T extends ToscaDataDefinition> Either<Map<String, T>, JanusGraphOperationStatus> getDataFromGraph(GraphVertex componentV,
191                                                                                                                  EdgeLabelEnum edgelabel) {
192         Either<Pair<GraphVertex, Map<String, T>>, JanusGraphOperationStatus> dataVertex = getDataAndVertexFromGraph(componentV, edgelabel);
193         if (dataVertex.isRight()) {
194             return Either.right(dataVertex.right().value());
195         }
196         Map<String, T> properties = dataVertex.left().value().getRight();
197         return Either.left(properties);
198     }
199
200     @SuppressWarnings("unchecked")
201     protected <T extends ToscaDataDefinition> Either<Pair<GraphVertex, Map<String, T>>, JanusGraphOperationStatus> getDataAndVertexFromGraph(
202         GraphVertex componentV, EdgeLabelEnum edgelabel) {
203         Either<GraphVertex, JanusGraphOperationStatus> dataVertex = getDataVertex(componentV, edgelabel);
204         if (dataVertex.isRight()) {
205             return Either.right(dataVertex.right().value());
206         }
207         GraphVertex propV = dataVertex.left().value();
208         Map<String, T> properties = (Map<String, T>) propV.getJson();
209         Pair<GraphVertex, Map<String, T>> pair = new ImmutablePair<>(propV, properties);
210         return Either.left(pair);
211     }
212
213     protected <T extends ToscaDataDefinition> Either<GraphVertex, JanusGraphOperationStatus> getDataVertex(GraphVertex componentV,
214                                                                                                            EdgeLabelEnum edgelabel) {
215         Either<GraphVertex, JanusGraphOperationStatus> childVertex = janusGraphDao.getChildVertex(componentV, edgelabel, JsonParseFlagEnum.ParseJson);
216         if (childVertex.isRight()) {
217             if (childVertex.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
218                 log.debug("failed to fetch {} for tosca element with id {}, error {}", edgelabel, componentV.getUniqueId(),
219                     childVertex.right().value());
220             }
221             return Either.right(childVertex.right().value());
222         }
223         GraphVertex propV = childVertex.left().value();
224         return Either.left(propV);
225     }
226
227     /**
228      * Returns tosca data belonging to tosca element specified by uid according received label
229      *
230      * @param toscaElementUid
231      * @param edgelabel
232      * @return
233      */
234     public <T extends ToscaDataDefinition> Either<Map<String, T>, JanusGraphOperationStatus> getDataFromGraph(String toscaElementUid,
235                                                                                                               EdgeLabelEnum edgelabel) {
236         Either<Map<String, T>, JanusGraphOperationStatus> result = null;
237         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
238         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
239         if (getToscaElementRes.isRight()) {
240             JanusGraphOperationStatus status = getToscaElementRes.right().value();
241             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get tosca element {} upon getting tosca data from graph. Status is {}. ",
242                 toscaElementUid, status);
243             result = Either.right(status);
244         }
245         if (result == null) {
246             result = getDataFromGraph(getToscaElementRes.left().value(), edgelabel);
247         }
248         return result;
249     }
250
251     public Either<GraphVertex, JanusGraphOperationStatus> findUserVertex(String userId) {
252         return janusGraphDao.getVertexByPropertyAndLabel(GraphPropertyEnum.USERID, userId, VertexTypeEnum.USER, JsonParseFlagEnum.NoParse);
253     }
254
255     /**
256      * @param elemementId
257      * @param label
258      * @return
259      */
260     public Either<Boolean, StorageOperationStatus> isCloneNeeded(String elemementId, EdgeLabelEnum label) {
261         Either<GraphVertex, JanusGraphOperationStatus> vertexById = janusGraphDao.getVertexById(elemementId);
262         if (vertexById.isRight()) {
263             log.debug("Failed to fetch element by id {} error {}", elemementId, vertexById.right().value());
264             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexById.right().value()));
265         }
266         GraphVertex toscaElementVertex = vertexById.left().value();
267         Either<GraphVertex, JanusGraphOperationStatus> childVertex = janusGraphDao
268             .getChildVertex(toscaElementVertex, label, JsonParseFlagEnum.NoParse);
269         if (childVertex.isRight()) {
270             if (childVertex.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
271                 log.debug("failed to fetch {} for tosca element with id {}, error {}", label, toscaElementVertex.getUniqueId(),
272                     childVertex.right().value());
273                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(childVertex.right().value()));
274             }
275             return Either.left(Boolean.FALSE);
276         }
277         GraphVertex dataVertex = childVertex.left().value();
278         Iterator<Edge> edges = dataVertex.getVertex().edges(Direction.IN, label.name());
279         int edgeCount = 0;
280         while (edges.hasNext()) {
281             edges.next();
282             ++edgeCount;
283         }
284         if (edgeCount > 1) {
285             return Either.left(Boolean.TRUE);
286         } else {
287             return Either.left(Boolean.FALSE);
288         }
289     }
290
291     protected Either<GraphVertex, JanusGraphOperationStatus> updateOrCopyOnUpdate(GraphVertex dataVertex, GraphVertex toscaElementVertex,
292                                                                                   EdgeLabelEnum label) {
293         Iterator<Edge> edges = dataVertex.getVertex().edges(Direction.IN, label.name());
294         int edgeCount = 0;
295         Edge edgeToRemove = null;
296         while (edges.hasNext()) {
297             Edge edge = edges.next();
298             ++edgeCount;
299             Vertex outVertex = edge.outVertex();
300             String outId = (String) janusGraphDao.getProperty((JanusGraphVertex) outVertex, GraphPropertyEnum.UNIQUE_ID.getProperty());
301             if (toscaElementVertex.getUniqueId().equals(outId)) {
302                 edgeToRemove = edge;
303             }
304         }
305         if (edgeToRemove == null) {
306             log.debug("No edges {} from vertex {} to vertex {}", label, toscaElementVertex.getUniqueId(), dataVertex.getUniqueId());
307             return Either.right(JanusGraphOperationStatus.GENERAL_ERROR);
308         }
309         switch (edgeCount) {
310             case 0:
311                 // error
312                 log.debug("No edges {} to vertex {}", label, dataVertex.getUniqueId());
313                 return Either.right(JanusGraphOperationStatus.GENERAL_ERROR);
314             case 1:
315                 // update
316                 log.trace("Only one edge {} to vertex {}. Update vertex", label, dataVertex.getUniqueId());
317                 return janusGraphDao.updateVertex(dataVertex);
318             default:
319                 // copy on update
320                 log.trace("More than one edge {} to vertex {}. Need to clone vertex", label, dataVertex.getUniqueId());
321                 return cloneDataVertex(dataVertex, toscaElementVertex, label, edgeToRemove);
322         }
323     }
324
325     private Either<GraphVertex, JanusGraphOperationStatus> cloneDataVertex(GraphVertex dataVertex, GraphVertex toscaElementVertex,
326                                                                            EdgeLabelEnum label, Edge edgeToRemove) {
327         GraphVertex newDataVertex = new GraphVertex(dataVertex.getLabel());
328         String id = IdBuilderUtils.generateChildId(toscaElementVertex.getUniqueId(), dataVertex.getLabel());
329         newDataVertex.cloneData(dataVertex);
330         newDataVertex.setUniqueId(id);
331         Either<GraphVertex, JanusGraphOperationStatus> createVertex = janusGraphDao.createVertex(newDataVertex);
332         if (createVertex.isRight()) {
333             log.debug("Failed to clone data vertex for {} error {}", dataVertex.getUniqueId(), createVertex.right().value());
334             return createVertex;
335         }
336         newDataVertex = createVertex.left().value();
337         JanusGraphOperationStatus createEdge = janusGraphDao
338             .createEdge(toscaElementVertex, newDataVertex, label, janusGraphDao.getEdgeProperties(edgeToRemove));
339         if (createEdge != JanusGraphOperationStatus.OK) {
340             log.debug("Failed to associate vertex {} to vertex {}, error {}", toscaElementVertex.getUniqueId(), newDataVertex.getUniqueId(),
341                 createEdge);
342             return Either.right(createEdge);
343         }
344         edgeToRemove.remove();
345         return Either.left(newDataVertex);
346     }
347
348     public Either<GraphVertex, StorageOperationStatus> associateElementToData(GraphVertex element, VertexTypeEnum vertexLabel,
349                                                                               EdgeLabelEnum edgeLabel,
350                                                                               Map<String, ? extends ToscaDataDefinition> data) {
351         GraphVertex dataV = new GraphVertex(vertexLabel);
352         String id = IdBuilderUtils.generateChildId(element.getUniqueId(), vertexLabel);
353         dataV.setUniqueId(id);
354         dataV.setJson(data);
355         Either<GraphVertex, JanusGraphOperationStatus> createVertex = janusGraphDao.createVertex(dataV);
356         if (createVertex.isRight()) {
357             log.trace("Failed to create {} vertex for type node {}", vertexLabel, element.getUniqueId());
358             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createVertex.right().value()));
359         }
360         dataV = createVertex.left().value();
361         JanusGraphOperationStatus createEdgeStatus = janusGraphDao.createEdge(element.getVertex(), dataV.getVertex(), edgeLabel, new HashMap<>());
362         if (createEdgeStatus != JanusGraphOperationStatus.OK) {
363             log.trace("Failed to create {} vertex for type node {}", vertexLabel, element.getUniqueId());
364             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdgeStatus));
365         }
366         return Either.left(dataV);
367     }
368
369     /**
370      * Adds tosca data element to tosca element according received labels
371      *
372      * @param toscaElement
373      * @param edgeLabel
374      * @param vertexLabel
375      * @param toscaData
376      * @param mapKeyField
377      * @return
378      */
379     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataToToscaElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
380                                                                                              VertexTypeEnum vertexLabel, T toscaData,
381                                                                                              JsonPresentationFields mapKeyField) {
382         List<T> toscaDataList = new ArrayList<>();
383         toscaDataList.add(toscaData);
384         return addToscaDataToToscaElement(toscaElement, edgeLabel, vertexLabel, toscaDataList, mapKeyField);
385     }
386
387     /**
388      * Adds list of tosca data deep elements to tosca element according received labels
389      *
390      * @param toscaElement
391      * @param edgeLabel
392      * @param vertexLabel
393      * @param toscaDataList
394      * @param pathKeys
395      * @param mapKeyField
396      * @return
397      */
398     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataDeepElementsToToscaElement(GraphVertex toscaElement,
399                                                                                                          EdgeLabelEnum edgeLabel,
400                                                                                                          VertexTypeEnum vertexLabel,
401                                                                                                          List<T> toscaDataList, List<String> pathKeys,
402                                                                                                          JsonPresentationFields mapKeyField) {
403         return updateOrAddToscaDataDeepElement(toscaElement, edgeLabel, vertexLabel, toscaDataList, pathKeys, mapKeyField, false);
404     }
405
406     /**
407      * Updates list of tosca data elements of tosca element according received labels
408      *
409      * @param toscaElement
410      * @param edgeLabel
411      * @param vertexLabel
412      * @param toscaData
413      * @param mapKeyField
414      * @return
415      */
416     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataOfToscaElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
417                                                                                                 VertexTypeEnum vertexLabel, T toscaData,
418                                                                                                 JsonPresentationFields mapKeyField) {
419         List<T> toscaDataList = new ArrayList<>();
420         toscaDataList.add(toscaData);
421         return updateToscaDataOfToscaElement(toscaElement, edgeLabel, vertexLabel, toscaDataList, mapKeyField);
422     }
423
424     /**
425      * Updates tosca data deep element of tosca element according received labels
426      *
427      * @param toscaElement
428      * @param edgeLabel
429      * @param vertexLabel
430      * @param toscaData
431      * @param pathKeys
432      * @param mapKeyField
433      * @return
434      */
435     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataDeepElementOfToscaElement(GraphVertex toscaElement,
436                                                                                                            EdgeLabelEnum edgeLabel,
437                                                                                                            VertexTypeEnum vertexLabel, T toscaData,
438                                                                                                            List<String> pathKeys,
439                                                                                                            JsonPresentationFields mapKeyField) {
440         List<T> toscaDataList = new ArrayList<>();
441         toscaDataList.add(toscaData);
442         return updateToscaDataDeepElementsOfToscaElement(toscaElement, edgeLabel, vertexLabel, toscaDataList, pathKeys, mapKeyField);
443     }
444
445     /**
446      * Updates tosca data deep elements of tosca element according received labels
447      *
448      * @param toscaElement
449      * @param edgeLabel
450      * @param vertexLabel
451      * @param toscaDataList
452      * @param pathKeys
453      * @param mapKeyField
454      * @return
455      */
456     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataDeepElementsOfToscaElement(GraphVertex toscaElement,
457                                                                                                             EdgeLabelEnum edgeLabel,
458                                                                                                             VertexTypeEnum vertexLabel,
459                                                                                                             List<T> toscaDataList,
460                                                                                                             List<String> pathKeys,
461                                                                                                             JsonPresentationFields mapKeyField) {
462         return updateOrAddToscaDataDeepElement(toscaElement, edgeLabel, vertexLabel, toscaDataList, pathKeys, mapKeyField, true);
463     }
464
465     /**
466      * Adds tosca data element to tosca element with specified uid according received labels
467      *
468      * @param toscaElementUid
469      * @param toscaData
470      * @param edgeLabel
471      * @param vertexLabel
472      * @param mapKeyField
473      * @return
474      */
475     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataToToscaElement(String toscaElementUid, EdgeLabelEnum edgeLabel,
476                                                                                              VertexTypeEnum vertexLabel, T toscaData,
477                                                                                              JsonPresentationFields mapKeyField) {
478         List<T> toscaDataList = new ArrayList<>();
479         toscaDataList.add(toscaData);
480         return addToscaDataToToscaElement(toscaElementUid, edgeLabel, vertexLabel, toscaDataList, mapKeyField);
481     }
482
483     /**
484      * Adds tosca data deep element to tosca element with specified uid according received labels
485      *
486      * @param toscaElementUid
487      * @param edgeLabel
488      * @param vertexLabel
489      * @param toscaData
490      * @param pathKeys
491      * @param mapKeyField
492      * @return
493      */
494     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataDeepElementToToscaElement(String toscaElementUid,
495                                                                                                         EdgeLabelEnum edgeLabel,
496                                                                                                         VertexTypeEnum vertexLabel, T toscaData,
497                                                                                                         List<String> pathKeys,
498                                                                                                         JsonPresentationFields mapKeyField) {
499         List<T> toscaDataList = new ArrayList<>();
500         toscaDataList.add(toscaData);
501         return addToscaDataDeepElementsToToscaElement(toscaElementUid, edgeLabel, vertexLabel, toscaDataList, pathKeys, mapKeyField);
502     }
503
504     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataDeepElementOfToscaElement(String toscaElementUid,
505                                                                                                            EdgeLabelEnum edgeLabel,
506                                                                                                            VertexTypeEnum vertexLabel, T toscaData,
507                                                                                                            List<String> pathKeys,
508                                                                                                            JsonPresentationFields mapKeyField) {
509         List<T> toscaDataList = new ArrayList<>();
510         toscaDataList.add(toscaData);
511         return updateToscaDataDeepElementsOfToscaElement(toscaElementUid, edgeLabel, vertexLabel, toscaDataList, pathKeys, mapKeyField);
512     }
513
514     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataDeepElementsOfToscaElement(String toscaElementUid,
515                                                                                                             EdgeLabelEnum edgeLabel,
516                                                                                                             VertexTypeEnum vertexLabel,
517                                                                                                             List<T> toscaDataList,
518                                                                                                             List<String> pathKeys,
519                                                                                                             JsonPresentationFields mapKeyField) {
520         StorageOperationStatus statusRes = null;
521         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
522         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
523         if (getToscaElementRes.isRight()) {
524             JanusGraphOperationStatus status = getToscaElementRes.right().value();
525             CommonUtility
526                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
527             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
528         }
529         if (statusRes == null && CollectionUtils.isNotEmpty(toscaDataList)) {
530             statusRes = updateToscaDataDeepElementsOfToscaElement(getToscaElementRes.left().value(), edgeLabel, vertexLabel, toscaDataList, pathKeys,
531                 mapKeyField);
532         }
533         if (statusRes == null) {
534             statusRes = StorageOperationStatus.OK;
535         }
536         return statusRes;
537     }
538
539     StorageOperationStatus overrideToscaDataOfToscaElement(String toscaElementUid, EdgeLabelEnum edgeLabel,
540                                                            Map<String, ? extends ToscaDataDefinition> toscaData) {
541         return janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse).left()
542             .bind(graphVertex -> overrideToscaElementData(graphVertex, toscaData, edgeLabel))
543             .either(graphVertex -> StorageOperationStatus.OK, DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
544     }
545
546     private Either<GraphVertex, JanusGraphOperationStatus> overrideToscaElementData(GraphVertex toscaElement,
547                                                                                     Map<String, ? extends ToscaDataDefinition> toscaData,
548                                                                                     EdgeLabelEnum edgeLabelEnum) {
549         return janusGraphDao.getChildVertex(toscaElement, edgeLabelEnum, JsonParseFlagEnum.ParseJson).left()
550             .bind(dataVertex -> overrideToscaElementData(dataVertex, toscaElement, toscaData, edgeLabelEnum)).right().map(
551                 err -> logAndReturn(err, "failed to override tosca data for element {} of type {}. status: {}", toscaElement.getUniqueId(),
552                     edgeLabelEnum, err));
553     }
554
555     private Either<GraphVertex, JanusGraphOperationStatus> overrideToscaElementData(GraphVertex dataElement, GraphVertex toscaElement,
556                                                                                     Map<String, ? extends ToscaDataDefinition> toscaData,
557                                                                                     EdgeLabelEnum edgeLabelEnum) {
558         dataElement.setJson(toscaData);
559         return updateOrCopyOnUpdate(dataElement, toscaElement, edgeLabelEnum);
560     }
561
562     /**
563      * Adds list of tosca data deep elements to tosca element with specified uid according received labels
564      *
565      * @param toscaElementUid
566      * @param edgeLabel
567      * @param vertexLabel
568      * @param toscaDataList
569      * @param pathKeys
570      * @param mapKeyField
571      * @return
572      */
573     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataDeepElementsToToscaElement(String toscaElementUid,
574                                                                                                          EdgeLabelEnum edgeLabel,
575                                                                                                          VertexTypeEnum vertexLabel,
576                                                                                                          List<T> toscaDataList, List<String> pathKeys,
577                                                                                                          JsonPresentationFields mapKeyField) {
578         StorageOperationStatus statusRes = null;
579         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
580         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
581         if (getToscaElementRes.isRight()) {
582             JanusGraphOperationStatus status = getToscaElementRes.right().value();
583             CommonUtility
584                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
585             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
586         }
587         if (statusRes == null && CollectionUtils.isNotEmpty(toscaDataList)) {
588             statusRes = addToscaDataDeepElementsToToscaElement(getToscaElementRes.left().value(), edgeLabel, vertexLabel, toscaDataList, pathKeys,
589                 mapKeyField);
590         }
591         if (statusRes == null) {
592             statusRes = StorageOperationStatus.OK;
593         }
594         return statusRes;
595     }
596
597     public <T extends ToscaDataDefinition> StorageOperationStatus deleteToscaDataDeepElementsBlockOfToscaElement(String toscaElementUid,
598                                                                                                                  EdgeLabelEnum edgeLabel,
599                                                                                                                  String key) {
600         StorageOperationStatus statusRes = null;
601         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
602         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
603         if (getToscaElementRes.isRight()) {
604             JanusGraphOperationStatus status = getToscaElementRes.right().value();
605             CommonUtility
606                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
607             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
608         }
609         if (statusRes == null) {
610             statusRes = deleteToscaDataDeepElementsBlockToToscaElement(getToscaElementRes.left().value(), edgeLabel, key);
611         }
612         if (statusRes == null) {
613             statusRes = StorageOperationStatus.OK;
614         }
615         return statusRes;
616     }
617
618     public <T extends ToscaDataDefinition> StorageOperationStatus deleteToscaDataDeepElementsBlockToToscaElement(GraphVertex toscaElement,
619                                                                                                                  EdgeLabelEnum edgeLabel,
620                                                                                                                  String key) {
621         StorageOperationStatus result = null;
622         GraphVertex toscaDataVertex = null;
623         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
624             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
625         if (toscaDataVertexRes.isRight()) {
626             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
627             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
628                 toscaElement.getUniqueId(), edgeLabel, status);
629             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
630         }
631         if (result == null) {
632             toscaDataVertex = toscaDataVertexRes.left().value();
633             result = deleteDeepElementsBlock(toscaDataVertex, key);
634         }
635         if (result == null) {
636             Either<GraphVertex, JanusGraphOperationStatus> updateOrCopyRes = updateOrCopyOnUpdate(toscaDataVertex, toscaElement, edgeLabel);
637             if (updateOrCopyRes.isRight()) {
638                 JanusGraphOperationStatus status = updateOrCopyRes.right().value();
639                 CommonUtility
640                     .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete tosca data block {} from the tosca element {}. Status is {}. ",
641                         edgeLabel, toscaElement.getUniqueId(), status);
642                 result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
643             }
644         }
645         if (result == null) {
646             result = StorageOperationStatus.OK;
647         }
648         return result;
649     }
650
651     @SuppressWarnings("rawtypes")
652     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataDeepElementsBlockToToscaElement(String toscaElementUid,
653                                                                                                               EdgeLabelEnum edgeLabel,
654                                                                                                               VertexTypeEnum vertexLabel,
655                                                                                                               MapDataDefinition toscaDataMap,
656                                                                                                               String key) {
657         StorageOperationStatus statusRes = null;
658         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
659         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
660         if (getToscaElementRes.isRight()) {
661             JanusGraphOperationStatus status = getToscaElementRes.right().value();
662             CommonUtility
663                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
664             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
665         }
666         if (statusRes == null && toscaDataMap != null) {
667             statusRes = addToscaDataDeepElementsBlockToToscaElement(getToscaElementRes.left().value(), edgeLabel, vertexLabel, toscaDataMap, key);
668         }
669         if (statusRes == null) {
670             statusRes = StorageOperationStatus.OK;
671         }
672         return statusRes;
673     }
674
675     @SuppressWarnings("rawtypes")
676     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataDeepElementsBlockToToscaElement(GraphVertex toscaElement,
677                                                                                                               EdgeLabelEnum edgeLabel,
678                                                                                                               VertexTypeEnum vertexLabel,
679                                                                                                               MapDataDefinition toscaDataMap,
680                                                                                                               String key) {
681         StorageOperationStatus result = null;
682         GraphVertex toscaDataVertex = null;
683         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
684             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
685         if (toscaDataVertexRes.isRight() && toscaDataVertexRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
686             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
687             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
688                 toscaElement.getUniqueId(), edgeLabel, status);
689             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
690         }
691         if (result == null && toscaDataVertexRes.isLeft()) {
692             toscaDataVertex = toscaDataVertexRes.left().value();
693             result = addDeepElementsBlock(toscaDataVertex, toscaDataMap, key);
694         }
695         if (result == null) {
696             if (toscaDataVertex != null) {
697                 Either<GraphVertex, JanusGraphOperationStatus> updateOrCopyRes = updateOrCopyOnUpdate(toscaDataVertex, toscaElement, edgeLabel);
698                 if (updateOrCopyRes.isRight()) {
699                     JanusGraphOperationStatus status = updateOrCopyRes.right().value();
700                     CommonUtility
701                         .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add tosca data {} to the tosca element {}. Status is {}. ", edgeLabel,
702                             toscaElement.getUniqueId(), status);
703                     result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
704                 }
705             } else {
706                 Map<String, MapDataDefinition> data = new HashMap<>();
707                 data.put(key, toscaDataMap);
708                 Either<GraphVertex, StorageOperationStatus> createRes = associateElementToData(toscaElement, vertexLabel, edgeLabel, data);
709                 if (createRes.isRight()) {
710                     StorageOperationStatus status = createRes.right().value();
711                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to assosiate tosca data {} of the tosca element {}. Status is {}. ",
712                         edgeLabel, toscaElement.getUniqueId(), status);
713                     result = status;
714                 }
715             }
716         }
717         if (result == null) {
718             result = StorageOperationStatus.OK;
719         }
720         return result;
721     }
722
723     /**
724      * @param toscaElementId the id of the tosca element data container
725      * @param edgeLabel      the edge label of the data type to update
726      * @param toscaDataMap   the data to update
727      * @param key            the key in the json object where the map object block resides
728      * @return the status of the update operation
729      */
730     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataDeepElementsBlockToToscaElement(String toscaElementId,
731                                                                                                                  EdgeLabelEnum edgeLabel,
732                                                                                                                  MapDataDefinition<T> toscaDataMap,
733                                                                                                                  String key) {
734         return janusGraphDao.getVertexById(toscaElementId, JsonParseFlagEnum.NoParse)
735             .either(toscaElement -> updateToscaDataDeepElementsBlockToToscaElement(toscaElement, edgeLabel, toscaDataMap, key),
736                 DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
737     }
738
739     private <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataDeepElementsBlockToToscaElement(GraphVertex toscaElement,
740                                                                                                                   EdgeLabelEnum edgeLabel,
741                                                                                                                   MapDataDefinition<T> toscaDataMap,
742                                                                                                                   String key) {
743         return janusGraphDao.getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson).left()
744             .bind(dataVertex -> updateToscaDataDeepElementsBlockToToscaElement(toscaElement, dataVertex, edgeLabel, toscaDataMap, key))
745             .either(updatedVertex -> StorageOperationStatus.OK, DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
746     }
747
748     private <T extends ToscaDataDefinition> Either<GraphVertex, JanusGraphOperationStatus> updateToscaDataDeepElementsBlockToToscaElement(
749         GraphVertex toscaElement, GraphVertex dataElement, EdgeLabelEnum edgeLabel, MapDataDefinition<T> toscaDataMap, String key) {
750         Map<String, T> mapToscaDataDefinition = toscaDataMap.getMapToscaDataDefinition();
751         updateDeepElements(dataElement, mapToscaDataDefinition, Collections.singletonList(key));
752         return updateOrCopyOnUpdate(dataElement, toscaElement, edgeLabel).right().map(
753             err -> logAndReturn(err, "failed while trying to update data vertex from tosca element {}, of type {} . status {}",
754                 toscaElement.getUniqueId(), edgeLabel, err));
755     }
756
757     /**
758      * Updates tosca data element of tosca element by specified uid according received labels
759      *
760      * @param toscaElementUid
761      * @param edgeLabel
762      * @param vertexLabel
763      * @param toscaData
764      * @param mapKeyField
765      * @return
766      */
767     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataOfToscaElement(String toscaElementUid, EdgeLabelEnum edgeLabel,
768                                                                                                 VertexTypeEnum vertexLabel, T toscaData,
769                                                                                                 JsonPresentationFields mapKeyField) {
770         List<T> toscaDataList = new ArrayList<>();
771         toscaDataList.add(toscaData);
772         return updateToscaDataOfToscaElement(toscaElementUid, edgeLabel, vertexLabel, toscaDataList, mapKeyField);
773     }
774
775     /**
776      * Updates list of tosca data elements belonging to tosca element with specified uid according received labels
777      *
778      * @param toscaElementUid
779      * @param edgeLabel
780      * @param vertexLabel
781      * @param toscaDataList
782      * @param mapKeyField
783      * @return
784      */
785     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataOfToscaElement(String toscaElementUid, EdgeLabelEnum edgeLabel,
786                                                                                                 VertexTypeEnum vertexLabel, List<T> toscaDataList,
787                                                                                                 JsonPresentationFields mapKeyField) {
788         StorageOperationStatus statusRes = null;
789         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
790         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
791         if (getToscaElementRes.isRight()) {
792             JanusGraphOperationStatus status = getToscaElementRes.right().value();
793             CommonUtility
794                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
795             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
796         }
797         if (statusRes == null && CollectionUtils.isNotEmpty(toscaDataList)) {
798             statusRes = updateToscaDataOfToscaElement(getToscaElementRes.left().value(), edgeLabel, vertexLabel, toscaDataList, mapKeyField);
799         }
800         if (statusRes == null) {
801             statusRes = StorageOperationStatus.OK;
802         }
803         return statusRes;
804     }
805
806     /**
807      * Adds list of tosca data elements to tosca element with specified uid according received labels
808      *
809      * @param toscaElementUid
810      * @param edgeLabel
811      * @param vertexLabel
812      * @param toscaDataList
813      * @param mapKeyField
814      * @return
815      */
816     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataToToscaElement(String toscaElementUid, EdgeLabelEnum edgeLabel,
817                                                                                              VertexTypeEnum vertexLabel, List<T> toscaDataList,
818                                                                                              JsonPresentationFields mapKeyField) {
819         StorageOperationStatus statusRes = null;
820         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
821         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
822         if (getToscaElementRes.isRight()) {
823             JanusGraphOperationStatus status = getToscaElementRes.right().value();
824             CommonUtility
825                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
826             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
827         }
828         if (statusRes == null && CollectionUtils.isNotEmpty(toscaDataList)) {
829             statusRes = addToscaDataToToscaElement(getToscaElementRes.left().value(), edgeLabel, vertexLabel, toscaDataList, mapKeyField);
830         }
831         if (statusRes == null) {
832             statusRes = StorageOperationStatus.OK;
833         }
834         return statusRes;
835     }
836
837     /**
838      * Converts recieved map of tosca data elements to list and adds it to tosca element according received labels
839      *
840      * @param toscaElement
841      * @param edgeLabel
842      * @param vertexLabel
843      * @param toscaDataMap
844      * @param mapKeyField
845      * @return
846      */
847     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataToToscaElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
848                                                                                              VertexTypeEnum vertexLabel, Map<String, T> toscaDataMap,
849                                                                                              JsonPresentationFields mapKeyField) {
850         return addToscaDataToToscaElement(toscaElement, edgeLabel, vertexLabel, toscaDataMap.values().stream().collect(Collectors.toList()),
851             mapKeyField);
852     }
853
854     /**
855      * Adds list of tosca data elements to tosca element according received labels
856      *
857      * @param toscaElement
858      * @param edgeLabel
859      * @param vertexLabel
860      * @param toscaDataList
861      * @param mapKeyField
862      * @return
863      */
864     public <T extends ToscaDataDefinition> StorageOperationStatus addToscaDataToToscaElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
865                                                                                              VertexTypeEnum vertexLabel, List<T> toscaDataList,
866                                                                                              JsonPresentationFields mapKeyField) {
867         return updateOrAddToscaData(toscaElement, edgeLabel, vertexLabel, toscaDataList, mapKeyField, false);
868     }
869
870     /**
871      * Updates list of tosca data elements belonging to tosca element according received labels
872      *
873      * @param toscaElement
874      * @param edgeLabel
875      * @param vertexLabel
876      * @param toscaDataList
877      * @param mapKeyField
878      * @return
879      */
880     public <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataOfToscaElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
881                                                                                                 VertexTypeEnum vertexLabel, List<T> toscaDataList,
882                                                                                                 JsonPresentationFields mapKeyField) {
883         return updateOrAddToscaData(toscaElement, edgeLabel, vertexLabel, toscaDataList, mapKeyField, true);
884     }
885
886     public boolean hasEdgeOfType(GraphVertex toscaElement, EdgeLabelEnum edgeLabel) {
887         Either<GraphVertex, JanusGraphOperationStatus> vertex = janusGraphDao.getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
888         return vertex.isLeft();
889     }
890
891     @SuppressWarnings("unchecked")
892     private <T extends ToscaDataDefinition> StorageOperationStatus updateOrAddToscaData(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
893                                                                                         VertexTypeEnum vertexLabel, List<T> toscaDataList,
894                                                                                         JsonPresentationFields mapKeyField, boolean isUpdate) {
895         StorageOperationStatus result = null;
896         GraphVertex toscaDataVertex = null;
897         Map<String, T> existingToscaDataMap = null;
898         Either<Map<String, T>, StorageOperationStatus> validateRes = null;
899         Map<String, T> mergedToscaDataMap;
900         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
901             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
902         if (toscaDataVertexRes.isRight() && toscaDataVertexRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
903             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
904             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
905                 toscaElement.getUniqueId(), edgeLabel, status);
906             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
907         }
908         if (result == null) {
909             if (toscaDataVertexRes.isLeft()) {
910                 toscaDataVertex = toscaDataVertexRes.left().value();
911                 existingToscaDataMap = (Map<String, T>) toscaDataVertex.getJson();
912             }
913             validateRes = validateMergeToscaData(toscaElement, toscaDataList, mapKeyField, existingToscaDataMap, isUpdate);
914             if (validateRes.isRight()) {
915                 result = validateRes.right().value();
916                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed validate tosca data upon adding to tosca element {}. Status is {}. ",
917                     toscaElement.getUniqueId(), edgeLabel, result);
918             }
919         }
920         if (result == null) {
921             mergedToscaDataMap = validateRes.left().value();
922             result = handleToscaData(toscaElement, vertexLabel, edgeLabel, toscaDataVertex, mergedToscaDataMap);
923         }
924         if (result == null) {
925             result = StorageOperationStatus.OK;
926         }
927         return result;
928     }
929
930     <T extends ToscaDataDefinition> StorageOperationStatus updateFullToscaData(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
931                                                                                VertexTypeEnum vertexLabel, Map<String, T> toscaData) {
932         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
933             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
934         if (toscaDataVertexRes.isRight() && toscaDataVertexRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
935             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
936             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
937                 toscaElement.getUniqueId(), edgeLabel, status);
938             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
939         }
940         GraphVertex toscaDataVertex = null;
941         if (toscaDataVertexRes.isLeft()) {
942             toscaDataVertex = toscaDataVertexRes.left().value();
943         }
944         StorageOperationStatus result = handleToscaData(toscaElement, vertexLabel, edgeLabel, toscaDataVertex, toscaData);
945         return result == null ? StorageOperationStatus.OK : result;
946     }
947
948     @SuppressWarnings({"rawtypes", "unchecked"})
949     private <T, K extends ToscaDataDefinition> StorageOperationStatus updateOrAddToscaDataDeepElement(GraphVertex toscaElement,
950                                                                                                       EdgeLabelEnum edgeLabel,
951                                                                                                       VertexTypeEnum vertexLabel,
952                                                                                                       List<K> toscaDataList, List<String> pathKeys,
953                                                                                                       JsonPresentationFields mapKeyField,
954                                                                                                       boolean isUpdate) {
955         StorageOperationStatus result = null;
956         GraphVertex toscaDataVertex = null;
957         Map<String, K> existingDeepElementsMap = null;
958         Either<Map<String, K>, StorageOperationStatus> validateRes = null;
959         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
960             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
961         if (toscaDataVertexRes.isRight() && toscaDataVertexRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
962             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
963             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
964                 toscaElement.getUniqueId(), edgeLabel, status);
965             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
966         }
967         if (result == null) {
968             if (toscaDataVertexRes.isLeft()) {
969                 toscaDataVertex = toscaDataVertexRes.left().value();
970                 existingDeepElementsMap = getDeepElements(toscaDataVertex, pathKeys);
971             }
972             validateRes = validateMergeToscaData(toscaElement, toscaDataList, mapKeyField, existingDeepElementsMap, isUpdate);
973             if (validateRes.isRight()) {
974                 result = validateRes.right().value();
975                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed validate tosca data upon adding to tosca element {}. Status is {}. ",
976                     toscaElement.getUniqueId(), edgeLabel, result);
977             }
978         }
979         if (result == null) {
980             updateDeepElements(toscaDataVertex, validateRes.left().value(), pathKeys);
981             Map<String, K> toscaDataToHandle;
982             if (toscaDataVertex == null) {
983                 toscaDataToHandle = new HashMap<>();
984                 Map<String, K> currMap = toscaDataToHandle;
985                 for (int i = 1; i < pathKeys.size() - 1; ++i) {
986                     currMap.put(pathKeys.get(i), (K) new MapDataDefinition());
987                     currMap = (Map<String, K>) ((MapDataDefinition) currMap).getMapToscaDataDefinition().get(pathKeys.get(i));
988                 }
989                 toscaDataToHandle.put(pathKeys.get(pathKeys.size() - 1), (K) new MapDataDefinition(validateRes.left().value()));
990             } else {
991                 toscaDataToHandle = (Map<String, K>) toscaDataVertex.getJson();
992             }
993             result = handleToscaData(toscaElement, vertexLabel, edgeLabel, toscaDataVertex, toscaDataToHandle);
994         }
995         if (result == null) {
996             result = StorageOperationStatus.OK;
997         }
998         return result;
999     }
1000
1001     @SuppressWarnings({"rawtypes", "unchecked"})
1002     private <T, K extends ToscaDataDefinition> void updateDeepElements(GraphVertex toscaDataVertex, Map<String, K> mergedDeepElementMap,
1003                                                                        List<String> pathKeys) {
1004         if (toscaDataVertex != null && MapUtils.isNotEmpty(mergedDeepElementMap)) {
1005             Map<String, MapDataDefinition> currMap = (Map<String, MapDataDefinition>) toscaDataVertex.getJson();
1006             if (!currMap.containsKey(pathKeys.get(0))) {
1007                 currMap.put(pathKeys.get(0), new MapDataDefinition<>());
1008             }
1009             Object object = currMap.get(pathKeys.get(0));
1010             MapDataDefinition currDeepElement = null;
1011             if (object instanceof MapDataDefinition) {
1012                 currDeepElement = (MapDataDefinition) object;
1013             } else {
1014                 currDeepElement = new MapDataDefinition(currMap);
1015             }
1016             for (int i = 1; i < pathKeys.size(); ++i) {
1017                 if (currDeepElement.findByKey(pathKeys.get(i)) == null) {
1018                     currDeepElement.put(pathKeys.get(i), new MapDataDefinition<>());
1019                 }
1020                 currDeepElement = (MapDataDefinition) currDeepElement.findByKey(pathKeys.get(i));
1021             }
1022             if (currDeepElement != null) {
1023                 for (Map.Entry<String, K> elementEntry : mergedDeepElementMap.entrySet()) {
1024                     currDeepElement.put(elementEntry.getKey(), elementEntry.getValue());
1025                 }
1026             }
1027         }
1028     }
1029
1030     @SuppressWarnings({"unchecked", "rawtypes"})
1031     private <T, K extends ToscaDataDefinition> Map<String, K> getDeepElements(GraphVertex toscaDataVertex, List<String> pathKeys) {
1032         Map<String, K> result = null;
1033         Map<String, T> currMap = (Map<String, T>) toscaDataVertex.getJson();
1034         MapDataDefinition currDeepElement = (MapDataDefinition) currMap.get(pathKeys.get(0));
1035         for (int i = 1; i < pathKeys.size(); ++i) {
1036             currDeepElement = (MapDataDefinition) currDeepElement.findByKey(pathKeys.get(i));
1037         }
1038         if (currDeepElement != null) {
1039             result = (Map<String, K>) currDeepElement.getMapToscaDataDefinition();
1040         }
1041         return result;
1042     }
1043
1044     @SuppressWarnings("unchecked")
1045     private <T extends ToscaDataDefinition> StorageOperationStatus addDeepElementsBlock(GraphVertex toscaDataVertex, T toscaDataBlock, String key) {
1046         StorageOperationStatus result = null;
1047         Map<String, T> currMap = (Map<String, T>) toscaDataVertex.getJson();
1048         if (currMap.containsKey(key)) {
1049             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
1050                 "Failed to add block of deep tosca data elements by label {}." + " The block element with the same key {} already exists. ",
1051                 toscaDataVertex.getLabel(), key);
1052             result = StorageOperationStatus.ENTITY_ALREADY_EXISTS;
1053         }
1054         if (result == null) {
1055             currMap.put(key, toscaDataBlock);
1056         }
1057         return result;
1058     }
1059
1060     @SuppressWarnings("unchecked")
1061     private <T extends ToscaDataDefinition> StorageOperationStatus deleteDeepElementsBlock(GraphVertex toscaDataVertex, String key) {
1062         StorageOperationStatus result = null;
1063         Map<String, T> currMap = (Map<String, T>) toscaDataVertex.getJson();
1064         if (!currMap.containsKey(key)) {
1065             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
1066                 "Failed to delete block of deep tosca data elements by label {}." + " The block element with the same key {} doesn't exist. ",
1067                 toscaDataVertex.getLabel(), key);
1068             result = StorageOperationStatus.NOT_FOUND;
1069         }
1070         if (result == null) {
1071             currMap.remove(key);
1072         }
1073         return null;
1074     }
1075
1076     /**
1077      * Removes tosca data vertex belonging to tosca element specified by uid according label
1078      *
1079      * @param toscaElementUid
1080      * @param edgeLabel
1081      * @return
1082      */
1083     public StorageOperationStatus removeToscaData(String toscaElementUid, EdgeLabelEnum edgeLabel) {
1084         StorageOperationStatus statusRes = StorageOperationStatus.OK;
1085         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
1086         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
1087         if (getToscaElementRes.isRight()) {
1088             JanusGraphOperationStatus status = getToscaElementRes.right().value();
1089             CommonUtility
1090                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
1091             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1092         }
1093         if (statusRes == StorageOperationStatus.OK) {
1094             statusRes = removeToscaDataVertex(getToscaElementRes.left().value(), edgeLabel);
1095         }
1096         return statusRes;
1097     }
1098
1099     /**
1100      * Removes tosca data vertex belonging to tosca element according label
1101      *
1102      * @param toscaElement
1103      * @param edgeLabel
1104      * @return
1105      */
1106     private StorageOperationStatus removeToscaDataVertex(GraphVertex toscaElement, EdgeLabelEnum edgeLabel) {
1107         StorageOperationStatus result = null;
1108         GraphVertex toscaDataVertex = null;
1109         Iterator<Edge> edges = null;
1110         int edgeCounter = 0;
1111         Edge edge = null;
1112         Edge edgeToDelete = null;
1113         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
1114             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
1115         if (toscaDataVertexRes.isRight()) {
1116             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
1117             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_REMOVE_TOSCA_DATA_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
1118                 toscaElement.getUniqueId(), edgeLabel, status);
1119             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
1120         }
1121         if (result == null) {
1122             toscaDataVertex = toscaDataVertexRes.left().value();
1123             edges = toscaDataVertex.getVertex().edges(Direction.IN);
1124             if (edges == null || !edges.hasNext()) {
1125                 result = StorageOperationStatus.NOT_FOUND;
1126                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_REMOVE_TOSCA_DATA_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
1127                     toscaElement.getUniqueId(), edgeLabel, result);
1128             }
1129         }
1130         if (result == null) {
1131             if (edges != null) {
1132                 while (edges.hasNext()) {
1133                     ++edgeCounter;
1134                     edge = edges.next();
1135                     if (edge.outVertex().id().equals(toscaElement.getVertex().id())) {
1136                         edgeToDelete = edge;
1137                         break;
1138                     }
1139                 }
1140             }
1141             if (edgeToDelete == null) {
1142                 result = StorageOperationStatus.NOT_FOUND;
1143                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_REMOVE_TOSCA_DATA_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
1144                     toscaElement.getUniqueId(), edgeLabel, result);
1145             }
1146         }
1147         if (result == null) {
1148             if (edgeCounter > 1 && edgeToDelete != null) {
1149                 edgeToDelete.remove();
1150             } else {
1151                 toscaDataVertex.getVertex().remove();
1152             }
1153         }
1154         if (result == null) {
1155             result = StorageOperationStatus.OK;
1156         }
1157         return result;
1158     }
1159
1160     /**
1161      * Deletes tosca data elements belonging to tosca element specified by uid according label
1162      *
1163      * @param toscaElementUid
1164      * @param edgeLabel
1165      * @param uniqueKeys
1166      * @return
1167      */
1168     public StorageOperationStatus deleteToscaDataElements(String toscaElementUid, EdgeLabelEnum edgeLabel, List<String> uniqueKeys) {
1169         StorageOperationStatus statusRes = StorageOperationStatus.OK;
1170         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
1171         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
1172         if (getToscaElementRes.isRight()) {
1173             JanusGraphOperationStatus status = getToscaElementRes.right().value();
1174             CommonUtility
1175                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
1176             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1177         }
1178         if (statusRes == StorageOperationStatus.OK) {
1179             statusRes = deleteToscaDataElements(getToscaElementRes.left().value(), edgeLabel, uniqueKeys);
1180         }
1181         return statusRes;
1182     }
1183
1184     /**
1185      * Deletes tosca data element belonging to tosca element specified by uid according label
1186      *
1187      * @param toscaElementUid
1188      * @param edgeLabel
1189      * @param vertexLabel
1190      * @param uniqueKey
1191      * @param mapKeyField
1192      * @return
1193      */
1194     public StorageOperationStatus deleteToscaDataElement(String toscaElementUid, EdgeLabelEnum edgeLabel, VertexTypeEnum vertexLabel,
1195                                                          String uniqueKey, JsonPresentationFields mapKeyField) {
1196         StorageOperationStatus statusRes = StorageOperationStatus.OK;
1197         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
1198         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
1199         if (getToscaElementRes.isRight()) {
1200             JanusGraphOperationStatus status = getToscaElementRes.right().value();
1201             CommonUtility
1202                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
1203             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1204         }
1205         if (statusRes == StorageOperationStatus.OK) {
1206             statusRes = deleteToscaDataElement(getToscaElementRes.left().value(), edgeLabel, uniqueKey);
1207         }
1208         return statusRes;
1209     }
1210
1211     /**
1212      * Deletes tosca data deep element belonging to tosca element specified by uid according label
1213      *
1214      * @param toscaElementUid
1215      * @param edgeLabel
1216      * @param uniqueKey
1217      * @param pathKeys
1218      * @return
1219      */
1220     public StorageOperationStatus deleteToscaDataDeepElement(String toscaElementUid, EdgeLabelEnum edgeLabel,
1221                                                              String uniqueKey, List<String> pathKeys) {
1222         StorageOperationStatus statusRes = StorageOperationStatus.OK;
1223         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
1224         getToscaElementRes = janusGraphDao.getVertexById(toscaElementUid, JsonParseFlagEnum.NoParse);
1225         if (getToscaElementRes.isRight()) {
1226             JanusGraphOperationStatus status = getToscaElementRes.right().value();
1227             CommonUtility
1228                 .addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_TOSCA_ELEMENT_UPON_ADDING_THE_PROPERTIES_STATUS_IS, toscaElementUid, status);
1229             statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1230         }
1231         if (statusRes == StorageOperationStatus.OK) {
1232             statusRes = deleteToscaDataDeepElement(getToscaElementRes.left().value(), edgeLabel, uniqueKey, pathKeys);
1233         }
1234         return statusRes;
1235     }
1236
1237     /**
1238      * Deletes tosca data deep element belonging to tosca element according label
1239      *
1240      * @param toscaElement
1241      * @param edgeLabel
1242      * @param uniqueKey
1243      * @param pathKeys
1244      * @return
1245      */
1246     public StorageOperationStatus deleteToscaDataDeepElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
1247                                                              String uniqueKey, List<String> pathKeys) {
1248         List<String> uniqueKeys = new ArrayList<>();
1249         uniqueKeys.add(uniqueKey);
1250         return deleteToscaDataDeepElements(toscaElement, edgeLabel, uniqueKeys, pathKeys);
1251     }
1252
1253     public StorageOperationStatus deleteToscaDataDeepElements(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
1254                                                               List<String> uniqueKeys, List<String> pathKeys) {
1255         StorageOperationStatus result = null;
1256         GraphVertex toscaDataVertex;
1257         Map<String, ToscaDataDefinition> existingToscaDataMap = null;
1258         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
1259             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
1260         if (toscaDataVertexRes.isRight()) {
1261             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
1262             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
1263                 toscaElement.getUniqueId(), edgeLabel, status);
1264             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
1265         }
1266         if (result == null) {
1267             toscaDataVertex = toscaDataVertexRes.left().value();
1268             existingToscaDataMap = getDeepElements(toscaDataVertexRes.left().value(), pathKeys);
1269             result = deleteElementsFromDataVertex(toscaElement, edgeLabel, uniqueKeys, toscaDataVertex, existingToscaDataMap);
1270         }
1271         if (result == null) {
1272             result = StorageOperationStatus.OK;
1273         }
1274         return result;
1275     }
1276
1277     private StorageOperationStatus deleteElementsFromDataVertex(GraphVertex toscaElement, EdgeLabelEnum edgeLabel, List<String> uniqueKeys,
1278                                                                 GraphVertex toscaDataVertex, Map<String, ToscaDataDefinition> existingToscaDataMap) {
1279         StorageOperationStatus result;
1280         for (String uniqueKey : uniqueKeys) {
1281             result = removeKeyFromDataVertex(uniqueKey, existingToscaDataMap);
1282             if (result != StorageOperationStatus.OK) {
1283                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
1284                     "Failed to delete tosca data element of the tosca element {} by label {}. Status is {}. ", toscaElement.getUniqueId(), edgeLabel,
1285                     result);
1286                 break;
1287             }
1288         }
1289         result = updateToscaDataElement(toscaElement, edgeLabel, toscaDataVertex);
1290         return result;
1291     }
1292
1293     /**
1294      * Deletes tosca data element belonging to tosca element according label
1295      *
1296      * @param toscaElement
1297      * @param edgeLabel
1298      * @param uniqueKey
1299      * @return
1300      */
1301     public StorageOperationStatus deleteToscaDataElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
1302                                                          String uniqueKey) {
1303         List<String> uniqueKeys = new ArrayList<>();
1304         uniqueKeys.add(uniqueKey);
1305         return deleteToscaDataElements(toscaElement, edgeLabel, uniqueKeys);
1306     }
1307
1308     @SuppressWarnings("unchecked")
1309 /**
1310  * Deletes tosca data elements belonging to tosca element according label
1311  * @param toscaElement
1312  * @param edgeLabel
1313  * @param uniqueKeys
1314  * @return
1315  */
1316     public StorageOperationStatus deleteToscaDataElements(GraphVertex toscaElement, EdgeLabelEnum edgeLabel, List<String> uniqueKeys) {
1317         StorageOperationStatus result = null;
1318         GraphVertex toscaDataVertex;
1319         Map<String, ToscaDataDefinition> existingToscaDataMap;
1320         Either<GraphVertex, JanusGraphOperationStatus> toscaDataVertexRes = janusGraphDao
1321             .getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
1322         if (toscaDataVertexRes.isRight()) {
1323             JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
1324             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS,
1325                 toscaElement.getUniqueId(), edgeLabel, status);
1326             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
1327         }
1328         if (result == null) {
1329             toscaDataVertex = toscaDataVertexRes.left().value();
1330             existingToscaDataMap = (Map<String, ToscaDataDefinition>) toscaDataVertex.getJson();
1331             result = deleteElementsFromDataVertex(toscaElement, edgeLabel, uniqueKeys, toscaDataVertex, existingToscaDataMap);
1332         }
1333         if (result == null) {
1334             result = StorageOperationStatus.OK;
1335         }
1336         return result;
1337     }
1338
1339     /**
1340      * Adds the map data entry to the graph vertex of the specified type, related with the specified edge to the component specified by ID
1341      *
1342      * @param componentId    The uniqueId of the component
1343      * @param vertexTypeEnum The type of the vertex
1344      * @param edgeLabelEnum  The type of the edge
1345      * @param mapDataEntry   The map data entry
1346      * @param <T             extends MapDataDefinition>
1347      * @return The status of the operation result
1348      */
1349     public <T extends MapDataDefinition> StorageOperationStatus addElementToComponent(String componentId, VertexTypeEnum vertexTypeEnum,
1350                                                                                       EdgeLabelEnum edgeLabelEnum,
1351                                                                                       Map.Entry<String, T> mapDataEntry) {
1352         if (MapUtils.isNotEmpty(mapDataEntry.getValue().getMapToscaDataDefinition())) {
1353             return addToscaDataDeepElementsBlockToToscaElement(componentId, edgeLabelEnum, vertexTypeEnum, mapDataEntry.getValue(),
1354                 mapDataEntry.getKey());
1355         }
1356         return StorageOperationStatus.OK;
1357     }
1358
1359     private <T extends ToscaDataDefinition> StorageOperationStatus updateToscaDataElement(GraphVertex toscaElement, EdgeLabelEnum edgeLabel,
1360                                                                                           GraphVertex toscaDataVertex) {
1361         StorageOperationStatus result = StorageOperationStatus.OK;
1362         Either<GraphVertex, JanusGraphOperationStatus> updateOrCopyRes = updateOrCopyOnUpdate(toscaDataVertex, toscaElement, edgeLabel);
1363         if (updateOrCopyRes.isRight()) {
1364             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updateOrCopyRes.right().value());
1365             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update tosca data {} of the tosca element {}. Status is {}. ", edgeLabel,
1366                 toscaElement.getUniqueId(), result);
1367         }
1368         return result;
1369     }
1370
1371     private <T extends ToscaDataDefinition> StorageOperationStatus removeKeyFromDataVertex(String uniqueKey, Map<String, T> existingToscaDataMap) {
1372         if (!existingToscaDataMap.containsKey(uniqueKey)) {
1373             return StorageOperationStatus.NOT_FOUND;
1374         }
1375         existingToscaDataMap.remove(uniqueKey);
1376         return StorageOperationStatus.OK;
1377     }
1378
1379     <K extends ToscaDataDefinition> StorageOperationStatus handleToscaData(GraphVertex toscaElement, VertexTypeEnum vertexLabel,
1380                                                                            EdgeLabelEnum edgeLabel, GraphVertex toscaDataVertex,
1381                                                                            Map<String, K> mergedToscaDataMap) {
1382         StorageOperationStatus result = StorageOperationStatus.OK;
1383         if (toscaDataVertex == null) {
1384             if (MapUtils.isEmpty(mergedToscaDataMap)) {
1385                 //If no new data and this vertex type does not exist, return
1386                 return result;
1387             }
1388             Either<GraphVertex, StorageOperationStatus> createRes = associateElementToData(toscaElement, vertexLabel, edgeLabel, mergedToscaDataMap);
1389             if (createRes.isRight()) {
1390                 StorageOperationStatus status = createRes.right().value();
1391                 CommonUtility
1392                     .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to associate tosca data {} of the tosca element {}. Status is {}. ", edgeLabel,
1393                         toscaElement.getUniqueId(), status);
1394                 result = status;
1395             }
1396         } else {
1397             if (MapUtils.isEmpty(mergedToscaDataMap)) {
1398                 JanusGraphOperationStatus janusGraphOperationStatus = janusGraphDao.disassociateAndDeleteLast(toscaElement, Direction.OUT, edgeLabel);
1399                 return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus);
1400             }
1401             toscaDataVertex.setJson(mergedToscaDataMap);
1402             Either<GraphVertex, JanusGraphOperationStatus> updateOrCopyRes = updateOrCopyOnUpdate(toscaDataVertex, toscaElement, edgeLabel);
1403             if (updateOrCopyRes.isRight()) {
1404                 JanusGraphOperationStatus status = updateOrCopyRes.right().value();
1405                 CommonUtility
1406                     .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add tosca data {} to the tosca element {}. Status is {}. ", edgeLabel,
1407                         toscaElement.getUniqueId(), status);
1408                 result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1409             }
1410         }
1411         return result;
1412     }
1413
1414     private <T extends ToscaDataDefinition> Either<Map<String, T>, StorageOperationStatus> validateMergeToscaData(GraphVertex toscaElement,
1415                                                                                                                   List<T> toscaDataList,
1416                                                                                                                   JsonPresentationFields mapKeyField,
1417                                                                                                                   Map<String, T> existingToscaDataMap,
1418                                                                                                                   boolean isUpdate) {
1419         Map<String, T> mergedToscaDataMap = new HashMap<>();
1420         StorageOperationStatus status;
1421         Either<Map<String, T>, StorageOperationStatus> result = Either.left(mergedToscaDataMap);
1422         if (MapUtils.isNotEmpty(existingToscaDataMap)) {
1423             mergedToscaDataMap.putAll(existingToscaDataMap);
1424         }
1425         for (T toscaDataElement : toscaDataList) {
1426             status = handleToscaDataElement(toscaElement, mapKeyField, mergedToscaDataMap, toscaDataElement, isUpdate);
1427             if (status != StorageOperationStatus.OK) {
1428                 result = Either.right(status);
1429                 break;
1430             }
1431         }
1432         return result;
1433     }
1434
1435     private <T extends ToscaDataDefinition> StorageOperationStatus handleToscaDataElement(GraphVertex toscaElement,
1436                                                                                           JsonPresentationFields mapKeyField,
1437                                                                                           Map<String, T> mergedToscaDataMap, T toscaDataElement,
1438                                                                                           boolean isUpdate) {
1439         StorageOperationStatus status = StorageOperationStatus.OK;
1440         String currKey = (String) toscaDataElement.getToscaPresentationValue(mapKeyField);
1441         if (StringUtils.isEmpty(currKey) && toscaDataElement instanceof ListDataDefinition) {
1442             ToscaDataDefinition toscaDataDefinition = ((ListDataDefinition<? extends ToscaDataDefinition>) toscaDataElement)
1443                 .getListToscaDataDefinition().get(0);
1444             if (toscaDataDefinition != null) {
1445                 currKey = (String) toscaDataDefinition.getToscaPresentationValue(mapKeyField);
1446             }
1447         }
1448         if (StringUtils.isEmpty(currKey)) {
1449             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add tosca data to tosca element {}. The key is empty. ");
1450             status = StorageOperationStatus.BAD_REQUEST;
1451         } else if (!isUpdate && mergedToscaDataMap.containsKey(currKey)) {
1452             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
1453                 "Failed to add tosca data to tosca element {}. The element with the same key {} already exists. ", toscaElement.getUniqueId(),
1454                 currKey);
1455             status = StorageOperationStatus.BAD_REQUEST;
1456         }
1457         mergedToscaDataMap.put(currKey, toscaDataElement);
1458         return status;
1459     }
1460
1461     protected GroupInstanceDataDefinition buildGroupInstanceDataDefinition(GroupDataDefinition group,
1462                                                                            ComponentInstanceDataDefinition componentInstance) {
1463         String componentInstanceName = componentInstance.getName();
1464         Long creationDate = System.currentTimeMillis();
1465         GroupInstanceDataDefinition groupInstance = new GroupInstanceDataDefinition();
1466         String groupUid = group.getUniqueId();
1467         groupInstance.setGroupUid(groupUid);
1468         groupInstance.setType(group.getType());
1469         groupInstance.setCustomizationUUID(generateCustomizationUUID());
1470         groupInstance.setCreationTime(creationDate);
1471         groupInstance.setModificationTime(creationDate);
1472         groupInstance.setName(buildGroupInstanceName(componentInstanceName, group.getName()));
1473         groupInstance.setGroupName(group.getName());
1474         groupInstance.setNormalizedName(ValidationUtils.normalizeComponentInstanceName(groupInstance.getName()));
1475         groupInstance
1476             .setUniqueId(UniqueIdBuilder.buildResourceInstanceUniqueId(componentInstance.getUniqueId(), groupUid, groupInstance.getNormalizedName()));
1477         groupInstance.setArtifacts(group.getArtifacts());
1478         groupInstance.setArtifactsUuid(group.getArtifactsUuid());
1479         groupInstance.setProperties(group.getProperties());
1480         convertPropertiesToInstanceProperties(groupInstance.getProperties());
1481         groupInstance.setInvariantUUID(group.getInvariantUUID());
1482         groupInstance.setGroupUUID(group.getGroupUUID());
1483         groupInstance.setVersion(group.getVersion());
1484         return groupInstance;
1485     }
1486
1487     protected String buildGroupInstanceName(String instanceName, String groupName) {
1488         return ValidationUtils.normalizeComponentInstanceName(instanceName) + ".." + groupName;
1489     }
1490
1491     protected String generateCustomizationUUID() {
1492         return UUID.randomUUID().toString();
1493     }
1494
1495     protected void convertPropertiesToInstanceProperties(List<PropertyDataDefinition> properties) {
1496         properties.forEach(PropertyDataDefinition::convertPropertyDataToInstancePropertyData);
1497     }
1498
1499     private JanusGraphOperationStatus logAndReturn(JanusGraphOperationStatus janusGraphOperationStatus, String logMsg, Object... logParams) {
1500         log.debug(logMsg, logParams);
1501         return janusGraphOperationStatus;
1502     }
1503
1504     protected GraphVertex throwStorageException(JanusGraphOperationStatus status) {
1505         throw new StorageException(status);
1506     }
1507
1508     public void setHealingPipelineDao(HealingPipelineDao healingPipelineDao) {
1509         this.healingPipelineDao = healingPipelineDao;
1510     }
1511 }