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