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