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