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