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