b7cc2c8bd6ae065e7e53eb213721f39454a35f3b
[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(
311         String toscaElementId,
312         String modifierId,
313         String ownerId) {
314         try {
315             return janusGraphDao
316                 .getVerticesByUniqueIdAndParseFlag(
317                     prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId))
318                 .right().map(status ->
319                     logDebugMessageAndReturnStorageOperationStatus(
320                         DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status),
321                         FAILED_TO_GET_VERTICES,
322                         toscaElementId))
323                 .left().bind(verticesRes -> {
324                     GraphVertex toscaElement = verticesRes.get(toscaElementId);
325                     GraphVertex modifier = verticesRes.get(modifierId);
326                     Integer majorVersion = getMajorVersion(
327                         (String) toscaElement.getMetadataProperty(GraphPropertyEnum.VERSION));
328
329                     return handleRelationsBeforeCertifyingAndProcessClone(toscaElement,
330                         modifier, majorVersion);
331                 });
332         } catch (Exception e) {
333             return Either.right(
334                 logDebugMessageAndReturnStorageOperationStatus(StorageOperationStatus.GENERAL_ERROR,
335                     "Exception occurred during certification tosca element {}.",
336                     toscaElementId, e)
337             );
338         }
339     }
340
341     private Either<ToscaElement, StorageOperationStatus> handleRelationsBeforeCertifyingAndProcessClone(
342         GraphVertex toscaElement,
343         GraphVertex modifier,
344         Integer majorVersion) {
345         StorageOperationStatus status = handleRelationsOfPreviousToscaElementBeforeCertifying(toscaElement,
346             modifier, majorVersion);
347         if (status != StorageOperationStatus.OK) {
348             return Either.right(
349                 logDebugMessageAndReturnStorageOperationStatus(status,
350                     "Failed to handle relations of previous tosca element before certifying {}. Status is {}. ",
351                     toscaElement.getUniqueId(), status));
352         } else {
353             return cloneToscaElementAndHandleRelations(toscaElement, modifier, majorVersion);
354         }
355     }
356
357     private Either<ToscaElement, StorageOperationStatus> cloneToscaElementAndHandleRelations(
358         GraphVertex toscaElement,
359         GraphVertex modifier,
360         Integer majorVersion) {
361         return cloneToscaElementForCertify(toscaElement, modifier, majorVersion)
362             .right().map(status -> logDebugMessageAndReturnStorageOperationStatus(status,
363                 "Failed to clone tosca element during certification. "))
364             .left().bind(certifiedToscaElement ->
365                 handleRelationsOfNewestCertifiedToscaElementAndReturn(toscaElement, certifiedToscaElement));
366     }
367
368     private Either<ToscaElement, StorageOperationStatus> handleRelationsOfNewestCertifiedToscaElementAndReturn(
369         GraphVertex toscaElement,
370         GraphVertex certifiedToscaElement) {
371         StorageOperationStatus status = handleRelationsOfNewestCertifiedToscaElement(toscaElement,
372             certifiedToscaElement);
373         if (status != StorageOperationStatus.OK) {
374             return Either.right(
375                 logDebugMessageAndReturnStorageOperationStatus(status,
376                     "Failed to handle relations of newest certified tosca element {}. Status is {}. ",
377                     certifiedToscaElement.getUniqueId(), status));
378         } else {
379             return getToscaElementOperation(toscaElement.getLabel())
380                 .getToscaElement(certifiedToscaElement.getUniqueId());
381         }
382     }
383
384     private static StorageOperationStatus logDebugMessageAndReturnStorageOperationStatus(
385         final StorageOperationStatus status,
386         final String msg,
387         final Object... args) {
388         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, msg, args);
389         return status;
390     }
391
392     private StorageOperationStatus handleRelationsOfNewestCertifiedToscaElement(GraphVertex toscaElement, GraphVertex certifiedToscaElement) {
393
394         JanusGraphOperationStatus createVersionEdgeStatus = janusGraphDao.createEdge(toscaElement, certifiedToscaElement, EdgeLabelEnum.VERSION, new HashMap<>());
395         if (createVersionEdgeStatus != JanusGraphOperationStatus.OK) {
396             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create version edge from last element {} to new certified element {}. status=", toscaElement.getUniqueId(), certifiedToscaElement.getUniqueId(),
397                     createVersionEdgeStatus);
398             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createVersionEdgeStatus);
399         }
400         return StorageOperationStatus.OK;
401     }
402
403     public Either<GraphVertex, JanusGraphOperationStatus> findUser(String userId) {
404         return findUserVertex(userId);
405     }
406
407     private Either<Boolean, StorageOperationStatus> markToscaElementsAsDeleted(ToscaElementOperation operation, List<GraphVertex> toscaElements) {
408         Either<Boolean, StorageOperationStatus> result = Either.left(true);
409         for (GraphVertex resourceToDelete : toscaElements) {
410             if (!(resourceToDelete.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals(LifecycleStateEnum.CERTIFIED.name())) {
411                 Either<GraphVertex, StorageOperationStatus> deleteElementRes = operation.markComponentToDelete(resourceToDelete);
412                 if (deleteElementRes.isRight()) {
413                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete tosca element {}. Status is {}. ", resourceToDelete.getUniqueId(), deleteElementRes.right().value());
414                     result = Either.right(deleteElementRes.right().value());
415                     break;
416                 }
417             }
418         }
419         return result;
420     }
421
422     private StorageOperationStatus handleRelationsOfPreviousToscaElementBeforeCertifying(GraphVertex toscaElement, GraphVertex modifier, Integer majorVersion) {
423         StorageOperationStatus result = null;
424         if (majorVersion > 0) {
425             Either<Vertex, StorageOperationStatus> findRes = findLastCertifiedToscaElementVertex(toscaElement);
426             if (findRes.isRight()) {
427                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch last certified tosca element {} . Status is {}. ", toscaElement.getMetadataProperty(GraphPropertyEnum.NAME), findRes.right().value());
428                 result = findRes.right().value();
429             }
430             if (result == null) {
431                 Vertex lastCertifiedVertex = findRes.left().value();
432                 Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
433                 properties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
434                 JanusGraphOperationStatus status = janusGraphDao
435                     .updateVertexMetadataPropertiesWithJson(lastCertifiedVertex, properties);
436                 if (status != JanusGraphOperationStatus.OK) {
437                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set highest version  of tosca element {} to [{}]. Status is {}", toscaElement.getUniqueId(), false, status);
438                     result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
439                 }
440                 // remove previous certified version from the catalog
441                 GraphVertex lastCertifiedV = new GraphVertex();
442                 lastCertifiedV.setVertex((JanusGraphVertex) lastCertifiedVertex);
443                 lastCertifiedV.setUniqueId((String) janusGraphDao
444                     .getProperty((JanusGraphVertex) lastCertifiedVertex, GraphPropertyEnum.UNIQUE_ID.getProperty()));
445                 lastCertifiedV.addMetadataProperty(GraphPropertyEnum.IS_ABSTRACT,
446                     (Boolean) janusGraphDao.getProperty((JanusGraphVertex) lastCertifiedVertex, GraphPropertyEnum.IS_ABSTRACT.getProperty()));
447                 StorageOperationStatus res = updateEdgeToCatalogRoot(null, lastCertifiedV);
448                 if (res != StorageOperationStatus.OK) {
449                     return res;
450                 }
451             }
452         }
453         if (result == null) {
454             result = StorageOperationStatus.OK;
455         }
456         return result;
457     }
458
459     private Either<Vertex, StorageOperationStatus> findLastCertifiedToscaElementVertex(GraphVertex toscaElement) {
460         return findLastCertifiedToscaElementVertexRecursively(toscaElement.getVertex());
461     }
462
463     private Either<Vertex, StorageOperationStatus> findLastCertifiedToscaElementVertexRecursively(Vertex vertex) {
464         if (isCertifiedVersion((String) vertex.property(GraphPropertyEnum.VERSION.getProperty()).value())) {
465             return Either.left(vertex);
466         }
467         Iterator<Edge> edgeIter = vertex.edges(Direction.IN, EdgeLabelEnum.VERSION.name());
468         if (!edgeIter.hasNext()) {
469             return Either.right(StorageOperationStatus.NOT_FOUND);
470         }
471         return findLastCertifiedToscaElementVertexRecursively(edgeIter.next().outVertex());
472     }
473
474     private boolean isCertifiedVersion(String version) {
475         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
476         if (Integer.parseInt(versionParts[0]) > 0 && Integer.parseInt(versionParts[1]) == 0) {
477             return true;
478         }
479         return false;
480     }
481
482     private StorageOperationStatus updateOldToscaElementBeforeUndoCheckout(Vertex previousVersionToscaElement) {
483
484         StorageOperationStatus result = StorageOperationStatus.OK;
485         String previousVersion = (String) previousVersionToscaElement.property(GraphPropertyEnum.VERSION.getProperty()).value();
486         if (!previousVersion.endsWith(".0")) {
487             try {
488                 CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update vertex of previous version of tosca element", previousVersionToscaElement.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()));
489
490                 Map<String, Object> propertiesToUpdate = new HashMap<>();
491                 propertiesToUpdate.put(GraphPropertyEnum.IS_HIGHEST_VERSION.getProperty(), true);
492                 Map<String, Object> jsonMetadataMap = JsonParserUtils.toMap((String) previousVersionToscaElement.property(GraphPropertyEnum.METADATA.getProperty()).value());
493                 jsonMetadataMap.put(GraphPropertyEnum.IS_HIGHEST_VERSION.getProperty(), true);
494                 propertiesToUpdate.put(GraphPropertyEnum.METADATA.getProperty(), JsonParserUtils.toJson(jsonMetadataMap));
495
496                 janusGraphDao.setVertexProperties(previousVersionToscaElement, propertiesToUpdate);
497
498                 Iterator<Edge> edgesIter = previousVersionToscaElement.edges(Direction.IN, EdgeLabelEnum.LAST_STATE.name());
499                 if (!edgesIter.hasNext()) {
500                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch last modifier vertex for tosca element {}. ", previousVersionToscaElement.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()));
501                     result = StorageOperationStatus.NOT_FOUND;
502                 } else {
503                     Edge lastStateEdge = edgesIter.next();
504                     Vertex lastModifier = lastStateEdge.outVertex();
505                     JanusGraphOperationStatus replaceRes = janusGraphDao
506                         .replaceEdgeLabel(lastModifier, previousVersionToscaElement, lastStateEdge, EdgeLabelEnum.LAST_STATE, EdgeLabelEnum.STATE);
507                     if (replaceRes != JanusGraphOperationStatus.OK) {
508                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to replace label from {} to {}. status = {}", EdgeLabelEnum.LAST_STATE, EdgeLabelEnum.STATE, replaceRes);
509                         result = StorageOperationStatus.INCONSISTENCY;
510                         if (replaceRes != JanusGraphOperationStatus.INVALID_ID) {
511                             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(replaceRes);
512                         }
513                     }
514
515                 }
516             } catch (Exception e) {
517                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during update previous tosca element {} before undo checkout. {} ", e.getMessage());
518             }
519         }
520         return result;
521     }
522
523     private StorageOperationStatus updatePreviousVersion(GraphVertex toscaElementVertex, GraphVertex ownerVertex) {
524         StorageOperationStatus result = null;
525         String ownerId = (String) ownerVertex.getMetadataProperty(GraphPropertyEnum.USERID);
526         String toscaElementId = toscaElementVertex.getUniqueId();
527         if (!toscaElementVertex.getMetadataProperty(GraphPropertyEnum.STATE).equals(LifecycleStateEnum.CERTIFIED.name())) {
528             toscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, false);
529             Either<GraphVertex, JanusGraphOperationStatus> updateVertexRes = janusGraphDao.updateVertex(toscaElementVertex);
530             if (updateVertexRes.isRight()) {
531                 JanusGraphOperationStatus titatStatus = updateVertexRes.right().value();
532                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update tosca element vertex {}. Status is  {}", toscaElementVertex.getUniqueId(), titatStatus);
533                 result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(titatStatus);
534             }
535             Either<Edge, JanusGraphOperationStatus> deleteEdgeRes = null;
536             if (result == null) {
537                 CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to replace edge with label {} to label {} from {} to {}. ", EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE, ownerId, toscaElementId);
538
539                 deleteEdgeRes = janusGraphDao
540                     .deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.STATE);
541                 if (deleteEdgeRes.isRight()) {
542                     JanusGraphOperationStatus janusGraphStatus = deleteEdgeRes.right().value();
543                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete edge with label {} from {} to {}. Status is {} ", EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE, ownerId, toscaElementId, janusGraphStatus);
544                     if (!janusGraphStatus.equals(JanusGraphOperationStatus.INVALID_ID)) {
545                         result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphStatus);
546                     } else {
547                         result = StorageOperationStatus.INCONSISTENCY;
548                     }
549                 }
550             }
551             if (result == null) {
552                 JanusGraphOperationStatus
553                     createEdgeRes = janusGraphDao
554                     .createEdge(ownerVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.LAST_STATE, deleteEdgeRes.left().value());
555                 if (createEdgeRes != JanusGraphOperationStatus.OK) {
556                     result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdgeRes);
557                 }
558             }
559         }
560         if (result == null) {
561             result = StorageOperationStatus.OK;
562         }
563         return result;
564     }
565
566     private Either<ToscaElement, StorageOperationStatus> cloneToscaElementForCheckout(GraphVertex toscaElementVertex, GraphVertex modifierVertex) {
567
568         Either<ToscaElement, StorageOperationStatus> result = null;
569         Either<GraphVertex, StorageOperationStatus> cloneResult = null;
570         ToscaElementOperation operation = getToscaElementOperation(toscaElementVertex.getLabel());
571         // check if component with the next version doesn't exist.
572         Iterator<Edge> nextVersionComponentIter = toscaElementVertex.getVertex().edges(Direction.OUT, EdgeLabelEnum.VERSION.name());
573         if (nextVersionComponentIter != null && nextVersionComponentIter.hasNext()) {
574             Vertex nextVersionVertex = nextVersionComponentIter.next().inVertex();
575             String fetchedVersion = (String) nextVersionVertex.property(GraphPropertyEnum.VERSION.getProperty()).value();
576             String fetchedName = (String) nextVersionVertex.property(GraphPropertyEnum.NORMALIZED_NAME.getProperty()).value();
577             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. ",
578                     toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME).toString(), toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION).toString(), fetchedName, fetchedVersion);
579             result = Either.right(StorageOperationStatus.ENTITY_ALREADY_EXISTS);
580         }
581         if (result == null) {
582             toscaElementVertex.getOrSetDefaultInstantiationTypeForToscaElementJson();
583             cloneResult = operation.cloneToscaElement(toscaElementVertex, cloneGraphVertexForCheckout(toscaElementVertex, modifierVertex), modifierVertex);
584             if (cloneResult.isRight()) {
585                 result = Either.right(cloneResult.right().value());
586             }
587         }
588         GraphVertex clonedVertex = null;
589         if (result == null) {
590             clonedVertex = cloneResult.left().value();
591             JanusGraphOperationStatus
592                 status = janusGraphDao
593                 .createEdge(toscaElementVertex.getVertex(), cloneResult.left().value().getVertex(), EdgeLabelEnum.VERSION, new HashMap<>());
594             if (status != JanusGraphOperationStatus.OK) {
595                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.VERSION,
596                         toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), cloneResult.left().value().getMetadataProperty(GraphPropertyEnum.NORMALIZED_NAME), status);
597                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
598             }
599         }
600         if (result == null) {
601             Boolean isHighest = (Boolean) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION);
602             GraphVertex prevVersionInCatalog = (isHighest != null && isHighest) ? null : toscaElementVertex;
603             StorageOperationStatus updateCatalogRes = updateEdgeToCatalogRoot(clonedVertex, prevVersionInCatalog);
604             if (updateCatalogRes != StorageOperationStatus.OK) {
605                 return Either.right(updateCatalogRes);
606             }
607             result = operation.getToscaElement(cloneResult.left().value().getUniqueId());
608             if (result.isRight()) {
609                 return result;
610             }
611             ToscaElement toscaElement = result.left().value();
612             if (toscaElement.getToscaType() == ToscaElementTypeEnum.TOPOLOGY_TEMPLATE) {
613                 result = handleFixTopologyTemplate(toscaElementVertex, result, operation, clonedVertex, toscaElement);
614             }
615         }
616
617         return result;
618     }
619
620     private Either<ToscaElement, StorageOperationStatus> handleFixTopologyTemplate(GraphVertex toscaElementVertex, Either<ToscaElement, StorageOperationStatus> result, ToscaElementOperation operation, GraphVertex clonedVertex,
621             ToscaElement toscaElement) {
622         TopologyTemplate topologyTemplate = (TopologyTemplate) toscaElement;
623         Map<String, MapPropertiesDataDefinition> instInputs = topologyTemplate.getInstInputs();
624         Map<String, MapGroupsDataDefinition> instGroups = topologyTemplate.getInstGroups();
625         Map<String, MapArtifactDataDefinition> instArtifactsMap = topologyTemplate.getInstanceArtifacts();
626         Map<String, ToscaElement> origCompMap = new HashMap<>();
627         if (instInputs == null) {
628             instInputs = new HashMap<>();
629         }
630         if (instGroups == null) {
631             instGroups = new HashMap<>();
632         }
633         if (instArtifactsMap == null) {
634             instArtifactsMap = new HashMap<>();
635         }
636         Map<String, ComponentInstanceDataDefinition> instancesMap = topologyTemplate.getComponentInstances();
637         boolean isAddInstGroup = instGroups == null || instGroups.isEmpty();
638         boolean needUpdateComposition = false;
639
640         if (instancesMap != null && !instancesMap.isEmpty()) {
641             for (ComponentInstanceDataDefinition vfInst : instancesMap.values()) {
642                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "vfInst name is {} . OriginType {}. ", vfInst.getName(), vfInst.getOriginType());
643                 if (vfInst.getOriginType().name().equals(OriginTypeEnum.VF.name())) {
644                     collectInstanceInputAndGroups(instInputs, instGroups, instArtifactsMap, origCompMap, isAddInstGroup, vfInst, clonedVertex);
645                 }
646                 needUpdateComposition = needUpdateComposition || fixToscaComponentName(vfInst, origCompMap);
647                 if (needUpdateComposition) {
648                     instancesMap.put(vfInst.getUniqueId(), vfInst);
649                 }
650             }
651             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add to graph instInputs {}  instGroups {} needUpdateComposition {}", instInputs, instGroups, needUpdateComposition);
652             if (!instInputs.isEmpty()) {
653                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add inst inputs {} ", instInputs == null ? 0 : instInputs.size());
654                 GraphVertex toscaDataVertex = null;
655                 Either<GraphVertex, JanusGraphOperationStatus> instInpVertexEither = janusGraphDao
656                     .getChildVertex(toscaElementVertex, EdgeLabelEnum.INST_INPUTS, JsonParseFlagEnum.ParseJson);
657                 if (instInpVertexEither.isLeft()) {
658                     toscaDataVertex = instInpVertexEither.left().value();
659                 }
660
661                 StorageOperationStatus status = handleToscaData(clonedVertex, VertexTypeEnum.INST_INPUTS, EdgeLabelEnum.INST_INPUTS, toscaDataVertex, instInputs);
662                 if (status != StorageOperationStatus.OK) {
663                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instance inputs . Status is {}. ", status);
664                     result = Either.right(status);
665                     return result;
666                 }
667
668             }
669             if (!instGroups.isEmpty()) {
670                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before add inst groups {} ", instGroups == null ? 0 : instGroups.size());
671                 GraphVertex toscaDataVertex = null;
672                 Either<GraphVertex, JanusGraphOperationStatus> instGrVertexEither = janusGraphDao
673                     .getChildVertex(toscaElementVertex, EdgeLabelEnum.INST_GROUPS, JsonParseFlagEnum.ParseJson);
674                 if (instGrVertexEither.isLeft()) {
675                     toscaDataVertex = instGrVertexEither.left().value();
676                 }
677
678                 StorageOperationStatus status = handleToscaData(clonedVertex, VertexTypeEnum.INST_GROUPS, EdgeLabelEnum.INST_GROUPS, toscaDataVertex, instGroups);
679                 if (status != StorageOperationStatus.OK) {
680                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instance group . Status is {}. ", status);
681                     result = Either.right(status);
682                     return result;
683                 }
684
685             }
686             if (needUpdateComposition) {
687                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before update Instances ");
688                 Map<String, CompositionDataDefinition> jsonComposition = (Map<String, CompositionDataDefinition>) clonedVertex.getJson();
689                 CompositionDataDefinition compositionDataDefinition = jsonComposition.get(JsonConstantKeysEnum.COMPOSITION.getValue());
690                 compositionDataDefinition.setComponentInstances(instancesMap);
691                 Either<GraphVertex, JanusGraphOperationStatus> updateElement = janusGraphDao.updateVertex(clonedVertex);
692                 if (updateElement.isRight()) {
693                     JanusGraphOperationStatus status = updateElement.right().value();
694                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update instances on metadata vertex . Status is {}. ", status);
695                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
696                     return result;
697                 }
698             }
699
700             result = operation.getToscaElement(clonedVertex.getUniqueId());
701
702         } else {
703             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "RI map empty on component {}", toscaElement.getUniqueId());
704         }
705         return result;
706     }
707
708     // TODO remove after jsonModelMigration
709     public boolean resolveToscaComponentName(ComponentInstanceDataDefinition vfInst, Map<String, ToscaElement> origCompMap) {
710         return fixToscaComponentName(vfInst, origCompMap);
711     }
712
713     private boolean fixToscaComponentName(ComponentInstanceDataDefinition vfInst, Map<String, ToscaElement> origCompMap) {
714         if (vfInst.getToscaComponentName() == null || vfInst.getToscaComponentName().isEmpty()) {
715             String ciUid = vfInst.getUniqueId();
716             String origCompUid = vfInst.getComponentUid();
717             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "fixToscaComponentName:: Ri id {} . origin component id is {}. type is{} ", ciUid, origCompUid, vfInst.getOriginType());
718             ToscaElement origComp = null;
719             if (!origCompMap.containsKey(origCompUid)) {
720                 Either<ToscaElement, StorageOperationStatus> origCompEither;
721                 if (vfInst.getOriginType() == null || vfInst.getOriginType().name().equals(OriginTypeEnum.VF.name())) {
722                     origCompEither = topologyTemplateOperation.getToscaElement(origCompUid);
723                 } else {
724                     origCompEither = nodeTypeOperation.getToscaElement(origCompUid);
725                 }
726                 if (origCompEither.isRight()) {
727                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find orig component {} . Status is {}. ", origCompEither.right().value());
728                     return false;
729                 }
730                 origComp = origCompEither.left().value();
731                 origCompMap.put(origCompUid, origComp);
732             } else {
733                 origComp = origCompMap.get(origCompUid);
734             }
735             String toscaName = (String) origComp.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME);
736             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Origin component id is {}. toscaName {}", origCompUid, toscaName);
737             vfInst.setToscaComponentName(toscaName);
738             return true;
739         }
740         return false;
741     }
742
743     private void collectInstanceInputAndGroups(Map<String, MapPropertiesDataDefinition> instInputs, Map<String, MapGroupsDataDefinition> instGroups, Map<String, MapArtifactDataDefinition> instArtifactsMap, Map<String, ToscaElement> origCompMap,
744             boolean isAddInstGroup, ComponentInstanceDataDefinition vfInst, GraphVertex clonedVertex) {
745         String ciUid = vfInst.getUniqueId();
746         String origCompUid = vfInst.getComponentUid();
747         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "collectInstanceInputAndGroups:: Ri id {} . origin component id is {}. ", ciUid, origCompUid);
748         TopologyTemplate origComp = null;
749         if (!origCompMap.containsKey(origCompUid)) {
750             Either<ToscaElement, StorageOperationStatus> origCompEither = topologyTemplateOperation.getToscaElement(origCompUid);
751             if (origCompEither.isRight()) {
752                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find orig component {} . Status is {}. ", origCompEither.right().value());
753                 return;
754             }
755             origComp = (TopologyTemplate) origCompEither.left().value();
756             origCompMap.put(origCompUid, origComp);
757         } else {
758             origComp = (TopologyTemplate) origCompMap.get(origCompUid);
759         }
760         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Orig component {}. ", origComp.getUniqueId());
761
762         Map<String, PropertyDataDefinition> origInputs = origComp.getInputs();
763         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Orig component inputs size {}. ", origInputs == null ? 0 : origInputs.size());
764         if (origInputs != null) {
765             if (!instInputs.containsKey(ciUid)) {
766                 MapPropertiesDataDefinition instProperties = new MapPropertiesDataDefinition(origInputs);
767                 instInputs.put(ciUid, instProperties);
768             } else {
769
770                 MapPropertiesDataDefinition instInputMap = instInputs.get(ciUid);
771                 Map<String, PropertyDataDefinition> instProp = instInputMap.getMapToscaDataDefinition();
772                 origInputs.forEach((propName, propMap) -> {
773                     if (!instProp.containsKey(propName)) {
774                         instProp.put(propName, propMap);
775                     }
776                 });
777             }
778             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "ComponentInstanseInputs {}. ", instInputs.get(ciUid));
779         }
780
781         if (isAddInstGroup) {
782             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "before create group instance. ");
783             List<GroupDataDefinition> filteredGroups = null;
784
785             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups before filter. Size is {} ", filteredGroups == null ? 0 : filteredGroups.size());
786             if (origComp.getGroups() != null && !origComp.getGroups().isEmpty()) {
787                 filteredGroups = origComp.getGroups().values().stream().filter(g -> g.getType().equals(VF_MODULE)).collect(Collectors.toList());
788                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups . Size is {} ", filteredGroups == null ? 0 : filteredGroups.size());
789             }
790             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check vf groups after filter. Size is {} ", filteredGroups == null ? 0 : filteredGroups.size());
791             if (CollectionUtils.isNotEmpty(filteredGroups)) {
792                 MapArtifactDataDefinition instArifacts = null;
793                 if (!instArtifactsMap.containsKey(ciUid)) {
794
795                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "istance artifacts not found ");
796
797                     Map<String, ArtifactDataDefinition> deploymentArtifacts = origComp.getDeploymentArtifacts();
798
799                     instArifacts = new MapArtifactDataDefinition(deploymentArtifacts);
800                     addToscaDataDeepElementsBlockToToscaElement(clonedVertex, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS, VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS, instArifacts, ciUid);
801
802                     instArtifactsMap.put(ciUid, instArifacts);
803
804                 } else {
805                     instArifacts = instArtifactsMap.get(ciUid);
806                 }
807
808                 if (instArifacts != null) {
809                     Map<String, ArtifactDataDefinition> instDeplArtifMap = instArifacts.getMapToscaDataDefinition();
810
811                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "check group dep artifacts. Size is {} ", instDeplArtifMap == null ? 0 : instDeplArtifMap.values().size());
812                     Map<String, GroupInstanceDataDefinition> groupInstanceToCreate = new HashMap<>();
813                     for (GroupDataDefinition group : filteredGroups) {
814                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "create new groupInstance  {} ", group.getName());
815                         GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition(group, vfInst, instDeplArtifMap);
816                         List<String> artifactsUid = new ArrayList<>();
817                         List<String> artifactsId = new ArrayList<>();
818                         if (instDeplArtifMap!=null) {
819                                 for (ArtifactDataDefinition artifact : instDeplArtifMap.values()) {
820                                     Optional<String> op = group.getArtifacts().stream().filter(p -> p.equals(artifact.getGeneratedFromId())).findAny();
821                                     if (op.isPresent()) {
822                                         artifactsUid.add(artifact.getArtifactUUID());
823                                         artifactsId.add(artifact.getUniqueId());
824         
825                                     }
826                                 }
827                         }
828                         groupInstance.setGroupInstanceArtifacts(artifactsId);
829                         groupInstance.setGroupInstanceArtifactsUuid(artifactsUid);
830                         groupInstanceToCreate.put(groupInstance.getName(), groupInstance);
831                     }
832                     if (MapUtils.isNotEmpty(groupInstanceToCreate)) {
833                         instGroups.put(vfInst.getUniqueId(), new MapGroupsDataDefinition(groupInstanceToCreate));
834
835                     }
836                 }
837             }
838         }
839     }
840
841     private GraphVertex cloneGraphVertexForCheckout(GraphVertex toscaElementVertex, GraphVertex modifierVertex) {
842         GraphVertex nextVersionToscaElementVertex = new GraphVertex();
843         String uniqueId = UniqueIdBuilder.buildComponentUniqueId();
844         Map<GraphPropertyEnum, Object> metadataProperties = new HashMap<>(toscaElementVertex.getMetadataProperties());
845         nextVersionToscaElementVertex.setMetadataProperties(metadataProperties);
846         nextVersionToscaElementVertex.setUniqueId(uniqueId);
847         nextVersionToscaElementVertex.setLabel(toscaElementVertex.getLabel());
848         nextVersionToscaElementVertex.setType(toscaElementVertex.getType());
849
850         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uniqueId);
851         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, nextVersionToscaElementVertex.getType().name());
852         String nextVersion = getNextVersion((String) toscaElementVertex.getMetadataProperty(GraphPropertyEnum.VERSION));
853         if (isFirstCheckoutAfterCertification(nextVersion)) {
854             nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UUID, IdBuilderUtils.generateUUID());
855         }
856         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.VERSION, nextVersion);
857         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name());
858         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
859
860         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE) {
861             nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED.name());
862         }
863         if (!MapUtils.isEmpty(toscaElementVertex.getMetadataJson())) {
864             nextVersionToscaElementVertex.setMetadataJson(new HashMap<>(toscaElementVertex.getMetadataJson()));
865             nextVersionToscaElementVertex.updateMetadataJsonWithCurrentMetadataProperties();
866         }
867         long currTime = System.currentTimeMillis();
868         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CREATION_DATE, currTime);
869         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, currTime);
870         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_CREATOR, modifierVertex.getUniqueId());
871         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_LAST_UPDATER, modifierVertex.getUniqueId());
872         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE) {
873             nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CONFORMANCE_LEVEL, ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel());
874         }
875
876         if (!MapUtils.isEmpty(toscaElementVertex.getJson())) {
877             nextVersionToscaElementVertex.setJson(new HashMap<String, ToscaDataDefinition>(toscaElementVertex.getJson()));
878         }
879         return nextVersionToscaElementVertex;
880     }
881
882     private Either<GraphVertex, StorageOperationStatus> cloneToscaElementForCertify(GraphVertex toscaElementVertex,
883         GraphVertex modifierVertex, Integer majorVersion) {
884         return getToscaElementOperation(toscaElementVertex.getLabel())
885             .cloneToscaElement(
886                 toscaElementVertex,
887                 cloneGraphVertexForCertify(toscaElementVertex, modifierVertex, majorVersion),
888                 modifierVertex)
889             .right().map(status ->
890                 logDebugMessageAndReturnStorageOperationStatus(status,
891                     "Failed to clone tosca element {} for certification. Status is {}. ",
892                     toscaElementVertex.getUniqueId(), status))
893             .left().bind(clonedToscaElement ->
894                 updateEdgesDeleteNotCertifiedVersionsAndHandlePreviousVersions(
895                     clonedToscaElement, toscaElementVertex, majorVersion
896                 ));
897     }
898
899     private Either<GraphVertex, StorageOperationStatus> updateEdgesDeleteNotCertifiedVersionsAndHandlePreviousVersions(
900         GraphVertex clonedToscaElement,
901         GraphVertex toscaElementVertex,
902         Integer majorVersion
903     ) {
904         StorageOperationStatus updateEdgeToCatalog = updateEdgeToCatalogRoot(clonedToscaElement, toscaElementVertex);
905         if (updateEdgeToCatalog != StorageOperationStatus.OK) {
906             return Either.right(updateEdgeToCatalog);
907         } else {
908             Either<List<GraphVertex>, StorageOperationStatus> deleteResultEither =
909                 deleteAllPreviousNotCertifiedVersions(toscaElementVertex);
910
911             if  (deleteResultEither == null) {
912                 return Either.right(
913                     logDebugMessageAndReturnStorageOperationStatus(StorageOperationStatus.GENERAL_ERROR,
914                         "Failed to delete all previous not certified versions of tosca element {}. Null value returned.",
915                         toscaElementVertex.getUniqueId()));
916             } else {
917                 return deleteResultEither
918                     .right().map(status ->
919                         logDebugMessageAndReturnStorageOperationStatus(status,
920                             "Failed to delete all previous not certified versions of tosca element {}. Status is {}. ",
921                             toscaElementVertex.getUniqueId(), status))
922                     .left().bind(deleteResult ->
923                         handlePreviousVersionRelation(clonedToscaElement, deleteResult, majorVersion));
924             }
925         }
926     }
927
928     private Either<GraphVertex, StorageOperationStatus> handlePreviousVersionRelation(GraphVertex clonedToscaElement, List<GraphVertex> deletedVersions, Integer majorVersion) {
929         Either<GraphVertex, StorageOperationStatus> result = null;
930         Vertex previousCertifiedToscaElement = null;
931         if (majorVersion > 0) {
932             List<GraphVertex> firstMinorVersionVertex = deletedVersions.stream().filter(gv -> getMinorVersion((String) gv.getMetadataProperty(GraphPropertyEnum.VERSION)) == 1).collect(Collectors.toList());
933
934             if (CollectionUtils.isEmpty(firstMinorVersionVertex)) {
935                 result = Either.right(StorageOperationStatus.NOT_FOUND);
936             } else {
937                 previousCertifiedToscaElement = getPreviousCertifiedToscaElement(firstMinorVersionVertex.get(0));
938                 if (previousCertifiedToscaElement == null) {
939                     result = Either.right(StorageOperationStatus.NOT_FOUND);
940                 }
941             }
942             if (result == null) {
943                 JanusGraphOperationStatus
944                     status = janusGraphDao
945                     .createEdge(previousCertifiedToscaElement, clonedToscaElement.getVertex(), EdgeLabelEnum.VERSION, new HashMap<>());
946                 if (status != JanusGraphOperationStatus.OK) {
947                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge with label {} from vertex {} to tosca element vertex {} on graph. Status is {}. ", EdgeLabelEnum.VERSION,
948                             previousCertifiedToscaElement.property(GraphPropertyEnum.UNIQUE_ID.getProperty()), clonedToscaElement.getUniqueId(), status);
949                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
950                 }
951             }
952
953         }
954         if (result == null) {
955             result = Either.left(clonedToscaElement);
956         }
957         return result;
958     }
959
960     private Vertex getPreviousCertifiedToscaElement(GraphVertex graphVertex) {
961
962         Iterator<Edge> edges = graphVertex.getVertex().edges(Direction.IN, EdgeLabelEnum.VERSION.name());
963         if (edges.hasNext()) {
964             return edges.next().outVertex();
965         }
966         return null;
967     }
968
969     private Either<List<GraphVertex>, StorageOperationStatus> deleteAllPreviousNotCertifiedVersions(GraphVertex toscaElementVertex) {
970         Either<List<GraphVertex>, StorageOperationStatus> result = null;
971
972         ToscaElementOperation operation = getToscaElementOperation(toscaElementVertex.getLabel());
973         List<GraphVertex> previosVersions = null;
974         Object uuid = toscaElementVertex.getMetadataProperty(GraphPropertyEnum.UUID);
975         Object componentName = toscaElementVertex.getMetadataProperty(GraphPropertyEnum.NAME);
976         try {
977             Map<GraphPropertyEnum, Object> properties = new HashMap<>();
978             properties.put(GraphPropertyEnum.UUID, uuid);
979             properties.put(GraphPropertyEnum.NAME, componentName);
980             Either<List<GraphVertex>, JanusGraphOperationStatus> getToscaElementsRes = janusGraphDao
981                 .getByCriteria(toscaElementVertex.getLabel(), properties, JsonParseFlagEnum.ParseMetadata);
982             if (getToscaElementsRes.isRight()) {
983                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getToscaElementsRes.right().value()));
984             }
985             if (result == null) {
986                 previosVersions = getToscaElementsRes.left().value();
987                 Either<Boolean, StorageOperationStatus> deleteResult = markToscaElementsAsDeleted(operation, getToscaElementsRes.left().value());
988                 if (deleteResult.isRight()) {
989                     result = Either.right(deleteResult.right().value());
990                 }
991             }
992             if (result == null) {
993                 result = Either.left(previosVersions);
994             }
995         } catch (Exception e) {
996             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occurred during deleting all tosca elements by UUID {} and name {}. {} ", uuid, componentName, e.getMessage());
997         }
998         return result;
999     }
1000
1001     private GraphVertex cloneGraphVertexForCertify(GraphVertex toscaElementVertex, GraphVertex modifierVertex, Integer majorVersion) {
1002
1003         GraphVertex nextVersionToscaElementVertex = new GraphVertex();
1004         String uniqueId = IdBuilderUtils.generateUniqueId();
1005         Map<GraphPropertyEnum, Object> metadataProperties = new EnumMap<>(toscaElementVertex.getMetadataProperties());
1006         nextVersionToscaElementVertex.setMetadataProperties(metadataProperties);
1007         nextVersionToscaElementVertex.setUniqueId(uniqueId);
1008         nextVersionToscaElementVertex.setLabel(toscaElementVertex.getLabel());
1009         nextVersionToscaElementVertex.setType(toscaElementVertex.getType());
1010
1011         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uniqueId);
1012         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, nextVersionToscaElementVertex.getType().name());
1013         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.VERSION, (majorVersion + 1) + VERSION_DELIMITER + "0");
1014         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
1015         nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
1016         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.CREATION_DATE, System.currentTimeMillis());
1017         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, null);
1018         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_CREATOR, modifierVertex.getUniqueId());
1019         nextVersionToscaElementVertex.setJsonMetadataField(JsonPresentationFields.USER_ID_LAST_UPDATER, modifierVertex.getUniqueId());
1020
1021         if (toscaElementVertex.getType() == ComponentTypeEnum.SERVICE) {
1022             nextVersionToscaElementVertex.addMetadataProperty(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED.name());
1023         }
1024         if (!MapUtils.isEmpty(toscaElementVertex.getMetadataJson())) {
1025             nextVersionToscaElementVertex.setMetadataJson(new HashMap<>(toscaElementVertex.getMetadataJson()));
1026             nextVersionToscaElementVertex.updateMetadataJsonWithCurrentMetadataProperties();
1027         }
1028         if (!MapUtils.isEmpty(toscaElementVertex.getJson())) {
1029             nextVersionToscaElementVertex.setJson(new HashMap<String, ToscaDataDefinition>(toscaElementVertex.getJson()));
1030         }
1031         return nextVersionToscaElementVertex;
1032     }
1033
1034
1035     private Either<GraphVertex, StorageOperationStatus> checkinToscaELement(LifecycleStateEnum currState, GraphVertex toscaElementVertex, GraphVertex ownerVertex, GraphVertex modifierVertex, LifecycleStateEnum nextState) {
1036         Either<GraphVertex, StorageOperationStatus> updateRelationsRes;
1037         Either<GraphVertex, StorageOperationStatus> result = changeStateToCheckedIn(currState, toscaElementVertex, ownerVertex, modifierVertex);
1038         if (result.isLeft()) {
1039             toscaElementVertex.addMetadataProperty(GraphPropertyEnum.STATE, nextState.name());
1040             toscaElementVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
1041             result = updateToscaElementVertexMetadataPropertiesAndJson(toscaElementVertex);
1042         }
1043         if (result.isLeft()) {
1044             updateRelationsRes = updateLastModifierEdge(toscaElementVertex, ownerVertex, modifierVertex);
1045             if (updateRelationsRes.isRight()) {
1046                 result = Either.right(updateRelationsRes.right().value());
1047             }
1048         }
1049         return result;
1050     }
1051
1052     private Either<GraphVertex, StorageOperationStatus> updateToscaElementVertexMetadataPropertiesAndJson(GraphVertex toscaElementVertex) {
1053
1054         Either<GraphVertex, StorageOperationStatus> result;
1055
1056         Either<GraphVertex, JanusGraphOperationStatus> updateVertexRes = janusGraphDao.updateVertex(toscaElementVertex);
1057         if (updateVertexRes.isRight()) {
1058             JanusGraphOperationStatus titatStatus = updateVertexRes.right().value();
1059             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update state of tosca element vertex {} metadata. Status is  {}", toscaElementVertex.getUniqueId(), titatStatus);
1060             result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(titatStatus));
1061         } else {
1062             result = Either.left(updateVertexRes.left().value());
1063         }
1064         return result;
1065     }
1066
1067     private Either<GraphVertex, StorageOperationStatus> changeStateToCheckedIn(LifecycleStateEnum currState, GraphVertex toscaElementVertex, GraphVertex ownerVertex, GraphVertex modifierVertex) {
1068         Either<GraphVertex, StorageOperationStatus> result = null;
1069         LifecycleStateEnum nextState = LifecycleStateEnum.NOT_CERTIFIED_CHECKIN;
1070         String faileToUpdateStateMsg = "Failed to update state of tosca element {}. Status is  {}";
1071
1072         // Remove CHECKOUT relation
1073             Either<Edge, JanusGraphOperationStatus> deleteEdgeResult = janusGraphDao
1074                 .deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.STATE);
1075         if (deleteEdgeResult.isRight()) {
1076             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, faileToUpdateStateMsg, toscaElementVertex.getUniqueId());
1077                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(deleteEdgeResult.right().value()));
1078         }
1079
1080         if (result == null) {
1081             // Create CHECKIN relation
1082             Map<EdgePropertyEnum, Object> edgeProperties = new EnumMap<>(EdgePropertyEnum.class);
1083             edgeProperties.put(EdgePropertyEnum.STATE, nextState);
1084             JanusGraphOperationStatus
1085                 createEdgeRes = janusGraphDao
1086                 .createEdge(modifierVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.STATE, edgeProperties);
1087             if (createEdgeRes != JanusGraphOperationStatus.OK) {
1088                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, faileToUpdateStateMsg, toscaElementVertex.getUniqueId());
1089                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdgeRes));
1090             }
1091         }
1092         if (result == null) {
1093             result = Either.left(toscaElementVertex);
1094         }
1095         return result;
1096     }
1097
1098     private Either<GraphVertex, StorageOperationStatus> updateLastModifierEdge(GraphVertex toscaElementVertex, GraphVertex ownerVertex, GraphVertex modifierVertex) {
1099         Either<GraphVertex, StorageOperationStatus> result = null;
1100         if (!modifierVertex.getMetadataProperties().get(GraphPropertyEnum.USERID).equals(ownerVertex.getMetadataProperties().get(GraphPropertyEnum.USERID))) {
1101             Either<Edge, JanusGraphOperationStatus> deleteEdgeRes = janusGraphDao
1102                 .deleteEdge(ownerVertex, toscaElementVertex, EdgeLabelEnum.LAST_MODIFIER);
1103             if (deleteEdgeRes.isRight()) {
1104                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete last modifier {} to tosca element {}. Edge type is {}", ownerVertex.getUniqueId(), ownerVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
1105                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(deleteEdgeRes.right().value()));
1106             }
1107             if (result == null) {
1108                 JanusGraphOperationStatus createEdgeRes = janusGraphDao
1109                     .createEdge(modifierVertex.getVertex(), toscaElementVertex.getVertex(), EdgeLabelEnum.LAST_MODIFIER, new HashMap<>());
1110
1111                 if (createEdgeRes != JanusGraphOperationStatus.OK) {
1112                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to associate user {} to component {}. Edge type is {}", modifierVertex.getUniqueId(), ownerVertex.getUniqueId(), EdgeLabelEnum.LAST_MODIFIER);
1113                     result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdgeRes));
1114                 } else {
1115                     result = Either.left(modifierVertex);
1116                 }
1117             }
1118         } else {
1119             result = Either.left(ownerVertex);
1120         }
1121         return result;
1122     }
1123
1124     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForCheckin(String toscaElementId, String modifierId, String ownerId) {
1125         Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGetParameters = new HashMap<>();
1126         verticesToGetParameters.put(toscaElementId, new ImmutablePair<>(GraphPropertyEnum.UNIQUE_ID, JsonParseFlagEnum.ParseMetadata));
1127         verticesToGetParameters.put(modifierId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1128         verticesToGetParameters.put(ownerId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1129         return verticesToGetParameters;
1130     }
1131
1132     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForRequestCertification(String toscaElementId, String modifierId, String ownerId) {
1133         Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> verticesToGetParameters = new HashMap<>();
1134         verticesToGetParameters.put(toscaElementId, new ImmutablePair<>(GraphPropertyEnum.UNIQUE_ID, JsonParseFlagEnum.ParseAll));
1135         verticesToGetParameters.put(modifierId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1136         verticesToGetParameters.put(ownerId, new ImmutablePair<>(GraphPropertyEnum.USERID, JsonParseFlagEnum.NoParse));
1137         return verticesToGetParameters;
1138     }
1139
1140     private Map<String, ImmutablePair<GraphPropertyEnum, JsonParseFlagEnum>> prepareParametersToGetVerticesForCheckout(String toscaElementId, String modifierId, String ownerId) {
1141         //Implementation is currently identical
1142         return prepareParametersToGetVerticesForRequestCertification(toscaElementId,modifierId, ownerId);
1143     }
1144
1145     private String getNextCertifiedVersion(String version) {
1146         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1147         Integer nextMajorVersion = Integer.parseInt(versionParts[0]) + 1;
1148         return nextMajorVersion + VERSION_DELIMITER + "0";
1149     }
1150
1151     private String getNextVersion(String currVersion) {
1152         String[] versionParts = currVersion.split(VERSION_DELIMITER_REGEXP);
1153         Integer minorVersion = Integer.parseInt(versionParts[1]) + 1;
1154         return versionParts[0] + VERSION_DELIMITER + minorVersion;
1155     }
1156
1157     private Integer getMinorVersion(String version) {
1158         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1159         return Integer.parseInt(versionParts[1]);
1160     }
1161
1162     private Integer getMajorVersion(String version) {
1163         String[] versionParts = version.split(VERSION_DELIMITER_REGEXP);
1164         return Integer.parseInt(versionParts[0]);
1165     }
1166
1167     private boolean isFirstCheckoutAfterCertification(String version) {
1168         return (Integer.parseInt(version.split(VERSION_DELIMITER_REGEXP)[0]) != 0 && Integer.parseInt(version.split(VERSION_DELIMITER_REGEXP)[1]) == 1);
1169     }
1170
1171     public Either<ToscaElement, StorageOperationStatus> forceCerificationOfToscaElement(String toscaElementId, String modifierId, String ownerId, String currVersion) {
1172         Either<GraphVertex, StorageOperationStatus> resultUpdate = null;
1173         Either<ToscaElement, StorageOperationStatus> result = null;
1174         GraphVertex toscaElement = null;
1175         GraphVertex modifier = null;
1176         GraphVertex owner;
1177         try {
1178             Either<Map<String, GraphVertex>, JanusGraphOperationStatus> getVerticesRes = janusGraphDao
1179                 .getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId));
1180             if (getVerticesRes.isRight()) {
1181                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
1182                 result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getVerticesRes.right().value()));
1183             }
1184             if (result == null) {
1185                 toscaElement = getVerticesRes.left().value().get(toscaElementId);
1186                 modifier = getVerticesRes.left().value().get(modifierId);
1187                 owner = getVerticesRes.left().value().get(ownerId);
1188
1189                 StorageOperationStatus status = handleRelationsUponForceCertification(toscaElement, modifier, owner);
1190                 if (status != StorageOperationStatus.OK) {
1191                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to handle relations on certification request for tosca element {}. Status is {}. ", toscaElement.getUniqueId(), status);
1192                 }
1193             }
1194             if (result == null) {
1195                 LifecycleStateEnum nextState = LifecycleStateEnum.CERTIFIED;
1196
1197                 toscaElement.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
1198                 toscaElement.addMetadataProperty(GraphPropertyEnum.VERSION, getNextCertifiedVersion(currVersion));
1199
1200                 resultUpdate = updateToscaElementVertexMetadataPropertiesAndJson(toscaElement);
1201                 if (resultUpdate.isRight()) {
1202                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to set lifecycle for tosca elememt {} to state {}, error: {}", toscaElement.getUniqueId(), nextState, resultUpdate.right().value());
1203                     result = Either.right(resultUpdate.right().value());
1204                 }
1205             }
1206             if (result == null) {
1207                 ToscaElementOperation operation = getToscaElementOperation(toscaElement.getLabel());
1208                 result = operation.getToscaElement(toscaElement.getUniqueId());
1209             }
1210             return result;
1211
1212         } catch (Exception e) {
1213             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during request certification tosca element {}. {}", toscaElementId, e.getMessage());
1214         }
1215         return result;
1216     }
1217
1218     private StorageOperationStatus handleRelationsUponForceCertification(GraphVertex toscaElement, GraphVertex modifier, GraphVertex owner) {
1219
1220         StorageOperationStatus result = null;
1221         JanusGraphOperationStatus status = janusGraphDao
1222             .replaceEdgeLabel(owner.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE);
1223         if (status != JanusGraphOperationStatus.OK) {
1224             result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1225         }
1226         if (result == null) {
1227             Map<EdgePropertyEnum, Object> properties = new EnumMap<>(EdgePropertyEnum.class);
1228             properties.put(EdgePropertyEnum.STATE, LifecycleStateEnum.CERTIFIED);
1229             status = janusGraphDao
1230                 .createEdge(modifier, toscaElement, EdgeLabelEnum.STATE, properties);
1231             if (status != JanusGraphOperationStatus.OK) {
1232                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "failed to create edge. Status is {}", status);
1233                 result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
1234             }
1235         }
1236         if (result == null) {
1237             result = StorageOperationStatus.OK;
1238         }
1239         return result;
1240     }
1241
1242     private StorageOperationStatus updateEdgeToCatalogRootByUndoCheckout(JanusGraphVertex preV, GraphVertex curV) {
1243         if (preV == null) {
1244             return updateEdgeToCatalogRoot(null, curV);
1245         }
1246         String uniqueIdPreVer = (String) janusGraphDao
1247             .getProperty((JanusGraphVertex) preV, GraphPropertyEnum.UNIQUE_ID.getProperty());
1248         LifecycleStateEnum state = LifecycleStateEnum.findState((String) janusGraphDao
1249             .getProperty(preV, GraphPropertyEnum.STATE.getProperty()));
1250         if (state == LifecycleStateEnum.CERTIFIED) {
1251             return updateEdgeToCatalogRoot(null, curV);
1252         }
1253         return janusGraphDao.getVertexById(uniqueIdPreVer)
1254                 .either(l -> updateEdgeToCatalogRoot(l, curV),
1255                         DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
1256     }
1257
1258     private StorageOperationStatus updateEdgeToCatalogRoot(GraphVertex newVersionV, GraphVertex prevVersionV) {
1259         Either<GraphVertex, JanusGraphOperationStatus> catalog = janusGraphDao.getVertexByLabel(VertexTypeEnum.CATALOG_ROOT);
1260         if (catalog.isRight()) {
1261             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch catalog vertex. error {}", catalog.right().value());
1262             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(catalog.right().value());
1263         }
1264         GraphVertex catalogV = catalog.left().value();
1265         if (newVersionV != null) {
1266             Boolean isAbstract = (Boolean) newVersionV.getMetadataProperty(GraphPropertyEnum.IS_ABSTRACT);
1267                         
1268                         if ( isAbstract == null || !isAbstract ) {
1269                 // create new vertex
1270                 JanusGraphOperationStatus
1271                     result = janusGraphDao
1272                     .createEdge(catalogV, newVersionV, EdgeLabelEnum.CATALOG_ELEMENT, null);
1273                 if (result != JanusGraphOperationStatus.OK) {
1274                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create edge from {} to catalog vertex. error {}", newVersionV.getUniqueId(), result);
1275                     return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(result);
1276                 }
1277             }
1278         }
1279         if (prevVersionV != null) {
1280             Boolean isAbstract = (Boolean) prevVersionV.getMetadataProperty(GraphPropertyEnum.IS_ABSTRACT);
1281             if (isAbstract == null || !isAbstract) {
1282                 // if prev == null -> new resource was added
1283                 Either<Edge, JanusGraphOperationStatus> deleteResult = janusGraphDao
1284                     .deleteEdge(catalogV, prevVersionV, EdgeLabelEnum.CATALOG_ELEMENT);
1285                 if (deleteResult.isRight()) {
1286                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete edge from {} to catalog vertex. error {}", prevVersionV.getUniqueId(), deleteResult.right().value());
1287                     return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(deleteResult.right().value());
1288                 }
1289             }
1290         }
1291         return StorageOperationStatus.OK;
1292     }
1293 }