Update vulnerable package dependencies
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsonjanusgraph / operations / ToscaElementLifecycleOperation.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 static fj.P.p;
23
24 import fj.P2;
25 import fj.data.Either;
26 import java.util.ArrayList;
27 import java.util.EnumMap;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Optional;
33 import java.util.stream.Collectors;
34 import org.apache.commons.collections.CollectionUtils;
35 import org.apache.commons.collections.MapUtils;
36 import org.apache.commons.lang3.StringUtils;
37 import org.apache.commons.lang3.tuple.ImmutablePair;
38 import org.apache.tinkerpop.gremlin.structure.Direction;
39 import org.apache.tinkerpop.gremlin.structure.Edge;
40 import org.apache.tinkerpop.gremlin.structure.Vertex;
41 import org.janusgraph.core.JanusGraphVertex;
42 import org.openecomp.sdc.be.config.ConfigurationManager;
43 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
44 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
45 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
46 import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum;
47 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
48 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
49 import org.openecomp.sdc.be.dao.jsongraph.utils.IdBuilderUtils;
50 import org.openecomp.sdc.be.dao.jsongraph.utils.JsonParserUtils;
51 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
52 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
53 import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
54 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
55 import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition;
56 import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition;
57 import org.openecomp.sdc.be.datatypes.elements.MapGroupsDataDefinition;
58 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
59 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
60 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
61 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
62 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
63 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
64 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
65 import org.openecomp.sdc.be.model.DistributionStatusEnum;
66 import org.openecomp.sdc.be.model.LifecycleStateEnum;
67 import org.openecomp.sdc.be.model.User;
68 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate;
69 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
70 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum;
71 import org.openecomp.sdc.be.model.jsonjanusgraph.enums.JsonConstantKeysEnum;
72 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
73 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
74 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
75 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
76 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
77 import org.openecomp.sdc.common.log.wrappers.Logger;
78
79 @org.springframework.stereotype.Component("tosca-element-lifecycle-operation")
80 /**
81  * Allows to perform lifecycle operations: checkin, checkout, submit for testing, start certification and certification process for tosca element
82  */
83 public class ToscaElementLifecycleOperation extends BaseOperation {
84
85     public static final String VERSION_DELIMITER = ".";
86     public static final String VERSION_DELIMITER_REGEXP = "\\.";
87     private static final String FAILED_TO_DELETE_LAST_STATE_EDGE_STATUS_IS = "Failed to delete last state edge. Status is {}. ";
88     private static final String FAILED_TO_GET_VERTICES = "Failed to get vertices by id {}. Status is {}. ";
89     private static final Logger log = Logger.getLogger(ToscaElementLifecycleOperation.class);
90
91     static StorageOperationStatus handleFailureToPrepareParameters(final JanusGraphOperationStatus status, final String toscaElementId) {
92         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
93         return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
94     }
95
96     static Either<ToscaElement, StorageOperationStatus> getToscaElementFromOperation(final ToscaElementOperation operation, final String uniqueId,
97                                                                                      final String toscaElementId) {
98         return operation.getToscaElement(uniqueId).right().map(status -> {
99             //We log a potential error we got while retrieving the ToscaElement
100             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated tosca element {}. Status is {}", toscaElementId, status);
101             return status;
102         });
103     }
104
105     private static StorageOperationStatus logDebugMessageAndReturnStorageOperationStatus(final StorageOperationStatus status, final String msg,
106                                                                                          final Object... args) {
107         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, msg, args);
108         return status;
109     }
110
111     /**
112      * Performs changing a lifecycle state of tosca element from "checked out" or "ready for certification" to "checked in"
113      *
114      * @param currState
115      * @param toscaElementId
116      * @param modifierId
117      * @param ownerId
118      * @return
119      */
120     public Either<ToscaElement, StorageOperationStatus> checkinToscaELement(LifecycleStateEnum currState, String toscaElementId, String modifierId,
121                                                                             String ownerId) {
122         try {
123             return janusGraphDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForCheckin(toscaElementId, modifierId, ownerId))
124                 .right().map(status -> handleFailureToPrepareParameters(status, toscaElementId)).left().bind(
125                     verticesMap -> checkinToscaELement(currState, verticesMap.get(toscaElementId), verticesMap.get(ownerId),
126                         verticesMap.get(modifierId), LifecycleStateEnum.NOT_CERTIFIED_CHECKIN).left().bind(checkinResult -> {
127                         //We retrieve the operation
128                         ToscaElementOperation operation = getToscaElementOperation(verticesMap.get(toscaElementId).getLabel());
129                         //We retrieve the ToscaElement from the operation
130                         return getToscaElementFromOperation(operation, checkinResult.getUniqueId(), toscaElementId);
131                     }));
132         } catch (Exception e) {
133             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occurred during checkin of tosca element {}. {} ", toscaElementId,
134                 e.getMessage());
135             return Either.right(StorageOperationStatus.GENERAL_ERROR);
136         }
137     }
138
139     /**
140      * Returns vertex presenting owner of tosca element specified by uniqueId
141      *
142      * @param toscaElementId
143      * @return
144      */
145     public Either<User, StorageOperationStatus> getToscaElementOwner(String toscaElementId) {
146         Either<User, StorageOperationStatus> result = null;
147         GraphVertex toscaElement = null;
148         Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes = janusGraphDao.getVertexById(toscaElementId, JsonParseFlagEnum.NoParse);
149         if (getToscaElementRes.isRight()) {
150             result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getToscaElementRes.right().value()));
151         }
152         if (result == null) {
153             toscaElement = getToscaElementRes.left().value();
154             Iterator<Vertex> vertices = toscaElement.getVertex().vertices(Direction.IN, EdgeLabelEnum.STATE.name());
155             if (vertices == null || !vertices.hasNext()) {
156                 result = Either.right(StorageOperationStatus.NOT_FOUND);
157             } else {
158                 result = Either.left(convertToUser(vertices.next()));
159             }
160         }
161         return result;
162     }
163
164     /**
165      * Returns vertex presenting owner of tosca element specified by uniqueId
166      *
167      * @param toscaElement
168      * @return
169      */
170     public Either<User, StorageOperationStatus> getToscaElementOwner(GraphVertex toscaElement) {
171         Iterator<Vertex> vertices = toscaElement.getVertex().vertices(Direction.IN, EdgeLabelEnum.STATE.name());
172         if (vertices == null || !vertices.hasNext()) {
173             return Either.right(StorageOperationStatus.NOT_FOUND);
174         } else {
175             return Either.left(convertToUser(vertices.next()));
176         }
177     }
178
179     /**
180      * Performs checkout of a tosca element
181      *
182      * @param toscaElementId
183      * @param modifierId
184      * @param ownerId
185      * @return
186      */
187     public Either<ToscaElement, StorageOperationStatus> checkoutToscaElement(String toscaElementId, String modifierId, String ownerId) {
188         Either<ToscaElement, StorageOperationStatus> result = null;
189         Map<String, GraphVertex> vertices = null;
190         try {
191             Either<Map<String, GraphVertex>, JanusGraphOperationStatus> getVerticesRes = janusGraphDao
192                 .getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForCheckout(toscaElementId, modifierId, ownerId));
193             if (getVerticesRes.isRight()) {
194                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
195                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getVerticesRes.right().value()));
196             }
197             if (result == null) {
198                 vertices = getVerticesRes.left().value();
199                 // update previous component if not certified
200                 StorageOperationStatus status = updatePreviousVersion(vertices.get(toscaElementId), vertices.get(ownerId));
201                 if (status != StorageOperationStatus.OK) {
202                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update vertex with id {} . Status is {}. ", status);
203                     result = Either.right(status);
204                 }
205             }
206             if (result == null) {
207                 result = cloneToscaElementForCheckout(vertices.get(toscaElementId), vertices.get(modifierId));
208                 if (result.isRight()) {
209                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to checkout tosca element {}. Status is {} ", toscaElementId,
210                         result.right().value());
211                 }
212             }
213         } catch (Exception e) {
214             CommonUtility
215                 .addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during checkout tosca element {}. {}", toscaElementId, e.getMessage());
216         }
217         return result;
218     }
219
220     /**
221      * Performs undo checkout for tosca element
222      *
223      * @param toscaElementId
224      * @return
225      */
226     public Either<ToscaElement, StorageOperationStatus> undoCheckout(String toscaElementId) {
227         try {
228             return janusGraphDao.getVertexById(toscaElementId, JsonParseFlagEnum.ParseMetadata).right().map(errorStatus -> {
229                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
230                 return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(errorStatus);
231             }).left().bind(this::retrieveAndUpdatePreviousVersion).left().bind(this::updateEdgeToCatalogRootAndReturnPreVersionElement);
232         } catch (Exception e) {
233             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occurred during undo checkout tosca element {}. {}", toscaElementId,
234                 e.getMessage());
235             return null;
236         }
237     }
238
239     private Either<P2<GraphVertex, JanusGraphVertex>, StorageOperationStatus> retrieveAndUpdatePreviousVersion(final GraphVertex currVersionV) {
240         if (!hasPreviousVersion(currVersionV)) {
241             return Either.left(p(currVersionV, null));
242         } else {
243             // find previous version
244             Iterator<Edge> nextVersionComponentIter = currVersionV.getVertex().edges(Direction.IN, EdgeLabelEnum.VERSION.name());
245             if (nextVersionComponentIter == null || !nextVersionComponentIter.hasNext()) {
246                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch previous version of tosca element with name {}. ",
247                     currVersionV.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME).toString());
248                 return Either.right(StorageOperationStatus.NOT_FOUND);
249             } else {
250                 Vertex preVersionVertex = nextVersionComponentIter.next().outVertex();
251                 StorageOperationStatus updateOldResourceResult = updateOldToscaElementBeforeUndoCheckout(preVersionVertex);
252                 if (updateOldResourceResult != StorageOperationStatus.OK) {
253                     return Either.right(updateOldResourceResult);
254                 } else {
255                     P2<GraphVertex, JanusGraphVertex> result = p(currVersionV, (JanusGraphVertex) preVersionVertex);
256                     return Either.left(result);
257                 }
258             }
259         }
260     }
261
262     private Either<ToscaElement, StorageOperationStatus> updateEdgeToCatalogRootAndReturnPreVersionElement(
263         final P2<GraphVertex, JanusGraphVertex> tuple) {
264         final GraphVertex currVersionV = tuple._1();
265         final JanusGraphVertex preVersionVertex = tuple._2();
266         StorageOperationStatus updateCatalogRes = updateEdgeToCatalogRootByUndoCheckout(preVersionVertex, currVersionV);
267         if (updateCatalogRes != StorageOperationStatus.OK) {
268             return Either.right(updateCatalogRes);
269         } else {
270             final ToscaElementOperation operation = getToscaElementOperation(currVersionV.getLabel());
271             return operation.deleteToscaElement(currVersionV).left().bind(discarded -> getUpdatedPreVersionElement(operation, preVersionVertex));
272         }
273     }
274
275     private Either<ToscaElement, StorageOperationStatus> getUpdatedPreVersionElement(final ToscaElementOperation operation,
276                                                                                      final JanusGraphVertex preVersionVertex) {
277         if (preVersionVertex == null) {
278             return Either.left(null);
279         } else {
280             String uniqueIdPreVer = (String) janusGraphDao.getProperty(preVersionVertex, GraphPropertyEnum.UNIQUE_ID.getProperty());
281             return operation.getToscaElement(uniqueIdPreVer);
282         }
283     }
284
285     private boolean hasPreviousVersion(GraphVertex toscaElementVertex) {
286         boolean hasPreviousVersion = true;
287         String version = (String) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION);
288         if (StringUtils.isEmpty(version) || "0.1".equals(version)) {
289             hasPreviousVersion = false;
290         }
291         return hasPreviousVersion;
292     }
293
294     public Either<ToscaElement, StorageOperationStatus> certifyToscaElement(String toscaElementId, String modifierId, String ownerId) {
295         try {
296             return janusGraphDao
297                 .getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId)).right()
298                 .map(status -> logDebugMessageAndReturnStorageOperationStatus(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status),
299                     FAILED_TO_GET_VERTICES, toscaElementId)).left().bind(verticesRes -> {
300                     GraphVertex toscaElement = verticesRes.get(toscaElementId);
301                     GraphVertex modifier = verticesRes.get(modifierId);
302                     Integer majorVersion = getMajorVersion((String) toscaElement.getMetadataProperty(GraphPropertyEnum.VERSION));
303                     return handleRelationsBeforeCertifyingAndProcessClone(toscaElement, modifier, majorVersion);
304                 });
305         } catch (Exception e) {
306             return Either.right(logDebugMessageAndReturnStorageOperationStatus(StorageOperationStatus.GENERAL_ERROR,
307                 "Exception occurred during certification tosca element {}.", toscaElementId, e));
308         }
309     }
310
311     private Either<ToscaElement, StorageOperationStatus> handleRelationsBeforeCertifyingAndProcessClone(GraphVertex toscaElement,
312                                                                                                         GraphVertex modifier, Integer majorVersion) {
313         StorageOperationStatus status = handleRelationsOfPreviousToscaElementBeforeCertifying(toscaElement, modifier, majorVersion);
314         if (status != StorageOperationStatus.OK) {
315             return Either.right(logDebugMessageAndReturnStorageOperationStatus(status,
316                 "Failed to handle relations of previous tosca element before certifying {}. Status is {}. ", toscaElement.getUniqueId(), status));
317         } else {
318             return cloneToscaElementAndHandleRelations(toscaElement, modifier, majorVersion);
319         }
320     }
321
322     private Either<ToscaElement, StorageOperationStatus> cloneToscaElementAndHandleRelations(GraphVertex toscaElement, GraphVertex modifier,
323                                                                                              Integer majorVersion) {
324         return cloneToscaElementForCertify(toscaElement, modifier, majorVersion).right()
325             .map(status -> logDebugMessageAndReturnStorageOperationStatus(status, "Failed to clone tosca element during certification. ")).left()
326             .bind(certifiedToscaElement -> handleRelationsOfNewestCertifiedToscaElementAndReturn(toscaElement, certifiedToscaElement));
327     }
328
329     private Either<ToscaElement, StorageOperationStatus> handleRelationsOfNewestCertifiedToscaElementAndReturn(GraphVertex toscaElement,
330                                                                                                                GraphVertex certifiedToscaElement) {
331         StorageOperationStatus status = handleRelationsOfNewestCertifiedToscaElement(toscaElement, certifiedToscaElement);
332         if (status != StorageOperationStatus.OK) {
333             return Either.right(logDebugMessageAndReturnStorageOperationStatus(status,
334                 "Failed to handle relations of newest certified tosca element {}. Status is {}. ", certifiedToscaElement.getUniqueId(), status));
335         } else {
336             return getToscaElementOperation(toscaElement.getLabel()).getToscaElement(certifiedToscaElement.getUniqueId());
337         }
338     }
339
340     private StorageOperationStatus handleRelationsOfNewestCertifiedToscaElement(GraphVertex toscaElement, GraphVertex certifiedToscaElement) {
341         JanusGraphOperationStatus createVersionEdgeStatus = janusGraphDao
342             .createEdge(toscaElement, certifiedToscaElement, EdgeLabelEnum.VERSION, new HashMap<>());
343         if (createVersionEdgeStatus != JanusGraphOperationStatus.OK) {
344             CommonUtility
345                 .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create version edge from last element {} to new certified element {}. status=",
346                     toscaElement.getUniqueId(), certifiedToscaElement.getUniqueId(), createVersionEdgeStatus);
347             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createVersionEdgeStatus);
348         }
349         return StorageOperationStatus.OK;
350     }
351
352     public Either<GraphVertex, JanusGraphOperationStatus> findUser(String userId) {
353         return findUserVertex(userId);
354     }
355
356     private Either<Boolean, StorageOperationStatus> markToscaElementsAsDeleted(ToscaElementOperation operation, List<GraphVertex> toscaElements) {
357         Either<Boolean, StorageOperationStatus> result = Either.left(true);
358         for (GraphVertex resourceToDelete : toscaElements) {
359             if (!(resourceToDelete.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals(LifecycleStateEnum.CERTIFIED.name())) {
360                 Either<GraphVertex, StorageOperationStatus> deleteElementRes = operation.markComponentToDelete(resourceToDelete);
361                 if (deleteElementRes.isRight()) {
362                     CommonUtility
363                         .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete tosca element {}. Status is {}. ", resourceToDelete.getUniqueId(),
364                             deleteElementRes.right().value());
365                     result = Either.right(deleteElementRes.right().value());
366                     break;
367                 }
368             }
369         }
370         return result;
371     }
372
373     private StorageOperationStatus handleRelationsOfPreviousToscaElementBeforeCertifying(GraphVertex toscaElement, GraphVertex modifier,
374                                                                                          Integer majorVersion) {
375         StorageOperationStatus result = null;
376         if (majorVersion > 0) {
377             Either<Vertex, StorageOperationStatus> findRes = findLastCertifiedToscaElementVertex(toscaElement);
378             if (findRes.isRight()) {
379                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch last certified tosca element {} . Status is {}. ",
380                     toscaElement.getMetadataProperty(GraphPropertyEnum.NAME), findRes.right().value());
381                 result = findRes.right().value();
382             }
383             if (result == null) {
384                 Vertex lastCertifiedVertex = findRes.left().value();
385                 Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
386                 properties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
387                 JanusGraphOperationStatus status = janusGraphDao.updateVertexMetadataPropertiesWithJson(lastCertifiedVertex, properties);
388                 if (status != JanusGraphOperationStatus.OK) {
389                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set highest version  of tosca element {} to [{}]. Status is {}",
390                         toscaElement.getUniqueId(), false, status);
391                     result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
392                 }
393                 // remove previous certified version from the catalog
394                 GraphVertex lastCertifiedV = new GraphVertex();
395                 lastCertifiedV.setVertex((JanusGraphVertex) lastCertifiedVertex);
396                 lastCertifiedV.setUniqueId(
397                     (String) janusGraphDao.getProperty((JanusGraphVertex) lastCertifiedVertex, GraphPropertyEnum.UNIQUE_ID.getProperty()));
398                 lastCertifiedV.addMetadataProperty(GraphPropertyEnum.IS_ABSTRACT,
399                     (Boolean) janusGraphDao.getProperty((JanusGraphVertex) lastCertifiedVertex, GraphPropertyEnum.IS_ABSTRACT.getProperty()));
400                 StorageOperationStatus res = updateEdgeToCatalogRoot(null, lastCertifiedV);
401                 if (res != StorageOperationStatus.OK) {
402                     return res;
403                 }
404             }
405         }
406         if (result == null) {
407             result = StorageOperationStatus.OK;
408         }
409         return result;
410     }
411
412     private Either<Vertex, StorageOperationStatus> findLastCertifiedToscaElementVertex(GraphVertex toscaElement) {
413         return findLastCertifiedToscaElementVertexRecursively(toscaElement.getVertex());
414     }
415
416     private Either<Vertex, StorageOperationStatus> findLastCertifiedToscaElementVertexRecursively(Vertex vertex) {
417         if (isCertifiedVersion((String) vertex.property(GraphPropertyEnum.VERSION.getProperty()).value())) {
418             return Either.left(vertex);
419         }
420         Iterator<Edge> edgeIter = vertex.edges(Direction.IN, EdgeLabelEnum.VERSION.name());
421         if (!edgeIter.hasNext()) {
422             return Either.right(StorageOperationStatus.NOT_FOUND);
423         }
424         return findLastCertifiedToscaElementVertexRecursively(edgeIter.next().outVertex());
425     }
426
427     private boolean isCertifiedVersion(String version) {
428         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
429         if (Integer.parseInt(versionParts[0]) > 0 && Integer.parseInt(versionParts[1]) == 0) {
430             return true;
431         }
432         return false;
433     }
434
435     private StorageOperationStatus updateOldToscaElementBeforeUndoCheckout(Vertex previousVersionToscaElement) {
436         StorageOperationStatus result = StorageOperationStatus.OK;
437         String previousVersion = (String) previousVersionToscaElement.property(GraphPropertyEnum.VERSION.getProperty()).value();
438         if (!previousVersion.endsWith(".0")) {
439             try {
440                 CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update vertex of previous version of tosca element",
441                     previousVersionToscaElement.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()));
442                 Map<String, Object> propertiesToUpdate = new HashMap<>();
443                 propertiesToUpdate.put(GraphPropertyEnum.IS_HIGHEST_VERSION.getProperty(), true);
444                 Map<String, Object> jsonMetadataMap = JsonParserUtils
445                     .toMap((String) previousVersionToscaElement.property(GraphPropertyEnum.METADATA.getProperty()).value());
446                 jsonMetadataMap.put(GraphPropertyEnum.IS_HIGHEST_VERSION.getProperty(), true);
447                 propertiesToUpdate.put(GraphPropertyEnum.METADATA.getProperty(), JsonParserUtils.toJson(jsonMetadataMap));
448                 janusGraphDao.setVertexProperties(previousVersionToscaElement, propertiesToUpdate);
449                 Iterator<Edge> edgesIter = previousVersionToscaElement.edges(Direction.IN, EdgeLabelEnum.LAST_STATE.name());
450                 if (!edgesIter.hasNext()) {
451                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch last modifier vertex for tosca element {}. ",
452                         previousVersionToscaElement.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()));
453                     result = StorageOperationStatus.NOT_FOUND;
454                 } else {
455                     Edge lastStateEdge = edgesIter.next();
456                     Vertex lastModifier = lastStateEdge.outVertex();
457                     JanusGraphOperationStatus replaceRes = janusGraphDao
458                         .replaceEdgeLabel(lastModifier, previousVersionToscaElement, lastStateEdge, EdgeLabelEnum.LAST_STATE, EdgeLabelEnum.STATE);
459                     if (replaceRes != JanusGraphOperationStatus.OK) {
460                         CommonUtility
461                             .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to replace label from {} to {}. status = {}", EdgeLabelEnum.LAST_STATE,
462                                 EdgeLabelEnum.STATE, replaceRes);
463                         result = StorageOperationStatus.INCONSISTENCY;
464                         if (replaceRes != JanusGraphOperationStatus.INVALID_ID) {
465                             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(replaceRes);
466                         }
467                     }
468                 }
469             } catch (Exception e) {
470                 CommonUtility
471                     .addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during update previous tosca element {} before undo checkout. {} ",
472                         e.getMessage());
473             }
474         }
475         return result;
476     }
477
478     private StorageOperationStatus updatePreviousVersion(GraphVertex toscaElementVertex, GraphVertex ownerVertex) {
479         StorageOperationStatus result = null;
480         String ownerId = (String) ownerVertex.getMetadataProperty(GraphPropertyEnum.USERID);
481         String toscaElementId = toscaElementVertex.getUniqueId();
482         if (!toscaElementVertex.getMetadataProperty(GraphPropertyEnum.STATE).equals(LifecycleStateEnum.CERTIFIED.name())) {
483             toscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
484             Either<GraphVertex, JanusGraphOperationStatus> updateVertexRes = janusGraphDao.updateVertex(toscaElementVertex);
485             if (updateVertexRes.isRight()) {
486                 JanusGraphOperationStatus titatStatus = updateVertexRes.right().value();
487                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update tosca element vertex {}. Status is  {}",
488                     toscaElementVertex.getUniqueId(), titatStatus);
489                 result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(titatStatus);
490             }
491             Either<Edge, JanusGraphOperationStatus> deleteEdgeRes = null;
492             if (result == null) {
493                 CommonUtility
494                     .addRecordToLog(log, LogLevelEnum.TRACE, "Going to replace edge with label {} to label {} from {} to {}. ", EdgeLabelEnum.STATE,
495                         EdgeLabelEnum.LAST_STATE, ownerId, toscaElementId);
496                 deleteEdgeRes = janusGraphDao.deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.STATE);
497                 if (deleteEdgeRes.isRight()) {
498                     JanusGraphOperationStatus janusGraphStatus = deleteEdgeRes.right().value();
499                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete edge with label {} from {} to {}. Status is {} ",
500                         EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE, ownerId, toscaElementId, janusGraphStatus);
501                     if (!janusGraphStatus.equals(JanusGraphOperationStatus.INVALID_ID)) {
502                         result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphStatus);
503                     } else {
504                         result = StorageOperationStatus.INCONSISTENCY;
505                     }
506                 }
507             }
508             if (result == null) {
509                 JanusGraphOperationStatus createEdgeRes = janusGraphDao
510                     .createEdge(ownerVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.LAST_STATE, deleteEdgeRes.left().value());
511                 if (createEdgeRes != JanusGraphOperationStatus.OK) {
512                     result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdgeRes);
513                 }
514             }
515         }
516         if (result == null) {
517             result = StorageOperationStatus.OK;
518         }
519         return result;
520     }
521
522     private Either<ToscaElement, StorageOperationStatus> cloneToscaElementForCheckout(GraphVertex toscaElementVertex, GraphVertex modifierVertex) {
523         Either<ToscaElement, StorageOperationStatus> result = null;
524         Either<GraphVertex, StorageOperationStatus> cloneResult = null;
525         ToscaElementOperation operation = getToscaElementOperation(toscaElementVertex.getLabel());
526         // check if component with the next version doesn't exist.
527         Iterator<Edge> nextVersionComponentIter = toscaElementVertex.getVertex().edges(Direction.OUT, EdgeLabelEnum.VERSION.name());
528         if (nextVersionComponentIter != null && nextVersionComponentIter.hasNext()) {
529             Vertex nextVersionVertex = nextVersionComponentIter.next().inVertex();
530             String fetchedVersion = (String) nextVersionVertex.property(GraphPropertyEnum.VERSION.getProperty()).value();
531             String fetchedName = (String) nextVersionVertex.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()).value();
532             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
533                 "Failed to checkout component {} with version {}. The component with name {} and version {} was fetched from graph as existing following version. ",
534                 toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME).toString(),
535                 toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION).toString(), fetchedName, fetchedVersion);
536             result = Either.right(StorageOperationStatus.ENTITY_ALREADY_EXISTS);
537         }
538         if (result == null) {
539             toscaElementVertex.getOrSetDefaultInstantiationTypeForToscaElementJson();
540             cloneResult = operation
541                 .cloneToscaElement(toscaElementVertex, cloneGraphVertexForCheckout(toscaElementVertex, modifierVertex), modifierVertex);
542             if (cloneResult.isRight()) {
543                 result = Either.right(cloneResult.right().value());
544             }
545         }
546         GraphVertex clonedVertex = null;
547         if (result == null) {
548             clonedVertex = cloneResult.left().value();
549             JanusGraphOperationStatus status = janusGraphDao
550                 .createEdge(toscaElementVertex.getVertex(), cloneResult.left().value().getVertex(), EdgeLabelEnum.VERSION, new HashMap<>());
551             if (status != JanusGraphOperationStatus.OK) {
552                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
553                     "Failed to create edge with label {} from vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.VERSION,
554                     toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME),
555                     cloneResult.left().value().getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), status);
556                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
557             }
558         }
559         if (result == null) {
560             Boolean isHighest = (Boolean) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION);
561             GraphVertex prevVersionInCatalog = (isHighest != null && isHighest) ? null : toscaElementVertex;
562             StorageOperationStatus updateCatalogRes = updateEdgeToCatalogRoot(clonedVertex, prevVersionInCatalog);
563             if (updateCatalogRes != StorageOperationStatus.OK) {
564                 return Either.right(updateCatalogRes);
565             }
566             result = operation.getToscaElement(cloneResult.left().value().getUniqueId());
567             if (result.isRight()) {
568                 return result;
569             }
570             ToscaElement toscaElement = result.left().value();
571             if (toscaElement.getToscaType() == ToscaElementTypeEnum.TOPOLOGY_TEMPLATE) {
572                 result = handleFixTopologyTemplate(toscaElementVertex, result, operation, clonedVertex, toscaElement);
573             }
574         }
575         return result;
576     }
577
578     private Either<ToscaElement, StorageOperationStatus> handleFixTopologyTemplate(GraphVertex toscaElementVertex,
579                                                                                    Either<ToscaElement, StorageOperationStatus> result,
580                                                                                    ToscaElementOperation operation, GraphVertex clonedVertex,
581                                                                                    ToscaElement toscaElement) {
582         TopologyTemplate topologyTemplate = (TopologyTemplate) toscaElement;
583         Map<String, MapPropertiesDataDefinition> instInputs = topologyTemplate.getInstInputs();
584         Map<String, MapGroupsDataDefinition> instGroups = topologyTemplate.getInstGroups();
585         Map<String, MapArtifactDataDefinition> instArtifactsMap = topologyTemplate.getInstanceArtifacts();
586         Map<String, ToscaElement> origCompMap = new HashMap<>();
587         if (instInputs == null) {
588             instInputs = new HashMap<>();
589         }
590         if (instGroups == null) {
591             instGroups = new HashMap<>();
592         }
593         if (instArtifactsMap == null) {
594             instArtifactsMap = new HashMap<>();
595         }
596         Map<String, ComponentInstanceDataDefinition> instancesMap = topologyTemplate.getComponentInstances();
597         boolean isAddInstGroup = instGroups == null || instGroups.isEmpty();
598         boolean needUpdateComposition = false;
599         if (instancesMap != null && !instancesMap.isEmpty()) {
600             for (ComponentInstanceDataDefinition vfInst : instancesMap.values()) {
601                 CommonUtility
602                     .addRecordToLog(log, LogLevelEnum.DEBUG, "vfInst name is {} . OriginType {}. ", vfInst.getName(), vfInst.getOriginType());
603                 if (vfInst.getOriginType().name().equals(OriginTypeEnum.VF.name())) {
604                     collectInstanceInputAndGroups(instInputs, instGroups, instArtifactsMap, origCompMap, isAddInstGroup, vfInst, clonedVertex);
605                 }
606                 needUpdateComposition = needUpdateComposition || fixToscaComponentName(vfInst, origCompMap);
607                 if (needUpdateComposition) {
608                     instancesMap.put(vfInst.getUniqueId(), vfInst);
609                 }
610             }
611             CommonUtility
612                 .addRecordToLog(log, LogLevelEnum.DEBUG, "before add to graph instInputs {}  instGroups {} needUpdateComposition {}", instInputs,
613                     instGroups, needUpdateComposition);
614             if (!instInputs.isEmpty()) {
615                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add inst inputs {} ", instInputs == null ? 0 : instInputs.size());
616                 GraphVertex toscaDataVertex = null;
617                 Either<GraphVertex, JanusGraphOperationStatus> instInpVertexEither = janusGraphDao
618                     .getChildVertex(toscaElementVertex, EdgeLabelEnum.INST_INPUTS, JsonParseFlagEnum.ParseJson);
619                 if (instInpVertexEither.isLeft()) {
620                     toscaDataVertex = instInpVertexEither.left().value();
621                 }
622                 StorageOperationStatus status = handleToscaData(clonedVertex, VertexTypeEnum.INST_INPUTS, EdgeLabelEnum.INST_INPUTS, toscaDataVertex,
623                     instInputs);
624                 if (status != StorageOperationStatus.OK) {
625                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instance inputs . Status is {}. ", status);
626                     result = Either.right(status);
627                     return result;
628                 }
629             }
630             if (!instGroups.isEmpty()) {
631                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add inst groups {} ", instGroups == null ? 0 : instGroups.size());
632                 GraphVertex toscaDataVertex = null;
633                 Either<GraphVertex, JanusGraphOperationStatus> instGrVertexEither = janusGraphDao
634                     .getChildVertex(toscaElementVertex, EdgeLabelEnum.INST_GROUPS, JsonParseFlagEnum.ParseJson);
635                 if (instGrVertexEither.isLeft()) {
636                     toscaDataVertex = instGrVertexEither.left().value();
637                 }
638                 StorageOperationStatus status = handleToscaData(clonedVertex, VertexTypeEnum.INST_GROUPS, EdgeLabelEnum.INST_GROUPS, toscaDataVertex,
639                     instGroups);
640                 if (status != StorageOperationStatus.OK) {
641                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instance group . Status is {}. ", status);
642                     result = Either.right(status);
643                     return result;
644                 }
645             }
646             if (needUpdateComposition) {
647                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before update Instances ");
648                 Map<String, CompositionDataDefinition> jsonComposition = (Map<String, CompositionDataDefinition>) clonedVertex.getJson();
649                 CompositionDataDefinition compositionDataDefinition = jsonComposition.get(JsonConstantKeysEnum.COMPOSITION.getValue());
650                 compositionDataDefinition.setComponentInstances(instancesMap);
651                 Either<GraphVertex, JanusGraphOperationStatus> updateElement = janusGraphDao.updateVertex(clonedVertex);
652                 if (updateElement.isRight()) {
653                     JanusGraphOperationStatus status = updateElement.right().value();
654                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instances on metadata vertex . Status is {}. ", status);
655                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
656                     return result;
657                 }
658             }
659             result = operation.getToscaElement(clonedVertex.getUniqueId());
660         } else {
661             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "RI map empty on component {}", toscaElement.getUniqueId());
662         }
663         return result;
664     }
665
666     // TODO remove after jsonModelMigration
667     public boolean resolveToscaComponentName(ComponentInstanceDataDefinition vfInst, Map<String, ToscaElement> origCompMap) {
668         return fixToscaComponentName(vfInst, origCompMap);
669     }
670
671     private boolean fixToscaComponentName(ComponentInstanceDataDefinition vfInst, Map<String, ToscaElement> origCompMap) {
672         if (vfInst.getToscaComponentName() == null || vfInst.getToscaComponentName().isEmpty()) {
673             String ciUid = vfInst.getUniqueId();
674             String origCompUid = vfInst.getComponentUid();
675             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "fixToscaComponentName:: Ri id {} . origin component id is {}. type is{} ", ciUid,
676                 origCompUid, vfInst.getOriginType());
677             ToscaElement origComp = null;
678             if (!origCompMap.containsKey(origCompUid)) {
679                 Either<ToscaElement, StorageOperationStatus> origCompEither;
680                 if (vfInst.getOriginType() == null || vfInst.getOriginType().name().equals(OriginTypeEnum.VF.name())) {
681                     origCompEither = topologyTemplateOperation.getToscaElement(origCompUid);
682                 } else {
683                     origCompEither = nodeTypeOperation.getToscaElement(origCompUid);
684                 }
685                 if (origCompEither.isRight()) {
686                     CommonUtility
687                         .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find orig component {} . Status is {}. ", origCompEither.right().value());
688                     return false;
689                 }
690                 origComp = origCompEither.left().value();
691                 origCompMap.put(origCompUid, origComp);
692             } else {
693                 origComp = origCompMap.get(origCompUid);
694             }
695             String toscaName = (String) origComp.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME);
696             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Origin component id is {}. toscaName {}", origCompUid, toscaName);
697             vfInst.setToscaComponentName(toscaName);
698             return true;
699         }
700         return false;
701     }
702
703     private void collectInstanceInputAndGroups(Map<String, MapPropertiesDataDefinition> instInputs, Map<String, MapGroupsDataDefinition> instGroups,
704                                                Map<String, MapArtifactDataDefinition> instArtifactsMap, Map<String, ToscaElement> origCompMap,
705                                                boolean isAddInstGroup, ComponentInstanceDataDefinition vfInst, GraphVertex clonedVertex) {
706         String ciUid = vfInst.getUniqueId();
707         String origCompUid = vfInst.getComponentUid();
708         CommonUtility
709             .addRecordToLog(log, LogLevelEnum.DEBUG, "collectInstanceInputAndGroups:: Ri id {} . origin component id is {}. ", ciUid, origCompUid);
710         TopologyTemplate origComp = null;
711         if (!origCompMap.containsKey(origCompUid)) {
712             Either<ToscaElement, StorageOperationStatus> origCompEither = topologyTemplateOperation.getToscaElement(origCompUid);
713             if (origCompEither.isRight()) {
714                 CommonUtility
715                     .addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find orig component {} . Status is {}. ", origCompEither.right().value());
716                 return;
717             }
718             origComp = (TopologyTemplate) origCompEither.left().value();
719             origCompMap.put(origCompUid, origComp);
720         } else {
721             origComp = (TopologyTemplate) origCompMap.get(origCompUid);
722         }
723         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Orig component {}. ", origComp.getUniqueId());
724         Map<String, PropertyDataDefinition> origInputs = origComp.getInputs();
725         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Orig component inputs size {}. ", origInputs == null ? 0 : origInputs.size());
726         if (origInputs != null) {
727             if (!instInputs.containsKey(ciUid)) {
728                 MapPropertiesDataDefinition instProperties = new MapPropertiesDataDefinition(origInputs);
729                 instInputs.put(ciUid, instProperties);
730             } else {
731                 MapPropertiesDataDefinition instInputMap = instInputs.get(ciUid);
732                 Map<String, PropertyDataDefinition> instProp = instInputMap.getMapToscaDataDefinition();
733                 origInputs.forEach((propName, propMap) -> {
734                     if (!instProp.containsKey(propName)) {
735                         instProp.put(propName, propMap);
736                     }
737                 });
738             }
739             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "ComponentInstanseInputs {}. ", instInputs.get(ciUid));
740         }
741         if (isAddInstGroup) {
742             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before create group instance. ");
743             List<GroupDataDefinition> filteredGroups = null;
744             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups before filter. Size is {} ",
745                 filteredGroups == null ? 0 : filteredGroups.size());
746             if (origComp.getGroups() != null && !origComp.getGroups().isEmpty()) {
747                 filteredGroups = origComp.getGroups().values().stream().filter(g -> g.getType().equals(VF_MODULE)).collect(Collectors.toList());
748                 CommonUtility
749                     .addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups . Size is {} ", filteredGroups == null ? 0 : filteredGroups.size());
750             }
751             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups after filter. Size is {} ",
752                 filteredGroups == null ? 0 : filteredGroups.size());
753             if (CollectionUtils.isNotEmpty(filteredGroups)) {
754                 MapArtifactDataDefinition instArifacts = null;
755                 if (!instArtifactsMap.containsKey(ciUid)) {
756                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "istance artifacts not found ");
757                     Map<String, ArtifactDataDefinition> deploymentArtifacts = origComp.getDeploymentArtifacts();
758                     instArifacts = new MapArtifactDataDefinition(deploymentArtifacts);
759                     addToscaDataDeepElementsBlockToToscaElement(clonedVertex, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS,
760                         VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS, instArifacts, ciUid);
761                     instArtifactsMap.put(ciUid, instArifacts);
762                 } else {
763                     instArifacts = instArtifactsMap.get(ciUid);
764                 }
765                 if (instArifacts != null) {
766                     Map<String, ArtifactDataDefinition> instDeplArtifMap = instArifacts.getMapToscaDataDefinition();
767                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check group dep artifacts. Size is {} ",
768                         instDeplArtifMap == null ? 0 : instDeplArtifMap.values().size());
769                     Map<String, GroupInstanceDataDefinition> groupInstanceToCreate = new HashMap<>();
770                     for (GroupDataDefinition group : filteredGroups) {
771                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "create new groupInstance  {} ", group.getName());
772                         GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition(group, vfInst, instDeplArtifMap);
773                         List<String> artifactsUid = new ArrayList<>();
774                         List<String> artifactsId = new ArrayList<>();
775                         if (instDeplArtifMap != null) {
776                             for (ArtifactDataDefinition artifact : instDeplArtifMap.values()) {
777                                 Optional<String> op = group.getArtifacts().stream().filter(p -> p.equals(artifact.getGeneratedFromId())).findAny();
778                                 if (op.isPresent()) {
779                                     artifactsUid.add(artifact.getArtifactUUID());
780                                     artifactsId.add(artifact.getUniqueId());
781                                 }
782                             }
783                         }
784                         groupInstance.setGroupInstanceArtifacts(artifactsId);
785                         groupInstance.setGroupInstanceArtifactsUuid(artifactsUid);
786                         groupInstanceToCreate.put(groupInstance.getName(), groupInstance);
787                     }
788                     if (MapUtils.isNotEmpty(groupInstanceToCreate)) {
789                         instGroups.put(vfInst.getUniqueId(), new MapGroupsDataDefinition(groupInstanceToCreate));
790                     }
791                 }
792             }
793         }
794     }
795
796     private GraphVertex cloneGraphVertexForCheckout(GraphVertex toscaElementVertex, GraphVertex modifierVertex) {
797         GraphVertex nextVersionToscaElementVertex = new GraphVertex();
798         String uniqueId = UniqueIdBuilder.buildComponentUniqueId();
799         Map<GraphPropertyEnum, Object> metadataProperties = new HashMap<>(toscaElementVertex.getMetadataProperties());
800         nextVersionToscaElementVertex.setMetadataProperties(metadataProperties);
801         nextVersionToscaElementVertex.setUniqueId(uniqueId);
802         nextVersionToscaElementVertex.setLabel(toscaElementVertex.getLabel());
803         nextVersionToscaElementVertex.setType(toscaElementVertex.getType());
804         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uniqueId);
805         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, nextVersionToscaElementVertex.getType().name());
806         String nextVersion = getNextVersion((String) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION));
807         if (isFirstCheckoutAfterCertification(nextVersion)) {
808             nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UUID, IdBuilderUtils.generateUUID());
809         }
810         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.VERSION, nextVersion);
811         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name());
812         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
813         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE) {
814             nextVersionToscaElementVertex
815                 .addMetadataProperty(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED.name());
816         }
817         if (!MapUtils.isEmpty(toscaElementVertex.getMetadataJson())) {
818             nextVersionToscaElementVertex.setMetadataJson(new HashMap<>(toscaElementVertex.getMetadataJson()));
819             nextVersionToscaElementVertex.updateMetadataJsonWithCurrentMetadataProperties();
820         }
821         long currTime = System.currentTimeMillis();
822         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CREATION_DATE, currTime);
823         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, currTime);
824         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_CREATOR, modifierVertex.getUniqueId());
825         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_LAST_UPDATER, modifierVertex.getUniqueId());
826         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE) {
827             nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CONFORMANCE_LEVEL,
828                 ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel());
829         }
830         if (!MapUtils.isEmpty(toscaElementVertex.getJson())) {
831             nextVersionToscaElementVertex.setJson(new HashMap<String, ToscaDataDefinition>(toscaElementVertex.getJson()));
832         }
833         return nextVersionToscaElementVertex;
834     }
835
836     private Either<GraphVertex, StorageOperationStatus> cloneToscaElementForCertify(GraphVertex toscaElementVertex, GraphVertex modifierVertex,
837                                                                                     Integer majorVersion) {
838         return getToscaElementOperation(toscaElementVertex.getLabel())
839             .cloneToscaElement(toscaElementVertex, cloneGraphVertexForCertify(toscaElementVertex, modifierVertex, majorVersion), modifierVertex)
840             .right().map(
841                 status -> logDebugMessageAndReturnStorageOperationStatus(status, "Failed to clone tosca element {} for certification. Status is {}. ",
842                     toscaElementVertex.getUniqueId(), status)).left().bind(
843                 clonedToscaElement -> updateEdgesDeleteNotCertifiedVersionsAndHandlePreviousVersions(clonedToscaElement, toscaElementVertex,
844                     majorVersion));
845     }
846
847     private Either<GraphVertex, StorageOperationStatus> updateEdgesDeleteNotCertifiedVersionsAndHandlePreviousVersions(GraphVertex clonedToscaElement,
848                                                                                                                        GraphVertex toscaElementVertex,
849                                                                                                                        Integer majorVersion) {
850         StorageOperationStatus updateEdgeToCatalog = updateEdgeToCatalogRoot(clonedToscaElement, toscaElementVertex);
851         if (updateEdgeToCatalog != StorageOperationStatus.OK) {
852             return Either.right(updateEdgeToCatalog);
853         } else {
854             Either<List<GraphVertex>, StorageOperationStatus> deleteResultEither = deleteAllPreviousNotCertifiedVersions(toscaElementVertex);
855             if (deleteResultEither == null) {
856                 return Either.right(logDebugMessageAndReturnStorageOperationStatus(StorageOperationStatus.GENERAL_ERROR,
857                     "Failed to delete all previous not certified versions of tosca element {}. Null value returned.",
858                     toscaElementVertex.getUniqueId()));
859             } else {
860                 return deleteResultEither.right().map(status -> logDebugMessageAndReturnStorageOperationStatus(status,
861                     "Failed to delete all previous not certified versions of tosca element {}. Status is {}. ", toscaElementVertex.getUniqueId(),
862                     status)).left().bind(deleteResult -> handlePreviousVersionRelation(clonedToscaElement, deleteResult, majorVersion));
863             }
864         }
865     }
866
867     private Either<GraphVertex, StorageOperationStatus> handlePreviousVersionRelation(GraphVertex clonedToscaElement,
868                                                                                       List<GraphVertex> deletedVersions, Integer majorVersion) {
869         Either<GraphVertex, StorageOperationStatus> result = null;
870         Vertex previousCertifiedToscaElement = null;
871         if (majorVersion > 0) {
872             List<GraphVertex> firstMinorVersionVertex = deletedVersions.stream()
873                 .filter(gv -> getMinorVersion((String) gv.getMetadataProperty(GraphPropertyEnum.VERSION)) == 1).collect(Collectors.toList());
874             if (CollectionUtils.isEmpty(firstMinorVersionVertex)) {
875                 result = Either.right(StorageOperationStatus.NOT_FOUND);
876             } else {
877                 previousCertifiedToscaElement = getPreviousCertifiedToscaElement(firstMinorVersionVertex.get(0));
878                 if (previousCertifiedToscaElement == null) {
879                     result = Either.right(StorageOperationStatus.NOT_FOUND);
880                 }
881             }
882             if (result == null) {
883                 JanusGraphOperationStatus status = janusGraphDao
884                     .createEdge(previousCertifiedToscaElement, clonedToscaElement.getVertex(), EdgeLabelEnum.VERSION, new HashMap<>());
885                 if (status != JanusGraphOperationStatus.OK) {
886                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
887                         "Failed to create edge with label {} from vertex {} to tosca element vertex {} on graph. Status is {}. ",
888                         EdgeLabelEnum.VERSION, previousCertifiedToscaElement.property(GraphPropertyEnum.UNIQUE_ID.getProperty()),
889                         clonedToscaElement.getUniqueId(), status);
890                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
891                 }
892             }
893         }
894         if (result == null) {
895             result = Either.left(clonedToscaElement);
896         }
897         return result;
898     }
899
900     private Vertex getPreviousCertifiedToscaElement(GraphVertex graphVertex) {
901         Iterator<Edge> edges = graphVertex.getVertex().edges(Direction.IN, EdgeLabelEnum.VERSION.name());
902         if (edges.hasNext()) {
903             return edges.next().outVertex();
904         }
905         return null;
906     }
907
908     private Either<List<GraphVertex>, StorageOperationStatus> deleteAllPreviousNotCertifiedVersions(GraphVertex toscaElementVertex) {
909         Either<List<GraphVertex>, StorageOperationStatus> result = null;
910         ToscaElementOperation operation = getToscaElementOperation(toscaElementVertex.getLabel());
911         List<GraphVertex> previosVersions = null;
912         Object uuid = toscaElementVertex.getMetadataProperty(GraphPropertyEnum.UUID);
913         Object componentName = toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NAME);
914         try {
915             Map<GraphPropertyEnum, Object> properties = new HashMap<>();
916             properties.put(GraphPropertyEnum.UUID, uuid);
917             properties.put(GraphPropertyEnum.NAME, componentName);
918             Either<List<GraphVertex>, JanusGraphOperationStatus> getToscaElementsRes = janusGraphDao
919                 .getByCriteria(toscaElementVertex.getLabel(), properties, JsonParseFlagEnum.ParseMetadata);
920             if (getToscaElementsRes.isRight()) {
921                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getToscaElementsRes.right().value()));
922             }
923             if (result == null) {
924                 previosVersions = getToscaElementsRes.left().value();
925                 Either<Boolean, StorageOperationStatus> deleteResult = markToscaElementsAsDeleted(operation, getToscaElementsRes.left().value());
926                 if (deleteResult.isRight()) {
927                     result = Either.right(deleteResult.right().value());
928                 }
929             }
930             if (result == null) {
931                 result = Either.left(previosVersions);
932             }
933         } catch (Exception e) {
934             CommonUtility
935                 .addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occurred during deleting all tosca elements by UUID {} and name {}. {} ", uuid,
936                     componentName, e.getMessage());
937         }
938         return result;
939     }
940
941     private GraphVertex cloneGraphVertexForCertify(GraphVertex toscaElementVertex, GraphVertex modifierVertex, Integer majorVersion) {
942         GraphVertex nextVersionToscaElementVertex = new GraphVertex();
943         String uniqueId = IdBuilderUtils.generateUniqueId();
944         Map<GraphPropertyEnum, Object> metadataProperties = new EnumMap<>(toscaElementVertex.getMetadataProperties());
945         nextVersionToscaElementVertex.setMetadataProperties(metadataProperties);
946         nextVersionToscaElementVertex.setUniqueId(uniqueId);
947         nextVersionToscaElementVertex.setLabel(toscaElementVertex.getLabel());
948         nextVersionToscaElementVertex.setType(toscaElementVertex.getType());
949         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uniqueId);
950         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, nextVersionToscaElementVertex.getType().name());
951         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.VERSION, (majorVersion + 1) + VERSION_DELIMITER + "0");
952         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
953         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
954         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CREATION_DATE, System.currentTimeMillis());
955         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, null);
956         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_CREATOR, modifierVertex.getUniqueId());
957         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_LAST_UPDATER, modifierVertex.getUniqueId());
958         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE) {
959             nextVersionToscaElementVertex
960                 .addMetadataProperty(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED.name());
961         }
962         if (!MapUtils.isEmpty(toscaElementVertex.getMetadataJson())) {
963             nextVersionToscaElementVertex.setMetadataJson(new HashMap<>(toscaElementVertex.getMetadataJson()));
964             nextVersionToscaElementVertex.updateMetadataJsonWithCurrentMetadataProperties();
965         }
966         if (!MapUtils.isEmpty(toscaElementVertex.getJson())) {
967             nextVersionToscaElementVertex.setJson(new HashMap<String, ToscaDataDefinition>(toscaElementVertex.getJson()));
968         }
969         return nextVersionToscaElementVertex;
970     }
971
972     private Either<GraphVertex, StorageOperationStatus> checkinToscaELement(LifecycleStateEnum currState, GraphVertex toscaElementVertex,
973                                                                             GraphVertex ownerVertex, GraphVertex modifierVertex,
974                                                                             LifecycleStateEnum nextState) {
975         Either<GraphVertex, StorageOperationStatus> updateRelationsRes;
976         Either<GraphVertex, StorageOperationStatus> result = changeStateToCheckedIn(currState, toscaElementVertex, ownerVertex, modifierVertex);
977         if (result.isLeft()) {
978             toscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, nextState.name());
979             toscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
980             result = updateToscaElementVertexMetadataPropertiesAndJson(toscaElementVertex);
981         }
982         if (result.isLeft()) {
983             updateRelationsRes = updateLastModifierEdge(toscaElementVertex, ownerVertex, modifierVertex);
984             if (updateRelationsRes.isRight()) {
985                 result = Either.right(updateRelationsRes.right().value());
986             }
987         }
988         return result;
989     }
990
991     private Either<GraphVertex, StorageOperationStatus> updateToscaElementVertexMetadataPropertiesAndJson(GraphVertex toscaElementVertex) {
992         Either<GraphVertex, StorageOperationStatus> result;
993         Either<GraphVertex, JanusGraphOperationStatus> updateVertexRes = janusGraphDao.updateVertex(toscaElementVertex);
994         if (updateVertexRes.isRight()) {
995             JanusGraphOperationStatus titatStatus = updateVertexRes.right().value();
996             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update state of tosca element vertex {} metadata. Status is  {}",
997                 toscaElementVertex.getUniqueId(), titatStatus);
998             result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(titatStatus));
999         } else {
1000             result = Either.left(updateVertexRes.left().value());
1001         }
1002         return result;
1003     }
1004
1005     private Either<GraphVertex, StorageOperationStatus> changeStateToCheckedIn(LifecycleStateEnum currState, GraphVertex toscaElementVertex,
1006                                                                                GraphVertex ownerVertex, GraphVertex modifierVertex) {
1007         Either<GraphVertex, StorageOperationStatus> result = null;
1008         LifecycleStateEnum nextState = LifecycleStateEnum.NOT_CERTIFIED_CHECKIN;
1009         String faileToUpdateStateMsg = "Failed to update state of tosca element {}. Status is  {}";
1010         // Remove CHECKOUT relation
1011         Either<Edge, JanusGraphOperationStatus> deleteEdgeResult = janusGraphDao.deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.STATE);
1012         if (deleteEdgeResult.isRight()) {
1013             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, faileToUpdateStateMsg, toscaElementVertex.getUniqueId());
1014             result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(deleteEdgeResult.right().value()));
1015         }
1016         if (result == null) {
1017             // Create CHECKIN relation
1018             Map<EdgePropertyEnum, Object> edgeProperties = new EnumMap<>(EdgePropertyEnum.class);
1019             edgeProperties.put(EdgePropertyEnum.STATE, nextState);
1020             JanusGraphOperationStatus createEdgeRes = janusGraphDao
1021                 .createEdge(modifierVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.STATE, edgeProperties);
1022             if (createEdgeRes != JanusGraphOperationStatus.OK) {
1023                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, faileToUpdateStateMsg, toscaElementVertex.getUniqueId());
1024                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdgeRes));
1025             }
1026         }
1027         if (result == null) {
1028             result = Either.left(toscaElementVertex);
1029         }
1030         return result;
1031     }
1032
1033     private Either<GraphVertex, StorageOperationStatus> updateLastModifierEdge(GraphVertex toscaElementVertex, GraphVertex ownerVertex,
1034                                                                                GraphVertex modifierVertex) {
1035         Either<GraphVertex, StorageOperationStatus> result = null;
1036         if (!modifierVertex.getMetadataProperties().get(GraphPropertyEnum.USERID)
1037             .equals(ownerVertex.getMetadataProperties().get(GraphPropertyEnum.USERID))) {
1038             Either<Edge, JanusGraphOperationStatus> deleteEdgeRes = janusGraphDao
1039                 .deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.LAST_MODIFIER);
1040             if (deleteEdgeRes.isRight()) {
1041                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete last modifier {} to tosca element {}. Edge type is {}",
1042                     ownerVertex.getUniqueId(), ownerVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
1043                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(deleteEdgeRes.right().value()));
1044             }
1045             if (result == null) {
1046                 JanusGraphOperationStatus createEdgeRes = janusGraphDao
1047                     .createEdge(modifierVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.LAST_MODIFIER, new HashMap<>());
1048                 if (createEdgeRes != JanusGraphOperationStatus.OK) {
1049                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to associate user {} to component {}. Edge type is {}",
1050                         modifierVertex.getUniqueId(), ownerVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
1051                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdgeRes));
1052                 } else {
1053                     result = Either.left(modifierVertex);
1054                 }
1055             }
1056         } else {
1057             result = Either.left(ownerVertex);
1058         }
1059         return result;
1060     }
1061
1062     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForCheckin(String toscaElementId,
1063                                                                                                                       String modifierId,
1064                                                                                                                       String ownerId) {
1065         Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGetParameters = new HashMap<>();
1066         verticesToGetParameters.put(toscaElementId, new ImmutablePair<>(GraphPropertyEnum.UNIQUE_ID, JsonParseFlagEnum.ParseMetadata));
1067         verticesToGetParameters.put(modifierId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1068         verticesToGetParameters.put(ownerId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1069         return verticesToGetParameters;
1070     }
1071
1072     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForRequestCertification(
1073         String toscaElementId, String modifierId, String ownerId) {
1074         Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGetParameters = new HashMap<>();
1075         verticesToGetParameters.put(toscaElementId, new ImmutablePair<>(GraphPropertyEnum.UNIQUE_ID, JsonParseFlagEnum.ParseAll));
1076         verticesToGetParameters.put(modifierId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1077         verticesToGetParameters.put(ownerId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1078         return verticesToGetParameters;
1079     }
1080
1081     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForCheckout(String toscaElementId,
1082                                                                                                                        String modifierId,
1083                                                                                                                        String ownerId) {
1084         //Implementation is currently identical
1085         return prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId);
1086     }
1087
1088     private String getNextCertifiedVersion(String version) {
1089         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1090         Integer nextMajorVersion = Integer.parseInt(versionParts[0]) + 1;
1091         return nextMajorVersion + VERSION_DELIMITER + "0";
1092     }
1093
1094     private String getNextVersion(String currVersion) {
1095         String[] versionParts = currVersion.split(VERSION_DELIMITER_REGEXP);
1096         Integer minorVersion = Integer.parseInt(versionParts[1]) + 1;
1097         return versionParts[0] + VERSION_DELIMITER + minorVersion;
1098     }
1099
1100     private Integer getMinorVersion(String version) {
1101         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1102         return Integer.parseInt(versionParts[1]);
1103     }
1104
1105     private Integer getMajorVersion(String version) {
1106         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1107         return Integer.parseInt(versionParts[0]);
1108     }
1109
1110     private boolean isFirstCheckoutAfterCertification(String version) {
1111         return (Integer.parseInt(version.split(VERSION_DELIMITER_REGEXP)[0]) != 0
1112             && Integer.parseInt(version.split(VERSION_DELIMITER_REGEXP)[1]) == 1);
1113     }
1114
1115     public Either<ToscaElement, StorageOperationStatus> forceCerificationOfToscaElement(String toscaElementId, String modifierId, String ownerId,
1116                                                                                         String currVersion) {
1117         Either<GraphVertex, StorageOperationStatus> resultUpdate = null;
1118         Either<ToscaElement, StorageOperationStatus> result = null;
1119         GraphVertex toscaElement = null;
1120         GraphVertex modifier = null;
1121         GraphVertex owner;
1122         try {
1123             Either<Map<String, GraphVertex>, JanusGraphOperationStatus> getVerticesRes = janusGraphDao
1124                 .getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId));
1125             if (getVerticesRes.isRight()) {
1126                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
1127                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getVerticesRes.right().value()));
1128             }
1129             if (result == null) {
1130                 toscaElement = getVerticesRes.left().value().get(toscaElementId);
1131                 modifier = getVerticesRes.left().value().get(modifierId);
1132                 owner = getVerticesRes.left().value().get(ownerId);
1133                 StorageOperationStatus status = handleRelationsUponForceCertification(toscaElement, modifier, owner);
1134                 if (status != StorageOperationStatus.OK) {
1135                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
1136                         "Failed to handle relations on certification request for tosca element {}. Status is {}. ", toscaElement.getUniqueId(),
1137                         status);
1138                 }
1139             }
1140             if (result == null) {
1141                 LifecycleStateEnum nextState = LifecycleStateEnum.CERTIFIED;
1142                 toscaElement.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
1143                 toscaElement.addMetadataProperty(GraphPropertyEnum.VERSION, getNextCertifiedVersion(currVersion));
1144                 resultUpdate = updateToscaElementVertexMetadataPropertiesAndJson(toscaElement);
1145                 if (resultUpdate.isRight()) {
1146                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set lifecycle for tosca elememt {} to state {}, error: {}",
1147                         toscaElement.getUniqueId(), nextState, resultUpdate.right().value());
1148                     result = Either.right(resultUpdate.right().value());
1149                 }
1150             }
1151             if (result == null) {
1152                 ToscaElementOperation operation = getToscaElementOperation(toscaElement.getLabel());
1153                 result = operation.getToscaElement(toscaElement.getUniqueId());
1154             }
1155             return result;
1156         } catch (Exception e) {
1157             CommonUtility
1158                 .addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during request certification tosca element {}. {}", toscaElementId,
1159                     e.getMessage());
1160         }
1161         return result;
1162     }
1163
1164     private StorageOperationStatus handleRelationsUponForceCertification(GraphVertex toscaElement, GraphVertex modifier, GraphVertex owner) {
1165         StorageOperationStatus result = null;
1166         JanusGraphOperationStatus status = janusGraphDao
1167             .replaceEdgeLabel(owner.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE);
1168         if (status != JanusGraphOperationStatus.OK) {
1169             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1170         }
1171         if (result == null) {
1172             Map<EdgePropertyEnum, Object> properties = new EnumMap<>(EdgePropertyEnum.class);
1173             properties.put(EdgePropertyEnum.STATE, LifecycleStateEnum.CERTIFIED);
1174             status = janusGraphDao.createEdge(modifier, toscaElement, EdgeLabelEnum.STATE, properties);
1175             if (status != JanusGraphOperationStatus.OK) {
1176                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "failed to create edge. Status is {}", status);
1177                 result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1178             }
1179         }
1180         if (result == null) {
1181             result = StorageOperationStatus.OK;
1182         }
1183         return result;
1184     }
1185
1186     private StorageOperationStatus updateEdgeToCatalogRootByUndoCheckout(JanusGraphVertex preV, GraphVertex curV) {
1187         if (preV == null) {
1188             return updateEdgeToCatalogRoot(null, curV);
1189         }
1190         String uniqueIdPreVer = (String) janusGraphDao.getProperty((JanusGraphVertex) preV, GraphPropertyEnum.UNIQUE_ID.getProperty());
1191         LifecycleStateEnum state = LifecycleStateEnum.findState((String) janusGraphDao.getProperty(preV, GraphPropertyEnum.STATE.getProperty()));
1192         if (state == LifecycleStateEnum.CERTIFIED) {
1193             return updateEdgeToCatalogRoot(null, curV);
1194         }
1195         return janusGraphDao.getVertexById(uniqueIdPreVer)
1196             .either(l -> updateEdgeToCatalogRoot(l, curV), DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
1197     }
1198
1199     private StorageOperationStatus updateEdgeToCatalogRoot(GraphVertex newVersionV, GraphVertex prevVersionV) {
1200         Either<GraphVertex, JanusGraphOperationStatus> catalog = janusGraphDao.getVertexByLabel(VertexTypeEnum.CATALOG_ROOT);
1201         if (catalog.isRight()) {
1202             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch catalog vertex. error {}", catalog.right().value());
1203             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(catalog.right().value());
1204         }
1205         GraphVertex catalogV = catalog.left().value();
1206         if (newVersionV != null) {
1207             Boolean isAbstract = (Boolean) newVersionV.getMetadataProperty(GraphPropertyEnum.IS_ABSTRACT);
1208             if (isAbstract == null || !isAbstract) {
1209                 // create new vertex
1210                 JanusGraphOperationStatus result = janusGraphDao.createEdge(catalogV, newVersionV, EdgeLabelEnum.CATALOG_ELEMENT, null);
1211                 if (result != JanusGraphOperationStatus.OK) {
1212                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge from {} to catalog vertex. error {}",
1213                         newVersionV.getUniqueId(), result);
1214                     return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(result);
1215                 }
1216             }
1217         }
1218         if (prevVersionV != null) {
1219             Boolean isAbstract = (Boolean) prevVersionV.getMetadataProperty(GraphPropertyEnum.IS_ABSTRACT);
1220             if (isAbstract == null || !isAbstract) {
1221                 // if prev == null -> new resource was added
1222                 Either<Edge, JanusGraphOperationStatus> deleteResult = janusGraphDao
1223                     .deleteEdge(catalogV, prevVersionV, EdgeLabelEnum.CATALOG_ELEMENT);
1224                 if (deleteResult.isRight()) {
1225                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete edge from {} to catalog vertex. error {}",
1226                         prevVersionV.getUniqueId(), deleteResult.right().value());
1227                     return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(deleteResult.right().value());
1228                 }
1229             }
1230         }
1231         return StorageOperationStatus.OK;
1232     }
1233 }