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