re base code
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsontitan / 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
21 package org.openecomp.sdc.be.model.jsontitan.operations;
22
23 import com.thinkaurelius.titan.core.TitanVertex;
24 import fj.data.Either;
25 import org.apache.commons.collections.CollectionUtils;
26 import org.apache.commons.collections.MapUtils;
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.apache.tinkerpop.gremlin.structure.Direction;
30 import org.apache.tinkerpop.gremlin.structure.Edge;
31 import org.apache.tinkerpop.gremlin.structure.Vertex;
32 import org.openecomp.sdc.be.config.ConfigurationManager;
33 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
34 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
35 import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum;
36 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
37 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
38 import org.openecomp.sdc.be.dao.jsongraph.utils.IdBuilderUtils;
39 import org.openecomp.sdc.be.dao.jsongraph.utils.JsonParserUtils;
40 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
41 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
42 import org.openecomp.sdc.be.datatypes.elements.*;
43 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
44 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
45 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
46 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
47 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
48 import org.openecomp.sdc.be.model.ComponentParametersView;
49 import org.openecomp.sdc.be.model.DistributionStatusEnum;
50 import org.openecomp.sdc.be.model.LifecycleStateEnum;
51 import org.openecomp.sdc.be.model.User;
52 import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate;
53 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
54 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
55 import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum;
56 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
57 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
58 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
59 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
60 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
61 import org.openecomp.sdc.common.log.wrappers.Logger;
62
63 import java.util.*;
64 import java.util.stream.Collectors;
65
66 @org.springframework.stereotype.Component("tosca-element-lifecycle-operation")
67
68 /**
69  * Allows to perform lifecycle operations: checkin, checkout, submit for testing, start certification and certification process for tosca element
70  */
71 public class ToscaElementLifecycleOperation extends BaseOperation {
72
73     private static final String FAILED_TO_DELETE_LAST_STATE_EDGE_STATUS_IS = "Failed to delete last state edge. Status is {}. ";
74         private static final String FAILED_TO_GET_VERTICES = "Failed to get vertices by id {}. Status is {}. ";
75     public static final String VERSION_DELIMITER = ".";
76     public static final String VERSION_DELIMITER_REGEXP = "\\.";
77
78     private static final Logger log = Logger.getLogger(ToscaElementLifecycleOperation.class);
79
80     /**
81      * Performs changing a lifecycle state of tosca element from "checked out" or "ready for certification" to "checked in"
82      * 
83      * @param currState
84      * @param toscaElementId
85      * @param modifierId
86      * @param ownerId
87      * @return
88      */
89     public Either<ToscaElement, StorageOperationStatus> checkinToscaELement(LifecycleStateEnum currState, String toscaElementId, String modifierId, String ownerId) {
90         Either<GraphVertex, StorageOperationStatus> updateResult = null;
91         Either<ToscaElement, StorageOperationStatus> result = null;
92         Map<String, GraphVertex> vertices = null;
93         ToscaElementOperation operation;
94         try {
95             Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForCheckin(toscaElementId, modifierId, ownerId));
96             if (getVerticesRes.isRight()) {
97                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
98                 updateResult = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value()));
99             } else {
100                 vertices = getVerticesRes.left().value();
101                 updateResult = checkinToscaELement(currState, vertices.get(toscaElementId), vertices.get(ownerId), vertices.get(modifierId), LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
102             }
103             if (updateResult.isLeft()) {
104                 operation = getToscaElementOperation(vertices.get(toscaElementId).getLabel());
105                 result = operation.getToscaElement(updateResult.left().value().getUniqueId());
106                 if (result.isRight()) {
107                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated tosca element {}. Status is {}", toscaElementId, result.right().value());
108                 }
109             } else {
110                 result = Either.right(updateResult.right().value());
111             }
112         } catch (Exception e) {
113             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during checkin of tosca element {}. {} ", toscaElementId, e.getMessage());
114         }
115         return result;
116     }
117
118     /**
119      * Returns vertex presenting owner of tosca element specified by uniqueId
120      * 
121      * @param toscaElementId
122      * @return
123      */
124     public Either<User, StorageOperationStatus> getToscaElementOwner(String toscaElementId) {
125         Either<User, StorageOperationStatus> result = null;
126         GraphVertex toscaElement = null;
127         Either<GraphVertex, TitanOperationStatus> getToscaElementRes = titanDao.getVertexById(toscaElementId, JsonParseFlagEnum.NoParse);
128         if (getToscaElementRes.isRight()) {
129             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getToscaElementRes.right().value()));
130         }
131         if (result == null) {
132             toscaElement = getToscaElementRes.left().value();
133             Iterator<Vertex> vertices = toscaElement.getVertex().vertices(Direction.IN, EdgeLabelEnum.STATE.name());
134             if (vertices == null || !vertices.hasNext()) {
135                 result = Either.right(StorageOperationStatus.NOT_FOUND);
136             } else {
137                 result = Either.left(convertToUser(vertices.next()));
138             }
139         }
140         return result;
141     }
142
143     /**
144      * Returns vertex presenting owner of tosca element specified by uniqueId
145      * 
146      * @param toscaElement
147      * @return
148      */
149     public Either<User, StorageOperationStatus> getToscaElementOwner(GraphVertex toscaElement) {
150         Either<User, StorageOperationStatus> result = null;
151         Iterator<Vertex> vertices = toscaElement.getVertex().vertices(Direction.IN, EdgeLabelEnum.STATE.name());
152         if (vertices == null || !vertices.hasNext()) {
153             result = Either.right(StorageOperationStatus.NOT_FOUND);
154         } else {
155             result = Either.left(convertToUser(vertices.next()));
156         }
157         return result;
158     }
159
160     /**
161      * Performs checkout of a tosca element
162      * 
163      * @param toscaElementId
164      * @param modifierId
165      * @param ownerId
166      * @return
167      */
168     public Either<ToscaElement, StorageOperationStatus> checkoutToscaElement(String toscaElementId, String modifierId, String ownerId) {
169         Either<ToscaElement, StorageOperationStatus> result = null;
170         Map<String, GraphVertex> vertices = null;
171         try {
172             Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForCheckout(toscaElementId, modifierId, ownerId));
173             if (getVerticesRes.isRight()) {
174                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
175                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value()));
176             }
177             if (result == null) {
178                 vertices = getVerticesRes.left().value();
179                 // update previous component if not certified
180                 StorageOperationStatus status = updatePreviousVersion(vertices.get(toscaElementId), vertices.get(ownerId));
181                 if (status != StorageOperationStatus.OK) {
182                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update vertex with id {} . Status is {}. ", status);
183                     result = Either.right(status);
184                 }
185             }
186             if (result == null) {
187                 result = cloneToscaElementForCheckout(vertices.get(toscaElementId), vertices.get(modifierId));
188                 if (result.isRight()) {
189                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to checkout tosca element {}. Status is {} ", toscaElementId, result.right().value());
190                 }
191
192             }
193         } catch (Exception e) {
194             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during checkout tosca element {}. {}", toscaElementId, e.getMessage());
195         }
196         return result;
197     }
198
199     /**
200      * Performs undo checkout for tosca element
201      * 
202      * @param toscaElementId
203      * @return
204      */
205     public Either<ToscaElement, StorageOperationStatus> undoCheckout(String toscaElementId) {
206         Either<ToscaElement, StorageOperationStatus> result = null;
207         Either<GraphVertex, TitanOperationStatus> getToscaElementRes = null;
208         Iterator<Edge> nextVersionComponentIter = null;
209         ToscaElementOperation operation;
210         Vertex preVersionVertex = null;
211         try {
212             getToscaElementRes = titanDao.getVertexById(toscaElementId, JsonParseFlagEnum.ParseMetadata);
213             if (getToscaElementRes.isRight()) {
214                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
215                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getToscaElementRes.right().value()));
216             }
217             GraphVertex currVersionV = getToscaElementRes.left().value();
218             if (result == null && hasPreviousVersion(currVersionV)) {
219                 // find previous version
220                 nextVersionComponentIter = currVersionV.getVertex().edges(Direction.IN, EdgeLabelEnum.VERSION.name());
221                 if (nextVersionComponentIter == null || !nextVersionComponentIter.hasNext()) {
222                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch previous version of tosca element with name {}. ", currVersionV.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME).toString());
223                     result = Either.right(StorageOperationStatus.NOT_FOUND);
224                 }
225                 if (result == null) {
226                     preVersionVertex = nextVersionComponentIter.next().outVertex();
227                     StorageOperationStatus updateOldResourceResult = updateOldToscaElementBeforeUndoCheckout(preVersionVertex);
228                     if (updateOldResourceResult != StorageOperationStatus.OK) {
229                         result = Either.right(updateOldResourceResult);
230                     }
231                 }
232             }
233             if (result == null) {
234                 StorageOperationStatus updateCatalogRes = updateEdgeToCatalogRootByUndoCheckout((TitanVertex) preVersionVertex, currVersionV);
235                 if (updateCatalogRes != StorageOperationStatus.OK) {
236                     return Either.right(updateCatalogRes);
237                 }
238                 operation = getToscaElementOperation(currVersionV.getLabel());
239                 result = operation.deleteToscaElement(currVersionV);
240             }
241         } catch (Exception e) {
242             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during undo checkout tosca element {}. {}", toscaElementId, e.getMessage());
243         }
244         return result;
245     }
246
247     private boolean hasPreviousVersion(GraphVertex toscaElementVertex) {
248         boolean hasPreviousVersion = true;
249         String version = (String) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION);
250         if (StringUtils.isEmpty(version) || version.equals("0.1"))
251             hasPreviousVersion = false;
252         return hasPreviousVersion;
253     }
254
255     /**
256      * Performs request certification for tosca element
257      * 
258      * @param toscaElementId
259      * @param modifierId
260      * @param ownerId
261      * @return
262      */
263     public Either<ToscaElement, StorageOperationStatus> requestCertificationToscaElement(String toscaElementId, String modifierId, String ownerId) {
264         Either<GraphVertex, StorageOperationStatus> resultUpdate = null;
265         Either<ToscaElement, StorageOperationStatus> result = null;
266         GraphVertex toscaElement = null;
267         GraphVertex modifier = null;
268         GraphVertex owner;
269         try {
270             Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId));
271             if (getVerticesRes.isRight()) {
272                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
273                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value()));
274             }
275             if (result == null) {
276                 toscaElement = getVerticesRes.left().value().get(toscaElementId);
277                 modifier = getVerticesRes.left().value().get(modifierId);
278                 owner = getVerticesRes.left().value().get(ownerId);
279
280                 StorageOperationStatus status = handleRelationsUponRequestForCertification(toscaElement, modifier, owner);
281                 if (status != StorageOperationStatus.OK) {
282                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations on certification request for tosca element {}. Status is {}. ", toscaElement.getUniqueId(), status);
283                 }
284             }
285             if (result == null) {
286                 LifecycleStateEnum nextState = LifecycleStateEnum.READY_FOR_CERTIFICATION;
287
288                 toscaElement.addMetadataProperty(GraphPropertyEnum.STATE, nextState.name());
289                 toscaElement.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
290
291                 resultUpdate = updateToscaElementVertexMetadataPropertiesAndJson(toscaElement);
292                 if (resultUpdate.isRight()) {
293                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set lifecycle for tosca elememt {} to state {}, error: {}", toscaElement.getUniqueId(), nextState, resultUpdate.right().value());
294                     result = Either.right(resultUpdate.right().value());
295                 }
296             }
297             if (result == null) {
298                 ToscaElementOperation operation = getToscaElementOperation(toscaElement.getLabel());
299                 result = operation.getToscaElement(toscaElement.getUniqueId());
300             }
301             return result;
302
303         } catch (Exception e) {
304             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during request certification tosca element {}. {}", toscaElementId, e.getMessage());
305         }
306         return result;
307     }
308
309     /**
310      * Starts certification of tosca element
311      * 
312      * @param toscaElementId
313      * @param modifierId
314      * @param ownerId
315      * @return
316      */
317     public Either<ToscaElement, StorageOperationStatus> startCertificationToscaElement(String toscaElementId, String modifierId, String ownerId) {
318         Either<ToscaElement, StorageOperationStatus> result = null;
319         Either<GraphVertex, StorageOperationStatus> resultUpdate = null;
320         GraphVertex toscaElement = null;
321         GraphVertex modifier = null;
322         GraphVertex owner;
323         try {
324             Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId));
325             if (getVerticesRes.isRight()) {
326                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
327                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value()));
328             }
329             if (result == null) {
330                 toscaElement = getVerticesRes.left().value().get(toscaElementId);
331                 modifier = getVerticesRes.left().value().get(modifierId);
332                 owner = getVerticesRes.left().value().get(ownerId);
333
334                 StorageOperationStatus status = handleRelationsUponCertification(toscaElement, modifier, owner);
335                 if (status != StorageOperationStatus.OK) {
336                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations during certification of tosca element {}. Status is {}. ", toscaElement.getUniqueId(), status);
337                 }
338             }
339             if (result == null) {
340                 LifecycleStateEnum nextState = LifecycleStateEnum.CERTIFICATION_IN_PROGRESS;
341
342                 toscaElement.addMetadataProperty(GraphPropertyEnum.STATE, nextState.name());
343                 toscaElement.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
344
345                 resultUpdate = updateToscaElementVertexMetadataPropertiesAndJson(toscaElement);
346                 if (resultUpdate.isRight()) {
347                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Couldn't set lifecycle for component {} to state {}, error: {}", toscaElement.getUniqueId(), nextState, resultUpdate.right().value());
348                     result = Either.right(resultUpdate.right().value());
349                 }
350             }
351             if (result == null) {
352                 ToscaElementOperation operation = getToscaElementOperation(toscaElement.getLabel());
353                 result = operation.getToscaElement(toscaElement.getUniqueId());
354             }
355         } catch (Exception e) {
356             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during start certification tosca element {}. {}", toscaElementId, e.getMessage());
357         }
358         return result;
359     }
360
361     public Either<ToscaElement, StorageOperationStatus> certifyToscaElement(String toscaElementId, String modifierId, String ownerId) {
362         Either<ToscaElement, StorageOperationStatus> result = null;
363         Either<GraphVertex, StorageOperationStatus> cloneRes = null;
364         GraphVertex toscaElement = null;
365         GraphVertex modifier = null;
366         GraphVertex certifiedToscaElement = null;
367         Integer majorVersion = null;
368
369         StorageOperationStatus status;
370         try {
371             Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId));
372             if (getVerticesRes.isRight()) {
373                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
374                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value()));
375             }
376             if (result == null) {
377                 toscaElement = getVerticesRes.left().value().get(toscaElementId);
378                 modifier = getVerticesRes.left().value().get(modifierId);
379                 majorVersion = getMajorVersion((String) toscaElement.getMetadataProperty(GraphPropertyEnum.VERSION));
380                 status = handleRelationsOfPreviousToscaElementBeforeCertifying(toscaElement, modifier, majorVersion);
381                 if (status != StorageOperationStatus.OK) {
382                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations of previous tosca element before certifying {}. Status is {}. ", toscaElement.getUniqueId(), status);
383                 }
384             }
385             if (result == null) {
386                 cloneRes = cloneToscaElementForCertify(toscaElement, modifier, majorVersion);
387                 if (cloneRes.isRight()) {
388                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to clone tosca element during certification. ");
389                     result = Either.right(cloneRes.right().value());
390                 }
391             }
392             if (result == null) {
393                 certifiedToscaElement = cloneRes.left().value();
394                 status = handleRelationsOfNewestCertifiedToscaElement(toscaElement, certifiedToscaElement);
395                 if (status != StorageOperationStatus.OK) {
396                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations of newest certified tosca element {}. Status is {}. ", certifiedToscaElement.getUniqueId(), status);
397                 }
398             }
399             if (result == null) {
400                 return getToscaElementOperation(toscaElement.getLabel()).getToscaElement(certifiedToscaElement.getUniqueId());
401             }
402         } catch (Exception e) {
403             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during certification tosca element {}. {}", toscaElementId, e.getMessage());
404         }
405         return result;
406     }
407
408     /**
409      * Deletes (marks as deleted) all tosca elements according received name and uuid
410      * 
411      * @param vertexType
412      * @param componentType
413      * @param componentName
414      * @param uuid
415      * @return
416      */
417     public Either<Boolean, StorageOperationStatus> deleteOldToscaElementVersions(VertexTypeEnum vertexType, ComponentTypeEnum componentType, String componentName, String uuid) {
418
419         Either<Boolean, StorageOperationStatus> result = null;
420         ToscaElementOperation operation = getToscaElementOperation(componentType);
421
422         try {
423             Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
424             properties.put(GraphPropertyEnum.UUID, uuid);
425             properties.put(GraphPropertyEnum.NAME, componentName);
426             Either<List<GraphVertex>, TitanOperationStatus> getToscaElementsRes = titanDao.getByCriteria(vertexType, properties, JsonParseFlagEnum.ParseMetadata);
427             if (getToscaElementsRes.isRight()) {
428                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getToscaElementsRes.right().value()));
429             }
430             if (result == null) {
431                 result = markToscaElementsAsDeleted(operation, getToscaElementsRes.left().value());
432             }
433             if (result == null) {
434                 result = Either.left(true);
435             }
436         } catch (Exception e) {
437             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during deleteng all tosca elements by UUID {} and name {}. {} ", uuid, componentName, e.getMessage());
438         }
439         return result;
440     }
441
442     /**
443      * Performs cancelation or failure of certification for received tosca element
444      * 
445      * @param toscaElementId
446      * @param modifierId
447      * @param ownerId
448      * @param nextState
449      * @return
450      */
451     public Either<ToscaElement, StorageOperationStatus> cancelOrFailCertification(String toscaElementId, String modifierId, String ownerId, LifecycleStateEnum nextState) {
452         Either<ToscaElement, StorageOperationStatus> result = null;
453         StorageOperationStatus status;
454         ToscaElementOperation operation = null;
455         GraphVertex toscaElement = null;
456         GraphVertex modifier = null;
457         try {
458             Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId));
459             if (getVerticesRes.isRight()) {
460                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
461                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value()));
462             }
463             if (result == null) {
464                 toscaElement = getVerticesRes.left().value().get(toscaElementId);
465                 modifier = getVerticesRes.left().value().get(modifierId);
466                 operation = getToscaElementOperation(toscaElement.getLabel());
467                 toscaElement.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
468                 toscaElement.setJsonMetadataField(JsonPresentationFields.USER_ID_LAST_UPDATER, modifier.getUniqueId());
469                 toscaElement.addMetadataProperty(GraphPropertyEnum.STATE, nextState.name());
470
471                 Either<GraphVertex, TitanOperationStatus> updateVertexRes = titanDao.updateVertex(toscaElement);
472                 if (updateVertexRes.isRight()) {
473                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update vertex {} . Status is {}. ", toscaElementId, updateVertexRes.right().value());
474                     result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateVertexRes.right().value()));
475                 }
476             }
477             if (result == null) {
478                 // cancel certification process
479                 status = handleRelationsUponCancelCertification(toscaElement, nextState);
480                 if (status != StorageOperationStatus.OK) {
481                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations upon cancel certification {}. Status is {}. ", toscaElement.getUniqueId(), status);
482                 }
483             }
484             if (result == null) {
485                 // fail certification
486                 status = handleRelationsUponFailCertification(toscaElement, nextState);
487                 if (status != StorageOperationStatus.OK) {
488                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations upon fail certification {}. Status is {}. ", toscaElement.getUniqueId(), status);
489                 }
490             }
491             if (result == null) {
492                 result = operation.getToscaElement(toscaElementId);
493             }
494         } catch (Exception e) {
495             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during cancel or fail certification of tosca element {}. {}. ", toscaElementId, e.getMessage());
496         }
497         return result;
498     }
499
500     public Either<GraphVertex, TitanOperationStatus> findUser(String userId) {
501         return findUserVertex(userId);
502     }
503
504     private Either<Boolean, StorageOperationStatus> markToscaElementsAsDeleted(ToscaElementOperation operation, List<GraphVertex> toscaElements) {
505         Either<Boolean, StorageOperationStatus> result = Either.left(true);
506         for (GraphVertex resourceToDelete : toscaElements) {
507             if (!((String) resourceToDelete.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals(LifecycleStateEnum.CERTIFIED.name())) {
508                 Either<GraphVertex, StorageOperationStatus> deleteElementRes = operation.markComponentToDelete(resourceToDelete);
509                 if (deleteElementRes.isRight()) {
510                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete tosca element {}. Status is {}. ", resourceToDelete.getUniqueId(), deleteElementRes.right().value());
511                     result = Either.right(deleteElementRes.right().value());
512                     break;
513                 }
514             }
515         }
516         return result;
517     }
518
519     private StorageOperationStatus handleRelationsOfNewestCertifiedToscaElement(GraphVertex toscaElement, GraphVertex certifiedToscaElement) {
520         StorageOperationStatus result = null;
521         Edge foundEdge = null;
522         Iterator<Edge> certReqUserEdgeIter = null;
523         // add rfc relation to preserve follower information
524         // get user of certification request
525         certReqUserEdgeIter = toscaElement.getVertex().edges(Direction.IN, GraphEdgeLabels.LAST_STATE.name());
526         if (certReqUserEdgeIter == null || !certReqUserEdgeIter.hasNext()) {
527             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find rfc relation during certification clone. ");
528             result = StorageOperationStatus.NOT_FOUND;
529         }
530         if (result == null) {
531             TitanOperationStatus createVersionEdgeStatus = titanDao.createEdge(toscaElement, certifiedToscaElement, EdgeLabelEnum.VERSION, new HashMap<>());
532             if (createVersionEdgeStatus != TitanOperationStatus.OK) {
533                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create version edge from last element {} to new certified element {}. status=", toscaElement.getUniqueId(), certifiedToscaElement.getUniqueId(),
534                         createVersionEdgeStatus);
535                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(createVersionEdgeStatus);
536             }
537         }
538         if (result == null) {
539                 if (certReqUserEdgeIter!=null) {
540                     while (certReqUserEdgeIter.hasNext()) {
541                         Edge edge = certReqUserEdgeIter.next();
542                         if (((String) titanDao.getProperty(edge, EdgePropertyEnum.STATE)).equals(LifecycleStateEnum.READY_FOR_CERTIFICATION.name())) {
543                             foundEdge = edge;
544                             break;
545                         }
546         
547                     }
548                 }
549             if (foundEdge == null) {
550                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find rfc relation during certification clone. ");
551                 result = StorageOperationStatus.NOT_FOUND;
552             }
553         }
554         if (result == null) {
555             TitanOperationStatus createEdgeRes = titanDao.createEdge(foundEdge.outVertex(), certifiedToscaElement.getVertex(), EdgeLabelEnum.LAST_STATE, foundEdge);
556             if (createEdgeRes != TitanOperationStatus.OK) {
557                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create rfc relation for component {}. status=", certifiedToscaElement.getUniqueId(), createEdgeRes);
558                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(createEdgeRes);
559             }
560         }
561         if (result == null) {
562             result = StorageOperationStatus.OK;
563         }
564         return result;
565     }
566
567     private StorageOperationStatus handleRelationsUponFailCertification(GraphVertex toscaElement, LifecycleStateEnum nextState) {
568         StorageOperationStatus result = null;
569         TitanOperationStatus status = null;
570         Edge originEdge;
571         Vertex user = null;
572         if (nextState == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN) {
573             // fail certification
574             // delete relation CERTIFICATION_IN_PROGRESS
575             Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
576             properties.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
577
578             Either<Edge, TitanOperationStatus> deleteResult = titanDao.deleteBelongingEdgeByCriteria(toscaElement, EdgeLabelEnum.STATE, properties);
579             if (deleteResult.isRight()) {
580                 status = deleteResult.right().value();
581                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete state edge. Status is {}. ", status);
582                 result = StorageOperationStatus.INCONSISTENCY;
583             }
584             if (result == null) {
585                 // delete relation READY_FOR_CERTIFICATION
586                 properties.put(GraphPropertyEnum.STATE, LifecycleStateEnum.READY_FOR_CERTIFICATION);
587                 deleteResult = titanDao.deleteBelongingEdgeByCriteria(toscaElement, EdgeLabelEnum.LAST_STATE, properties);
588                 if (deleteResult.isRight()) {
589                     status = deleteResult.right().value();
590                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_DELETE_LAST_STATE_EDGE_STATUS_IS, status);
591                     result = StorageOperationStatus.INCONSISTENCY;
592                 }
593             }
594             if (result == null) {
595                 // delete relation NOT_CERTIFIED_CHECKIN (in order to change to STATE)
596                 properties.put(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
597                 deleteResult = titanDao.deleteBelongingEdgeByCriteria(toscaElement, EdgeLabelEnum.LAST_STATE, properties);
598                 if (deleteResult.isRight()) {
599                     status = deleteResult.right().value();
600                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_DELETE_LAST_STATE_EDGE_STATUS_IS, status);
601                     result = StorageOperationStatus.INCONSISTENCY;
602                 }
603             }
604             if (result == null) {
605                 // create new STATE relation NOT_CERTIFIED_CHECKIN
606                 originEdge = deleteResult.left().value();
607                 user = originEdge.outVertex();
608                 status = titanDao.createEdge(user, toscaElement.getVertex(), EdgeLabelEnum.STATE, originEdge);
609                 if (status != TitanOperationStatus.OK) {
610                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create state edge. Status is {}. ", status);
611                     result = StorageOperationStatus.INCONSISTENCY;
612                 }
613             }
614             if (result == null) {
615                 // delete relation LAST_MODIFIER (in order to change tester to designer)
616                 deleteResult = titanDao.deleteBelongingEdgeByCriteria(toscaElement, EdgeLabelEnum.LAST_MODIFIER, new HashMap<>());
617                 if (status != TitanOperationStatus.OK) {
618                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create last modifier edge. Status is {}. ", status);
619                     result = StorageOperationStatus.INCONSISTENCY;
620                 }
621             }
622             if (result == null) {
623                 // create new LAST_MODIFIER relation
624                 originEdge = deleteResult.left().value();
625                 status = titanDao.createEdge(user, toscaElement.getVertex(), EdgeLabelEnum.LAST_MODIFIER, originEdge);
626                 if (status != TitanOperationStatus.OK) {
627                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create last modifier edge. Status is {}. ", status);
628                     result = StorageOperationStatus.INCONSISTENCY;
629                 }
630             }
631         }
632         if (result == null) {
633             result = StorageOperationStatus.OK;
634         }
635         return result;
636     }
637
638     private StorageOperationStatus handleRelationsUponCancelCertification(GraphVertex toscaElement, LifecycleStateEnum nextState) {
639         StorageOperationStatus result = null;
640         Edge originEdge;
641         if (nextState == LifecycleStateEnum.READY_FOR_CERTIFICATION) {
642             // delete relation CERTIFICATION_IN_PROGRESS
643             Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
644             properties.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
645             Either<Edge, TitanOperationStatus> deleteResult = titanDao.deleteBelongingEdgeByCriteria(toscaElement, EdgeLabelEnum.STATE, properties);
646
647             if (deleteResult.isRight()) {
648                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete state edge. Status is  {}. ", deleteResult.right().value());
649                 result = StorageOperationStatus.INCONSISTENCY;
650             }
651             if (result == null) {
652                 // delete relation READY_FOR_CERTIFICATION (LAST_STATE)
653                 properties.put(GraphPropertyEnum.STATE, nextState);
654                 deleteResult = titanDao.deleteBelongingEdgeByCriteria(toscaElement, EdgeLabelEnum.LAST_STATE, properties);
655
656                 if (deleteResult.isRight()) {
657                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_DELETE_LAST_STATE_EDGE_STATUS_IS, deleteResult.right().value());
658                     result = StorageOperationStatus.INCONSISTENCY;
659                 }
660             }
661             if (result == null) {
662                 // create relation READY_FOR_CERTIFICATION (STATE)
663                 originEdge = deleteResult.left().value();
664                 TitanOperationStatus status = titanDao.createEdge(originEdge.outVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, originEdge);
665                 if (status != TitanOperationStatus.OK) {
666                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create state edge. Status is {}. ", status);
667                     result = StorageOperationStatus.INCONSISTENCY;
668                 }
669             }
670             if (result == null) {
671                 result = StorageOperationStatus.OK;
672             }
673         }
674         return result;
675     }
676
677     private StorageOperationStatus handleRelationsOfPreviousToscaElementBeforeCertifying(GraphVertex toscaElement, GraphVertex modifier, Integer majorVersion) {
678         StorageOperationStatus result = null;
679         if (majorVersion > 0) {
680             Either<Vertex, StorageOperationStatus> findRes = findLastCertifiedToscaElementVertex(toscaElement);
681             if (findRes.isRight()) {
682                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch last certified tosca element {} . Status is {}. ", toscaElement.getMetadataProperty(GraphPropertyEnum.NAME), findRes.right().value());
683                 result = findRes.right().value();
684             }
685             if (result == null) {
686                 Vertex lastCertifiedVertex = findRes.left().value();
687                 Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
688                 properties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
689                 TitanOperationStatus status = titanDao.updateVertexMetadataPropertiesWithJson(lastCertifiedVertex, properties);
690                 if (status != TitanOperationStatus.OK) {
691                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set highest version  of tosca element {} to [{}]. Status is {}", toscaElement.getUniqueId(), false, status);
692                     result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
693                 }
694                 // remove previous certified version from the catalog
695                 GraphVertex lastCertifiedV = new GraphVertex();
696                 lastCertifiedV.setVertex((TitanVertex) lastCertifiedVertex);
697                 lastCertifiedV.setUniqueId((String) titanDao.getProperty((TitanVertex) lastCertifiedVertex, GraphPropertyEnum.UNIQUE_ID.getProperty()));
698                 StorageOperationStatus res = updateEdgeToCatalogRoot(null, lastCertifiedV);
699                 if (res != StorageOperationStatus.OK) {
700                     return res;
701                 }
702             }
703         }
704         if (result == null) {
705             result = StorageOperationStatus.OK;
706         }
707         return result;
708     }
709
710     private StorageOperationStatus handleRelationsUponRequestForCertification(GraphVertex toscaElement, GraphVertex modifier, GraphVertex owner) {
711         TitanOperationStatus status;
712         StorageOperationStatus result = null;
713
714         if (((String) toscaElement.getMetadataProperty(GraphPropertyEnum.STATE)).equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) {
715             // remove CHECKOUT relation
716             Either<Edge, TitanOperationStatus> deleteRes = titanDao.deleteEdge(owner, toscaElement, EdgeLabelEnum.STATE);
717             if (deleteRes.isRight()) {
718                 status = deleteRes.right().value();
719                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete edge. Status is {}. ", status);
720                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
721             }
722             if (result == null) {
723                 // create CHECKIN relation
724                 Map<EdgePropertyEnum, Object> properties = new EnumMap<>(EdgePropertyEnum.class);
725                 properties.put(EdgePropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKIN);
726                 status = titanDao.createEdge(modifier.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.LAST_STATE, properties);
727                 if (status != TitanOperationStatus.OK) {
728                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge. Status is {}", status);
729                     result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
730                 }
731             }
732         } else {
733             status = titanDao.replaceEdgeLabel(owner.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE);
734             if (status != TitanOperationStatus.OK) {
735                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
736             }
737         }
738         if (result == null) {
739             // create RFC relation
740             Map<EdgePropertyEnum, Object> properties = new EnumMap<>(EdgePropertyEnum.class);
741             properties.put(EdgePropertyEnum.STATE, LifecycleStateEnum.READY_FOR_CERTIFICATION);
742             status = titanDao.createEdge(modifier.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, properties);
743             if (status != TitanOperationStatus.OK) {
744                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge. Status is {}", status);
745                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
746             }
747         }
748         if (result == null) {
749             result = StorageOperationStatus.OK;
750         }
751         return result;
752     }
753
754     private StorageOperationStatus handleRelationsUponCertification(GraphVertex toscaElement, GraphVertex modifier, GraphVertex owner) {
755
756         StorageOperationStatus result = null;
757         TitanOperationStatus status = titanDao.replaceEdgeLabel(owner.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE);
758         if (status != TitanOperationStatus.OK) {
759             result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
760         }
761         if (result == null) {
762             Map<EdgePropertyEnum, Object> properties = new EnumMap<>(EdgePropertyEnum.class);
763             properties.put(EdgePropertyEnum.STATE, LifecycleStateEnum.CERTIFICATION_IN_PROGRESS);
764             status = titanDao.createEdge(modifier, toscaElement, EdgeLabelEnum.STATE, properties);
765             if (status != TitanOperationStatus.OK) {
766                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "failed to create edge. Status is {}", status);
767                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
768             }
769         }
770         if (result == null) {
771             Either<GraphVertex, StorageOperationStatus> updateRelationsRes = updateLastModifierEdge(toscaElement, owner, modifier);
772             if (updateRelationsRes.isRight()) {
773                 result = updateRelationsRes.right().value();
774             }
775         }
776         if (result == null) {
777             result = StorageOperationStatus.OK;
778         }
779         return result;
780     }
781
782     private Either<Vertex, StorageOperationStatus> findLastCertifiedToscaElementVertex(GraphVertex toscaElement) {
783         return findLastCertifiedToscaElementVertexRecursively(toscaElement.getVertex());
784     }
785
786     private Either<Vertex, StorageOperationStatus> findLastCertifiedToscaElementVertexRecursively(Vertex vertex) {
787         if (isCertifiedVersion((String) vertex.property(GraphPropertyEnum.VERSION.getProperty()).value())) {
788             return Either.left(vertex);
789         }
790         Iterator<Edge> edgeIter = vertex.edges(Direction.IN, EdgeLabelEnum.VERSION.name());
791         if (!edgeIter.hasNext()) {
792             return Either.right(StorageOperationStatus.NOT_FOUND);
793         }
794         return findLastCertifiedToscaElementVertexRecursively(edgeIter.next().outVertex());
795     }
796
797     private boolean isCertifiedVersion(String version) {
798         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
799         if (Integer.parseInt(versionParts[0]) > 0 && Integer.parseInt(versionParts[1]) == 0) {
800             return true;
801         }
802         return false;
803     }
804
805     private StorageOperationStatus updateOldToscaElementBeforeUndoCheckout(Vertex previousVersionToscaElement) {
806
807         StorageOperationStatus result = StorageOperationStatus.OK;
808         String previousVersion = (String) previousVersionToscaElement.property(GraphPropertyEnum.VERSION.getProperty()).value();
809         if (!previousVersion.endsWith(".0")) {
810             try {
811                 CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update vertex of previous version of tosca element", previousVersionToscaElement.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()));
812
813                 Map<String, Object> propertiesToUpdate = new HashMap<>();
814                 propertiesToUpdate.put(GraphPropertyEnum.IS_HIGHEST_VERSION.getProperty(), true);
815                 Map<String, Object> jsonMetadataMap = JsonParserUtils.toMap((String) previousVersionToscaElement.property(GraphPropertyEnum.METADATA.getProperty()).value());
816                 jsonMetadataMap.put(GraphPropertyEnum.IS_HIGHEST_VERSION.getProperty(), true);
817                 propertiesToUpdate.put(GraphPropertyEnum.METADATA.getProperty(), JsonParserUtils.toJson(jsonMetadataMap));
818
819                 titanDao.setVertexProperties(previousVersionToscaElement, propertiesToUpdate);
820
821                 Iterator<Edge> edgesIter = previousVersionToscaElement.edges(Direction.IN, EdgeLabelEnum.LAST_STATE.name());
822                 if (!edgesIter.hasNext()) {
823                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch last modifier vertex for tosca element {}. ", previousVersionToscaElement.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()));
824                     result = StorageOperationStatus.NOT_FOUND;
825                 } else {
826                     Edge lastStateEdge = edgesIter.next();
827                     Vertex lastModifier = lastStateEdge.outVertex();
828                     TitanOperationStatus replaceRes = titanDao.replaceEdgeLabel(lastModifier, previousVersionToscaElement, lastStateEdge, EdgeLabelEnum.LAST_STATE, EdgeLabelEnum.STATE);
829                     if (replaceRes != TitanOperationStatus.OK) {
830                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to replace label from {} to {}. status = {}", EdgeLabelEnum.LAST_STATE, EdgeLabelEnum.STATE, replaceRes);
831                         result = StorageOperationStatus.INCONSISTENCY;
832                         if (replaceRes != TitanOperationStatus.INVALID_ID) {
833                             result = DaoStatusConverter.convertTitanStatusToStorageStatus(replaceRes);
834                         }
835                     }
836
837                 }
838             } catch (Exception e) {
839                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during update previous tosca element {} before undo checkout. {} ", e.getMessage());
840             }
841         }
842         return result;
843     }
844
845     private StorageOperationStatus updatePreviousVersion(GraphVertex toscaElementVertex, GraphVertex ownerVertex) {
846         StorageOperationStatus result = null;
847         String ownerId = (String) ownerVertex.getMetadataProperty(GraphPropertyEnum.USERID);
848         String toscaElementId = toscaElementVertex.getUniqueId();
849         if (!toscaElementVertex.getMetadataProperty(GraphPropertyEnum.STATE).equals(LifecycleStateEnum.CERTIFIED.name())) {
850             toscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
851             Either<GraphVertex, TitanOperationStatus> updateVertexRes = titanDao.updateVertex(toscaElementVertex);
852             if (updateVertexRes.isRight()) {
853                 TitanOperationStatus titatStatus = updateVertexRes.right().value();
854                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update tosca element vertex {}. Status is  {}", toscaElementVertex.getUniqueId(), titatStatus);
855                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(titatStatus);
856             }
857             Either<Edge, TitanOperationStatus> deleteEdgeRes = null;
858             if (result == null) {
859                 CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to replace edge with label {} to label {} from {} to {}. ", EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE, ownerId, toscaElementId);
860
861                 deleteEdgeRes = titanDao.deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.STATE);
862                 if (deleteEdgeRes.isRight()) {
863                     TitanOperationStatus titanStatus = deleteEdgeRes.right().value();
864                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete edge with label {} from {} to {}. Status is {} ", EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE, ownerId, toscaElementId, titanStatus);
865                     if (!titanStatus.equals(TitanOperationStatus.INVALID_ID)) {
866                         result = DaoStatusConverter.convertTitanStatusToStorageStatus(titanStatus);
867                     } else {
868                         result = StorageOperationStatus.INCONSISTENCY;
869                     }
870                 }
871             }
872             if (result == null) {
873                 TitanOperationStatus createEdgeRes = titanDao.createEdge(ownerVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.LAST_STATE, deleteEdgeRes.left().value());
874                 if (createEdgeRes != TitanOperationStatus.OK) {
875                     result = DaoStatusConverter.convertTitanStatusToStorageStatus(createEdgeRes);
876                 }
877             }
878         }
879         if (result == null) {
880             result = StorageOperationStatus.OK;
881         }
882         return result;
883     }
884
885     private Either<ToscaElement, StorageOperationStatus> cloneToscaElementForCheckout(GraphVertex toscaElementVertex, GraphVertex modifierVertex) {
886
887         Either<ToscaElement, StorageOperationStatus> result = null;
888         Either<GraphVertex, StorageOperationStatus> cloneResult = null;
889         ToscaElementOperation operation = getToscaElementOperation(toscaElementVertex.getLabel());
890         // check if component with the next version doesn't exist.
891         Iterator<Edge> nextVersionComponentIter = toscaElementVertex.getVertex().edges(Direction.OUT, EdgeLabelEnum.VERSION.name());
892         if (nextVersionComponentIter != null && nextVersionComponentIter.hasNext()) {
893             Vertex nextVersionVertex = nextVersionComponentIter.next().inVertex();
894             String fetchedVersion = (String) nextVersionVertex.property(GraphPropertyEnum.VERSION.getProperty()).value();
895             String fetchedName = (String) nextVersionVertex.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()).value();
896             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to checkout component {} with version {}. The component with name {} and version {} was fetched from graph as existing following version. ",
897                     toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME).toString(), toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION).toString(), fetchedName, fetchedVersion);
898             result = Either.right(StorageOperationStatus.ENTITY_ALREADY_EXISTS);
899         }
900         if (result == null) {
901             toscaElementVertex.getOrSetDefaultInstantiationTypeForToscaElementJson();
902             cloneResult = operation.cloneToscaElement(toscaElementVertex, cloneGraphVertexForCheckout(toscaElementVertex, modifierVertex), modifierVertex);
903             if (cloneResult.isRight()) {
904                 result = Either.right(cloneResult.right().value());
905             }
906         }
907         GraphVertex clonedVertex = null;
908         if (result == null) {
909             clonedVertex = cloneResult.left().value();
910             TitanOperationStatus status = titanDao.createEdge(toscaElementVertex.getVertex(), cloneResult.left().value().getVertex(), EdgeLabelEnum.VERSION, new HashMap<>());
911             if (status != TitanOperationStatus.OK) {
912                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.VERSION,
913                         toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), cloneResult.left().value().getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), status);
914                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
915             }
916         }
917         if (result == null) {
918             Boolean isHighest = (Boolean) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION);
919             GraphVertex prevVersionInCatalog = (isHighest != null && isHighest) ? null : toscaElementVertex;
920             StorageOperationStatus updateCatalogRes = updateEdgeToCatalogRoot(clonedVertex, prevVersionInCatalog);
921             if (updateCatalogRes != StorageOperationStatus.OK) {
922                 return Either.right(updateCatalogRes);
923             }
924             result = operation.getToscaElement(cloneResult.left().value().getUniqueId());
925             if (result.isRight()) {
926                 return result;
927             }
928             ToscaElement toscaElement = result.left().value();
929             if (toscaElement.getToscaType() == ToscaElementTypeEnum.TOPOLOGY_TEMPLATE) {
930                 result = handleFixTopologyTemplate(toscaElementVertex, result, operation, clonedVertex, toscaElement);
931             }
932         }
933
934         return result;
935     }
936
937     private Either<ToscaElement, StorageOperationStatus> handleFixTopologyTemplate(GraphVertex toscaElementVertex, Either<ToscaElement, StorageOperationStatus> result, ToscaElementOperation operation, GraphVertex clonedVertex,
938             ToscaElement toscaElement) {
939         TopologyTemplate topologyTemplate = (TopologyTemplate) toscaElement;
940         Map<String, MapPropertiesDataDefinition> instInputs = topologyTemplate.getInstInputs();
941         Map<String, MapGroupsDataDefinition> instGroups = topologyTemplate.getInstGroups();
942         Map<String, MapArtifactDataDefinition> instArtifactsMap = topologyTemplate.getInstanceArtifacts();
943         Map<String, ToscaElement> origCompMap = new HashMap<>();
944         if (instInputs == null) {
945             instInputs = new HashMap<>();
946         }
947         if (instGroups == null) {
948             instGroups = new HashMap<>();
949         }
950         if (instArtifactsMap == null) {
951             instArtifactsMap = new HashMap<>();
952         }
953         Map<String, ComponentInstanceDataDefinition> instancesMap = topologyTemplate.getComponentInstances();
954         boolean isAddInstGroup = instGroups == null || instGroups.isEmpty();
955         boolean needUpdateComposition = false;
956
957         if (instancesMap != null && !instancesMap.isEmpty()) {
958             for (ComponentInstanceDataDefinition vfInst : instancesMap.values()) {
959                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "vfInst name is {} . OriginType {}. ", vfInst.getName(), vfInst.getOriginType());
960                 if (vfInst.getOriginType().name().equals(OriginTypeEnum.VF.name())) {
961                     collectInstanceInputAndGroups(instInputs, instGroups, instArtifactsMap, origCompMap, isAddInstGroup, vfInst, clonedVertex);
962                 }
963                 needUpdateComposition = needUpdateComposition || fixToscaComponentName(vfInst, origCompMap);
964                 if (needUpdateComposition) {
965                     instancesMap.put(vfInst.getUniqueId(), vfInst);
966                 }
967             }
968             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add to graph instInputs {}  instGroups {} needUpdateComposition {}", instInputs, instGroups, needUpdateComposition);
969             if (!instInputs.isEmpty()) {
970                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add inst inputs {} ", instInputs == null ? 0 : instInputs.size());
971                 GraphVertex toscaDataVertex = null;
972                 Either<GraphVertex, TitanOperationStatus> instInpVertexEither = titanDao.getChildVertex(toscaElementVertex, EdgeLabelEnum.INST_INPUTS, JsonParseFlagEnum.ParseJson);
973                 if (instInpVertexEither.isLeft()) {
974                     toscaDataVertex = instInpVertexEither.left().value();
975                 }
976
977                 StorageOperationStatus status = handleToscaData(clonedVertex, VertexTypeEnum.INST_INPUTS, EdgeLabelEnum.INST_INPUTS, toscaDataVertex, instInputs);
978                 if (status != StorageOperationStatus.OK) {
979                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instance inputs . Status is {}. ", status);
980                     result = Either.right(status);
981                     return result;
982                 }
983
984             }
985             if (!instGroups.isEmpty()) {
986                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add inst groups {} ", instGroups == null ? 0 : instGroups.size());
987                 GraphVertex toscaDataVertex = null;
988                 Either<GraphVertex, TitanOperationStatus> instGrVertexEither = titanDao.getChildVertex(toscaElementVertex, EdgeLabelEnum.INST_GROUPS, JsonParseFlagEnum.ParseJson);
989                 if (instGrVertexEither.isLeft()) {
990                     toscaDataVertex = instGrVertexEither.left().value();
991                 }
992
993                 StorageOperationStatus status = handleToscaData(clonedVertex, VertexTypeEnum.INST_GROUPS, EdgeLabelEnum.INST_GROUPS, toscaDataVertex, instGroups);
994                 if (status != StorageOperationStatus.OK) {
995                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instance group . Status is {}. ", status);
996                     result = Either.right(status);
997                     return result;
998                 }
999
1000             }
1001             if (needUpdateComposition) {
1002                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before update Instances ");
1003                 Map<String, CompositionDataDefinition> jsonComposition = (Map<String, CompositionDataDefinition>) clonedVertex.getJson();
1004                 CompositionDataDefinition compositionDataDefinition = jsonComposition.get(JsonConstantKeysEnum.COMPOSITION.getValue());
1005                 compositionDataDefinition.setComponentInstances(instancesMap);
1006                 Either<GraphVertex, TitanOperationStatus> updateElement = titanDao.updateVertex(clonedVertex);
1007                 if (updateElement.isRight()) {
1008                     TitanOperationStatus status = updateElement.right().value();
1009                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instances on metadata vertex . Status is {}. ", status);
1010                     result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
1011                     return result;
1012                 }
1013             }
1014
1015             result = operation.getToscaElement(clonedVertex.getUniqueId());
1016
1017         } else {
1018             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "RI map empty on component {}", toscaElement.getUniqueId());
1019         }
1020         return result;
1021     }
1022
1023     // TODO remove after jsonModelMigration
1024     public boolean resolveToscaComponentName(ComponentInstanceDataDefinition vfInst, Map<String, ToscaElement> origCompMap) {
1025         return fixToscaComponentName(vfInst, origCompMap);
1026     }
1027
1028     private boolean fixToscaComponentName(ComponentInstanceDataDefinition vfInst, Map<String, ToscaElement> origCompMap) {
1029         if (vfInst.getToscaComponentName() == null || vfInst.getToscaComponentName().isEmpty()) {
1030             String ciUid = vfInst.getUniqueId();
1031             String origCompUid = vfInst.getComponentUid();
1032             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "fixToscaComponentName:: Ri id {} . origin component id is {}. type is{} ", ciUid, origCompUid, vfInst.getOriginType());
1033             ToscaElement origComp = null;
1034             if (!origCompMap.containsKey(origCompUid)) {
1035                 Either<ToscaElement, StorageOperationStatus> origCompEither;
1036                 if (vfInst.getOriginType() == null || vfInst.getOriginType().name().equals(OriginTypeEnum.VF.name())) {
1037                     origCompEither = topologyTemplateOperation.getToscaElement(origCompUid);
1038                 } else {
1039                     origCompEither = nodeTypeOperation.getToscaElement(origCompUid);
1040                 }
1041                 if (origCompEither.isRight()) {
1042                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find orig component {} . Status is {}. ", origCompEither.right().value());
1043                     return false;
1044                 }
1045                 origComp = origCompEither.left().value();
1046                 origCompMap.put(origCompUid, origComp);
1047             } else {
1048                 origComp = origCompMap.get(origCompUid);
1049             }
1050             String toscaName = (String) origComp.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME);
1051             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Origin component id is {}. toscaName {}", origCompUid, toscaName);
1052             vfInst.setToscaComponentName(toscaName);
1053             return true;
1054         }
1055         return false;
1056     }
1057
1058     private void collectInstanceInputAndGroups(Map<String, MapPropertiesDataDefinition> instInputs, Map<String, MapGroupsDataDefinition> instGroups, Map<String, MapArtifactDataDefinition> instArtifactsMap, Map<String, ToscaElement> origCompMap,
1059             boolean isAddInstGroup, ComponentInstanceDataDefinition vfInst, GraphVertex clonedVertex) {
1060         String ciUid = vfInst.getUniqueId();
1061         String origCompUid = vfInst.getComponentUid();
1062         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "collectInstanceInputAndGroups:: Ri id {} . origin component id is {}. ", ciUid, origCompUid);
1063         TopologyTemplate origComp = null;
1064         if (!origCompMap.containsKey(origCompUid)) {
1065             Either<ToscaElement, StorageOperationStatus> origCompEither = topologyTemplateOperation.getToscaElement(origCompUid);
1066             if (origCompEither.isRight()) {
1067                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find orig component {} . Status is {}. ", origCompEither.right().value());
1068                 return;
1069             }
1070             origComp = (TopologyTemplate) origCompEither.left().value();
1071             origCompMap.put(origCompUid, origComp);
1072         } else {
1073             origComp = (TopologyTemplate) origCompMap.get(origCompUid);
1074         }
1075         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Orig component {}. ", origComp.getUniqueId());
1076
1077         Map<String, PropertyDataDefinition> origInputs = origComp.getInputs();
1078         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Orig component inputs size {}. ", origInputs == null ? 0 : origInputs.size());
1079         if (origInputs != null) {
1080             if (!instInputs.containsKey(ciUid)) {
1081                 MapPropertiesDataDefinition instProperties = new MapPropertiesDataDefinition(origInputs);
1082                 instInputs.put(ciUid, instProperties);
1083             } else {
1084
1085                 MapPropertiesDataDefinition instInputMap = instInputs.get(ciUid);
1086                 Map<String, PropertyDataDefinition> instProp = instInputMap.getMapToscaDataDefinition();
1087                 origInputs.forEach((propName, propMap) -> {
1088                     if (!instProp.containsKey(propName)) {
1089                         instProp.put(propName, propMap);
1090                     }
1091                 });
1092             }
1093             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "ComponentInstanseInputs {}. ", instInputs.get(ciUid));
1094         }
1095
1096         if (isAddInstGroup) {
1097             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before create group instance. ");
1098             List<GroupDataDefinition> filteredGroups = null;
1099
1100             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups before filter. Size is {} ", filteredGroups == null ? 0 : filteredGroups.size());
1101             if (origComp.getGroups() != null && !origComp.getGroups().isEmpty()) {
1102                 filteredGroups = origComp.getGroups().values().stream().filter(g -> g.getType().equals(VF_MODULE)).collect(Collectors.toList());
1103                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups . Size is {} ", filteredGroups == null ? 0 : filteredGroups.size());
1104             }
1105             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups after filter. Size is {} ", filteredGroups == null ? 0 : filteredGroups.size());
1106             if (CollectionUtils.isNotEmpty(filteredGroups)) {
1107                 MapArtifactDataDefinition instArifacts = null;
1108                 if (!instArtifactsMap.containsKey(ciUid)) {
1109
1110                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "istance artifacts not found ");
1111
1112                     Map<String, ArtifactDataDefinition> deploymentArtifacts = origComp.getDeploymentArtifacts();
1113
1114                     instArifacts = new MapArtifactDataDefinition(deploymentArtifacts);
1115                     addToscaDataDeepElementsBlockToToscaElement(clonedVertex, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS, VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS, instArifacts, ciUid);
1116
1117                     instArtifactsMap.put(ciUid, instArifacts);
1118
1119                 } else {
1120                     instArifacts = instArtifactsMap.get(ciUid);
1121                 }
1122
1123                 if (instArifacts != null) {
1124                     Map<String, ArtifactDataDefinition> instDeplArtifMap = instArifacts.getMapToscaDataDefinition();
1125
1126                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check group dep artifacts. Size is {} ", instDeplArtifMap == null ? 0 : instDeplArtifMap.values().size());
1127                     Map<String, GroupInstanceDataDefinition> groupInstanceToCreate = new HashMap<>();
1128                     for (GroupDataDefinition group : filteredGroups) {
1129                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "create new groupInstance  {} ", group.getName());
1130                         GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition(group, vfInst, instDeplArtifMap);
1131                         List<String> artifactsUid = new ArrayList<>();
1132                         List<String> artifactsId = new ArrayList<>();
1133                         if (instDeplArtifMap!=null) {
1134                                 for (ArtifactDataDefinition artifact : instDeplArtifMap.values()) {
1135                                     Optional<String> op = group.getArtifacts().stream().filter(p -> p.equals(artifact.getGeneratedFromId())).findAny();
1136                                     if (op.isPresent()) {
1137                                         artifactsUid.add(artifact.getArtifactUUID());
1138                                         artifactsId.add(artifact.getUniqueId());
1139         
1140                                     }
1141                                 }
1142                         }
1143                         groupInstance.setGroupInstanceArtifacts(artifactsId);
1144                         groupInstance.setGroupInstanceArtifactsUuid(artifactsUid);
1145                         groupInstanceToCreate.put(groupInstance.getName(), groupInstance);
1146                     }
1147                     if (MapUtils.isNotEmpty(groupInstanceToCreate)) {
1148                         instGroups.put(vfInst.getUniqueId(), new MapGroupsDataDefinition(groupInstanceToCreate));
1149
1150                     }
1151                 }
1152             }
1153         }
1154     }
1155
1156     private GraphVertex cloneGraphVertexForCheckout(GraphVertex toscaElementVertex, GraphVertex modifierVertex) {
1157         GraphVertex nextVersionToscaElementVertex = new GraphVertex();
1158         String uniqueId = UniqueIdBuilder.buildComponentUniqueId();
1159         Map<GraphPropertyEnum, Object> metadataProperties = new HashMap<>(toscaElementVertex.getMetadataProperties());
1160         nextVersionToscaElementVertex.setMetadataProperties(metadataProperties);
1161         nextVersionToscaElementVertex.setUniqueId(uniqueId);
1162         nextVersionToscaElementVertex.setLabel(toscaElementVertex.getLabel());
1163         nextVersionToscaElementVertex.setType(toscaElementVertex.getType());
1164
1165         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uniqueId);
1166         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, nextVersionToscaElementVertex.getType().name());
1167         String nextVersion = getNextVersion((String) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION));
1168         if (isFirstCheckoutAfterCertification(nextVersion)) {
1169             nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UUID, IdBuilderUtils.generateUUID());
1170         }
1171         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.VERSION, nextVersion);
1172         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name());
1173         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
1174
1175         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE && toscaElementVertex.getMetadataProperty(GraphPropertyEnum.STATE).equals(LifecycleStateEnum.CERTIFIED.name())) {
1176             nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED.name());
1177         }
1178         if (!MapUtils.isEmpty(toscaElementVertex.getMetadataJson())) {
1179             nextVersionToscaElementVertex.setMetadataJson(new HashMap<>(toscaElementVertex.getMetadataJson()));
1180             nextVersionToscaElementVertex.updateMetadataJsonWithCurrentMetadataProperties();
1181         }
1182         long currTime = System.currentTimeMillis();
1183         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CREATION_DATE, currTime);
1184         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, currTime);
1185         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_CREATOR, modifierVertex.getUniqueId());
1186         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_LAST_UPDATER, modifierVertex.getUniqueId());
1187         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE) {
1188             nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CONFORMANCE_LEVEL, ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel());
1189         }
1190
1191         if (!MapUtils.isEmpty(toscaElementVertex.getJson())) {
1192             nextVersionToscaElementVertex.setJson(new HashMap<String, ToscaDataDefinition>(toscaElementVertex.getJson()));
1193         }
1194         return nextVersionToscaElementVertex;
1195     }
1196
1197     private Either<GraphVertex, StorageOperationStatus> cloneToscaElementForCertify(GraphVertex toscaElementVertex, GraphVertex modifierVertex, Integer majorVersion) {
1198         Either<GraphVertex, StorageOperationStatus> result;
1199         Either<List<GraphVertex>, StorageOperationStatus> deleteResult = null;
1200         GraphVertex clonedToscaElement = null;
1201         result = getToscaElementOperation(toscaElementVertex.getLabel()).cloneToscaElement(toscaElementVertex, cloneGraphVertexForCertify(toscaElementVertex, modifierVertex, majorVersion), modifierVertex);
1202         if (result.isRight()) {
1203             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to clone tosca element {} for certification. Sattus is {}. ", toscaElementVertex.getUniqueId(), result.right().value());
1204         } else {
1205             clonedToscaElement = result.left().value();
1206             StorageOperationStatus updateEdgeToCatalog = updateEdgeToCatalogRoot(clonedToscaElement, toscaElementVertex);
1207             if (updateEdgeToCatalog != StorageOperationStatus.OK) {
1208                 return Either.right(updateEdgeToCatalog);
1209             }
1210             deleteResult = deleteAllPreviousNotCertifiedVersions(toscaElementVertex);
1211             if (deleteResult.isRight()) {
1212                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete all previous npt certified versions of tosca element {}. Status is {}. ", toscaElementVertex.getUniqueId(), deleteResult.right().value());
1213                 result = Either.right(deleteResult.right().value());
1214             }
1215         }
1216         if (result.isLeft()) {
1217             result = handlePreviousVersionRelation(clonedToscaElement, deleteResult.left().value(), majorVersion);
1218         }
1219         return result;
1220     }
1221
1222     private Either<GraphVertex, StorageOperationStatus> handlePreviousVersionRelation(GraphVertex clonedToscaElement, List<GraphVertex> deletedVersions, Integer majorVersion) {
1223         Either<GraphVertex, StorageOperationStatus> result = null;
1224         Vertex previousCertifiedToscaElement = null;
1225         if (majorVersion > 0) {
1226             List<GraphVertex> firstMinorVersionVertex = deletedVersions.stream().filter(gv -> getMinorVersion((String) gv.getMetadataProperty(GraphPropertyEnum.VERSION)) == 1).collect(Collectors.toList());
1227
1228             if (CollectionUtils.isEmpty(firstMinorVersionVertex)) {
1229                 result = Either.right(StorageOperationStatus.NOT_FOUND);
1230             } else {
1231                 previousCertifiedToscaElement = getPreviousCertifiedToscaElement(firstMinorVersionVertex.get(0));
1232                 if (previousCertifiedToscaElement == null) {
1233                     result = Either.right(StorageOperationStatus.NOT_FOUND);
1234                 }
1235             }
1236             if (result == null) {
1237                 TitanOperationStatus status = titanDao.createEdge(previousCertifiedToscaElement, clonedToscaElement.getVertex(), EdgeLabelEnum.VERSION, new HashMap<>());
1238                 if (status != TitanOperationStatus.OK) {
1239                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.VERSION,
1240                             previousCertifiedToscaElement.property(GraphPropertyEnum.UNIQUE_ID.getProperty()), clonedToscaElement.getUniqueId(), status);
1241                     result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
1242                 }
1243             }
1244
1245         }
1246         if (result == null) {
1247             result = Either.left(clonedToscaElement);
1248         }
1249         return result;
1250     }
1251
1252     private Vertex getPreviousCertifiedToscaElement(GraphVertex graphVertex) {
1253
1254         Iterator<Edge> edges = graphVertex.getVertex().edges(Direction.IN, EdgeLabelEnum.VERSION.name());
1255         if (edges.hasNext()) {
1256             return edges.next().outVertex();
1257         }
1258         return null;
1259     }
1260
1261     private Either<List<GraphVertex>, StorageOperationStatus> deleteAllPreviousNotCertifiedVersions(GraphVertex toscaElementVertex) {
1262         Either<List<GraphVertex>, StorageOperationStatus> result = null;
1263
1264         ToscaElementOperation operation = getToscaElementOperation(toscaElementVertex.getLabel());
1265         List<GraphVertex> previosVersions = null;
1266         Object uuid = toscaElementVertex.getMetadataProperty(GraphPropertyEnum.UUID);
1267         Object componentName = toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NAME);
1268         try {
1269             Map<GraphPropertyEnum, Object> properties = new HashMap<>();
1270             properties.put(GraphPropertyEnum.UUID, uuid);
1271             properties.put(GraphPropertyEnum.NAME, componentName);
1272             Either<List<GraphVertex>, TitanOperationStatus> getToscaElementsRes = titanDao.getByCriteria(toscaElementVertex.getLabel(), properties, JsonParseFlagEnum.ParseMetadata);
1273             if (getToscaElementsRes.isRight()) {
1274                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getToscaElementsRes.right().value()));
1275             }
1276             if (result == null) {
1277                 previosVersions = getToscaElementsRes.left().value();
1278                 Either<Boolean, StorageOperationStatus> deleteResult = markToscaElementsAsDeleted(operation, getToscaElementsRes.left().value());
1279                 if (deleteResult.isRight()) {
1280                     result = Either.right(deleteResult.right().value());
1281                 }
1282             }
1283             if (result == null) {
1284                 result = Either.left(previosVersions);
1285             }
1286         } catch (Exception e) {
1287             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during deleteng all tosca elements by UUID {} and name {}. {} ", uuid, componentName, e.getMessage());
1288         }
1289         return result;
1290     }
1291
1292     private GraphVertex cloneGraphVertexForCertify(GraphVertex toscaElementVertex, GraphVertex modifierVertex, Integer majorVersion) {
1293
1294         GraphVertex nextVersionToscaElementVertex = new GraphVertex();
1295         String uniqueId = IdBuilderUtils.generateUniqueId();
1296         Map<GraphPropertyEnum, Object> metadataProperties = new HashMap<>(toscaElementVertex.getMetadataProperties());
1297         nextVersionToscaElementVertex.setMetadataProperties(metadataProperties);
1298         nextVersionToscaElementVertex.setUniqueId(uniqueId);
1299         nextVersionToscaElementVertex.setLabel(toscaElementVertex.getLabel());
1300         nextVersionToscaElementVertex.setType(toscaElementVertex.getType());
1301
1302         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uniqueId);
1303         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, nextVersionToscaElementVertex.getType().name());
1304         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.VERSION, (majorVersion + 1) + VERSION_DELIMITER + "0");
1305         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
1306         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
1307         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CREATION_DATE, System.currentTimeMillis());
1308         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, null);
1309         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_CREATOR, modifierVertex.getUniqueId());
1310         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_LAST_UPDATER, modifierVertex.getUniqueId());
1311
1312         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE && toscaElementVertex.getMetadataProperty(GraphPropertyEnum.STATE).equals(LifecycleStateEnum.CERTIFIED)) {
1313             nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED.name());
1314         }
1315         if (!MapUtils.isEmpty(toscaElementVertex.getMetadataJson())) {
1316             nextVersionToscaElementVertex.setMetadataJson(new HashMap<>(toscaElementVertex.getMetadataJson()));
1317             nextVersionToscaElementVertex.updateMetadataJsonWithCurrentMetadataProperties();
1318         }
1319         if (!MapUtils.isEmpty(toscaElementVertex.getJson())) {
1320             nextVersionToscaElementVertex.setJson(new HashMap<String, ToscaDataDefinition>(toscaElementVertex.getJson()));
1321         }
1322         return nextVersionToscaElementVertex;
1323     }
1324
1325     private ComponentParametersView buildComponentParametersViewAfterCheckin() {
1326         ComponentParametersView componentParametersView = new ComponentParametersView();
1327         componentParametersView.disableAll();
1328         componentParametersView.setIgnoreUsers(false);
1329         return componentParametersView;
1330     }
1331
1332     private Either<GraphVertex, StorageOperationStatus> checkinToscaELement(LifecycleStateEnum currState, GraphVertex toscaElementVertex, GraphVertex ownerVertex, GraphVertex modifierVertex, LifecycleStateEnum nextState) {
1333         Either<GraphVertex, StorageOperationStatus> updateRelationsRes;
1334         Either<GraphVertex, StorageOperationStatus> result = changeStateToCheckedIn(currState, toscaElementVertex, ownerVertex, modifierVertex);
1335         if (result.isLeft()) {
1336             toscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, nextState.name());
1337             toscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
1338             result = updateToscaElementVertexMetadataPropertiesAndJson(toscaElementVertex);
1339         }
1340         if (result.isLeft()) {
1341             updateRelationsRes = updateLastModifierEdge(toscaElementVertex, ownerVertex, modifierVertex);
1342             if (updateRelationsRes.isRight()) {
1343                 result = Either.right(updateRelationsRes.right().value());
1344             }
1345         }
1346         return result;
1347     }
1348
1349     private Either<GraphVertex, StorageOperationStatus> updateToscaElementVertexMetadataPropertiesAndJson(GraphVertex toscaElementVertex) {
1350
1351         Either<GraphVertex, StorageOperationStatus> result;
1352
1353         Either<GraphVertex, TitanOperationStatus> updateVertexRes = titanDao.updateVertex(toscaElementVertex);
1354         if (updateVertexRes.isRight()) {
1355             TitanOperationStatus titatStatus = updateVertexRes.right().value();
1356             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update state of tosca element vertex {} metadata. Status is  {}", toscaElementVertex.getUniqueId(), titatStatus);
1357             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titatStatus));
1358         } else {
1359             result = Either.left(updateVertexRes.left().value());
1360         }
1361         return result;
1362     }
1363
1364     private Either<GraphVertex, StorageOperationStatus> changeStateToCheckedIn(LifecycleStateEnum currState, GraphVertex toscaElementVertex, GraphVertex ownerVertex, GraphVertex modifierVertex) {
1365         Either<GraphVertex, StorageOperationStatus> result = null;
1366         LifecycleStateEnum nextState = LifecycleStateEnum.NOT_CERTIFIED_CHECKIN;
1367         String faileToUpdateStateMsg = "Failed to update state of tosca element {}. Status is  {}";
1368
1369         if (currState == LifecycleStateEnum.READY_FOR_CERTIFICATION) {
1370             // In case of cancel "ready for certification" remove last state edge with "STATE" property equals to "NOT_CERTIFIED_CHECKIN"
1371             Map<GraphPropertyEnum, Object> vertexProperties = new HashMap<>();
1372             vertexProperties.put(GraphPropertyEnum.STATE, nextState);
1373             Either<Edge, TitanOperationStatus> deleteResult = titanDao.deleteBelongingEdgeByCriteria(toscaElementVertex, EdgeLabelEnum.LAST_STATE, vertexProperties);
1374             if (deleteResult.isRight()) {
1375                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, faileToUpdateStateMsg, toscaElementVertex.getUniqueId(), deleteResult.right().value());
1376                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "failed to update last state relation");
1377                 result = Either.right(StorageOperationStatus.INCONSISTENCY);
1378             }
1379         }
1380         if (result == null) {
1381             // Remove CHECKOUT relation
1382             Either<Edge, TitanOperationStatus> deleteEdgeResult = titanDao.deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.STATE);
1383             if (deleteEdgeResult.isRight()) {
1384                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, faileToUpdateStateMsg, toscaElementVertex.getUniqueId());
1385                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(deleteEdgeResult.right().value()));
1386             }
1387         }
1388         if (result == null) {
1389             // Create CHECKIN relation
1390             Map<EdgePropertyEnum, Object> edgeProperties = new HashMap<>();
1391             edgeProperties.put(EdgePropertyEnum.STATE, nextState);
1392             TitanOperationStatus createEdgeRes = titanDao.createEdge(modifierVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.STATE, edgeProperties);
1393             if (createEdgeRes != TitanOperationStatus.OK) {
1394                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, faileToUpdateStateMsg, toscaElementVertex.getUniqueId());
1395                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(createEdgeRes));
1396             }
1397         }
1398         if (result == null) {
1399             result = Either.left(toscaElementVertex);
1400         }
1401         return result;
1402     }
1403
1404     private Either<GraphVertex, StorageOperationStatus> updateLastModifierEdge(GraphVertex toscaElementVertex, GraphVertex ownerVertex, GraphVertex modifierVertex) {
1405         Either<GraphVertex, StorageOperationStatus> result = null;
1406         if (!modifierVertex.getMetadataProperties().get(GraphPropertyEnum.USERID).equals(ownerVertex.getMetadataProperties().get(GraphPropertyEnum.USERID))) {
1407             Either<Edge, TitanOperationStatus> deleteEdgeRes = titanDao.deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.LAST_MODIFIER);
1408             if (deleteEdgeRes.isRight()) {
1409                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete last modifier {} to tosca element {}. Edge type is {}", ownerVertex.getUniqueId(), ownerVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
1410                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(deleteEdgeRes.right().value()));
1411             }
1412             if (result == null) {
1413                 TitanOperationStatus createEdgeRes = titanDao.createEdge(modifierVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.LAST_MODIFIER, new HashMap<>());
1414
1415                 if (createEdgeRes != TitanOperationStatus.OK) {
1416                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to associate user {} to component {}. Edge type is {}", modifierVertex.getUniqueId(), ownerVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
1417                     result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(createEdgeRes));
1418                 } else {
1419                     result = Either.left(modifierVertex);
1420                 }
1421             }
1422         } else {
1423             result = Either.left(ownerVertex);
1424         }
1425         return result;
1426     }
1427
1428     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForCheckin(String toscaElementId, String modifierId, String ownerId) {
1429         Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGetParameters = new HashMap<>();
1430         verticesToGetParameters.put(toscaElementId, new ImmutablePair<>(GraphPropertyEnum.UNIQUE_ID, JsonParseFlagEnum.ParseMetadata));
1431         verticesToGetParameters.put(modifierId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1432         verticesToGetParameters.put(ownerId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1433         return verticesToGetParameters;
1434     }
1435
1436     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForRequestCertification(String toscaElementId, String modifierId, String ownerId) {
1437         Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGetParameters = new HashMap<>();
1438         verticesToGetParameters.put(toscaElementId, new ImmutablePair<>(GraphPropertyEnum.UNIQUE_ID, JsonParseFlagEnum.ParseAll));
1439         verticesToGetParameters.put(modifierId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1440         verticesToGetParameters.put(ownerId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1441         return verticesToGetParameters;
1442     }
1443
1444     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForCheckout(String toscaElementId, String modifierId, String ownerId) {
1445         //Implementation is currently identical
1446         return prepareParametersToGetVerticesForRequestCertification(toscaElementId,modifierId, ownerId);
1447     }
1448
1449     private String getNextCertifiedVersion(String version) {
1450         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1451         Integer nextMajorVersion = Integer.parseInt(versionParts[0]) + 1;
1452         return nextMajorVersion + VERSION_DELIMITER + "0";
1453     }
1454
1455     private String getNextVersion(String currVersion) {
1456         String[] versionParts = currVersion.split(VERSION_DELIMITER_REGEXP);
1457         Integer minorVersion = Integer.parseInt(versionParts[1]) + 1;
1458         return versionParts[0] + VERSION_DELIMITER + minorVersion;
1459     }
1460
1461     private Integer getMinorVersion(String version) {
1462         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1463         return Integer.parseInt(versionParts[1]);
1464     }
1465
1466     private Integer getMajorVersion(String version) {
1467         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1468         return Integer.parseInt(versionParts[0]);
1469     }
1470
1471     private boolean isFirstCheckoutAfterCertification(String version) {
1472         return (Integer.parseInt(version.split(VERSION_DELIMITER_REGEXP)[0]) != 0 && Integer.parseInt(version.split(VERSION_DELIMITER_REGEXP)[1]) == 1);
1473     }
1474
1475     public Either<ToscaElement, StorageOperationStatus> forceCerificationOfToscaElement(String toscaElementId, String modifierId, String ownerId, String currVersion) {
1476         Either<GraphVertex, StorageOperationStatus> resultUpdate = null;
1477         Either<ToscaElement, StorageOperationStatus> result = null;
1478         GraphVertex toscaElement = null;
1479         GraphVertex modifier = null;
1480         GraphVertex owner;
1481         try {
1482             Either<Map<String, GraphVertex>, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId));
1483             if (getVerticesRes.isRight()) {
1484                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
1485                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value()));
1486             }
1487             if (result == null) {
1488                 toscaElement = getVerticesRes.left().value().get(toscaElementId);
1489                 modifier = getVerticesRes.left().value().get(modifierId);
1490                 owner = getVerticesRes.left().value().get(ownerId);
1491
1492                 StorageOperationStatus status = handleRelationsUponForceCertification(toscaElement, modifier, owner);
1493                 if (status != StorageOperationStatus.OK) {
1494                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations on certification request for tosca element {}. Status is {}. ", toscaElement.getUniqueId(), status);
1495                 }
1496             }
1497             if (result == null) {
1498                 LifecycleStateEnum nextState = LifecycleStateEnum.CERTIFIED;
1499
1500                 toscaElement.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
1501                 toscaElement.addMetadataProperty(GraphPropertyEnum.VERSION, getNextCertifiedVersion(currVersion));
1502
1503                 resultUpdate = updateToscaElementVertexMetadataPropertiesAndJson(toscaElement);
1504                 if (resultUpdate.isRight()) {
1505                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set lifecycle for tosca elememt {} to state {}, error: {}", toscaElement.getUniqueId(), nextState, resultUpdate.right().value());
1506                     result = Either.right(resultUpdate.right().value());
1507                 }
1508             }
1509             if (result == null) {
1510                 ToscaElementOperation operation = getToscaElementOperation(toscaElement.getLabel());
1511                 result = operation.getToscaElement(toscaElement.getUniqueId());
1512             }
1513             return result;
1514
1515         } catch (Exception e) {
1516             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during request certification tosca element {}. {}", toscaElementId, e.getMessage());
1517         }
1518         return result;
1519     }
1520
1521     private StorageOperationStatus handleRelationsUponForceCertification(GraphVertex toscaElement, GraphVertex modifier, GraphVertex owner) {
1522
1523         StorageOperationStatus result = null;
1524         TitanOperationStatus status = titanDao.replaceEdgeLabel(owner.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE);
1525         if (status != TitanOperationStatus.OK) {
1526             result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
1527         }
1528         if (result == null) {
1529             Map<EdgePropertyEnum, Object> properties = new EnumMap<>(EdgePropertyEnum.class);
1530             properties.put(EdgePropertyEnum.STATE, LifecycleStateEnum.CERTIFIED);
1531             status = titanDao.createEdge(modifier, toscaElement, EdgeLabelEnum.STATE, properties);
1532             if (status != TitanOperationStatus.OK) {
1533                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "failed to create edge. Status is {}", status);
1534                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(status);
1535             }
1536         }
1537         if (result == null) {
1538             result = StorageOperationStatus.OK;
1539         }
1540         return result;
1541     }
1542
1543     private StorageOperationStatus updateEdgeToCatalogRootByUndoCheckout(TitanVertex preV, GraphVertex curV) {
1544         if (preV == null) {
1545             return updateEdgeToCatalogRoot(null, curV);
1546         }
1547         String uniqueIdPreVer = (String) titanDao.getProperty((TitanVertex) preV, GraphPropertyEnum.UNIQUE_ID.getProperty());
1548         LifecycleStateEnum state = LifecycleStateEnum.findState((String) titanDao.getProperty(preV, GraphPropertyEnum.STATE.getProperty()));
1549         if (state == LifecycleStateEnum.CERTIFIED) {
1550             return updateEdgeToCatalogRoot(null, curV);
1551         }
1552         return titanDao.getVertexById(uniqueIdPreVer)
1553                 .either(l -> updateEdgeToCatalogRoot(l, curV),
1554                         DaoStatusConverter::convertTitanStatusToStorageStatus);
1555     }
1556
1557     private StorageOperationStatus updateEdgeToCatalogRoot(GraphVertex newVersionV, GraphVertex prevVersionV) {
1558         Either<GraphVertex, TitanOperationStatus> catalog = titanDao.getVertexByLabel(VertexTypeEnum.CATALOG_ROOT);
1559         if (catalog.isRight()) {
1560             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch catalog vertex. error {}", catalog.right().value());
1561             return DaoStatusConverter.convertTitanStatusToStorageStatus(catalog.right().value());
1562         }
1563         GraphVertex catalogV = catalog.left().value();
1564         if (newVersionV != null) {
1565             Boolean isAbstract = (Boolean) newVersionV.getMetadataProperty(GraphPropertyEnum.IS_ABSTRACT);
1566                         
1567                         if ( isAbstract == null || !isAbstract ) {
1568                 // no new vertex, only delete previous
1569                 TitanOperationStatus result = titanDao.createEdge(catalogV, newVersionV, EdgeLabelEnum.CATALOG_ELEMENT, null);
1570                 if (result != TitanOperationStatus.OK) {
1571                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge from {} to catalog vertex. error {}", newVersionV.getUniqueId(), result);
1572                     return DaoStatusConverter.convertTitanStatusToStorageStatus(result);
1573                 }
1574             }
1575         }
1576         if (prevVersionV != null) {
1577             Boolean isAbstract = (Boolean) prevVersionV.getMetadataProperty(GraphPropertyEnum.IS_ABSTRACT);
1578             if (isAbstract == null || !isAbstract) {
1579                 // if prev == null -> new resource was added
1580                 Either<Edge, TitanOperationStatus> deleteResult = titanDao.deleteEdge(catalogV, prevVersionV, EdgeLabelEnum.CATALOG_ELEMENT);
1581                 if (deleteResult.isRight()) {
1582                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete edge from {} to catalog vertex. error {}", prevVersionV.getUniqueId(), deleteResult.right().value());
1583                     return DaoStatusConverter.convertTitanStatusToStorageStatus(deleteResult.right().value());
1584                 }
1585             }
1586         }
1587         return StorageOperationStatus.OK;
1588     }
1589 }