Upgrade SDC from Titan to Janus Graph
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / ArtifactOperation.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.operations.impl;
22
23 import org.janusgraph.core.JanusGraph;
24 import org.janusgraph.core.JanusGraphVertex;
25 import fj.data.Either;
26 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import org.apache.tinkerpop.gremlin.structure.Direction;
28 import org.apache.tinkerpop.gremlin.structure.Edge;
29 import org.apache.tinkerpop.gremlin.structure.Vertex;
30 import org.openecomp.sdc.be.config.BeEcompErrorManager;
31 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
32 import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
33 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
34 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
35 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
36 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
37 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
38 import org.openecomp.sdc.be.dao.neo4j.GraphEdgePropertiesDictionary;
39 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
40 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
41 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
42 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
43 import org.openecomp.sdc.be.model.ArtifactDefinition;
44 import org.openecomp.sdc.be.model.HeatParameterDefinition;
45 import org.openecomp.sdc.be.model.operations.api.IArtifactOperation;
46 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
47 import org.openecomp.sdc.be.resources.data.ArtifactData;
48 import org.openecomp.sdc.be.resources.data.HeatParameterData;
49 import org.openecomp.sdc.be.resources.data.HeatParameterValueData;
50 import org.openecomp.sdc.be.resources.data.UniqueIdData;
51 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
52 import org.openecomp.sdc.common.log.wrappers.Logger;
53 import org.slf4j.MDC;
54 import org.springframework.stereotype.Component;
55
56 import java.util.*;
57
58 @Component("artifact-operation")
59 public class ArtifactOperation implements IArtifactOperation {
60
61     private static final String THE_RETURNED_ARTIFACT_DEFINTION_IS = "The returned ArtifactDefintion is {}";
62
63         @javax.annotation.Resource
64     private JanusGraphGenericDao janusGraphGenericDao;
65
66     @javax.annotation.Resource
67     private HeatParametersOperation heatParametersOperation;
68
69     @javax.annotation.Resource
70     private GroupOperation groupOperation;
71     @javax.annotation.Resource
72     private GroupInstanceOperation groupInstanceOperation;
73
74     private static final Logger log = Logger.getLogger(ArtifactOperation.class.getName());
75
76     public ArtifactOperation() {
77         super();
78     }
79
80     public JanusGraphGenericDao getJanusGraphGenericDao() {
81         return janusGraphGenericDao;
82     }
83
84     public void setJanusGraphGenericDao(JanusGraphGenericDao janusGraphGenericDao) {
85         this.janusGraphGenericDao = janusGraphGenericDao;
86     }
87
88     public HeatParametersOperation getHeatParametersOperation() {
89         return heatParametersOperation;
90     }
91
92     public void setHeatParametersOperation(HeatParametersOperation heatParametersOperation) {
93         this.heatParametersOperation = heatParametersOperation;
94     }
95
96     @Override
97     public Either<ArtifactDefinition, StorageOperationStatus> addArifactToComponent(ArtifactDefinition artifactInfo, String parentId, NodeTypeEnum type, boolean failIfExist, boolean inTransaction) {
98
99         Either<ArtifactData, StorageOperationStatus> status = addArtifactToGraph(artifactInfo, parentId, type, failIfExist);
100
101         if (status.isRight()) {
102             if (!inTransaction) {
103                 janusGraphGenericDao.rollback();
104             }
105             log.debug("Failed to add artifact {} to {} {}", artifactInfo.getArtifactName(), type , parentId);
106             return Either.right(status.right().value());
107         } else {
108             if (!inTransaction) {
109                 janusGraphGenericDao.commit();
110             }
111             ArtifactData artifactData = status.left().value();
112
113             ArtifactDefinition artifactDefResult = convertArtifactDataToArtifactDefinition(artifactData);
114
115             log.debug(THE_RETURNED_ARTIFACT_DEFINTION_IS, artifactDefResult);
116             return Either.left(artifactDefResult);
117         }
118
119     }
120
121     @Override
122     public StorageOperationStatus addArifactToComponent(ArtifactDefinition artifactInfo, String parentId, NodeTypeEnum type, boolean failIfExist, JanusGraphVertex parentVertex) {
123
124         StorageOperationStatus status = addArtifactToGraph(artifactInfo, parentId, type, failIfExist, parentVertex);
125
126         if (status.equals(StorageOperationStatus.OK)) {
127             log.debug("Failed to add artifact {} {} to {}", artifactInfo.getArtifactName(), type, parentId);
128         }
129         return status;
130     }
131
132     private StorageOperationStatus addArtifactToGraph(ArtifactDefinition artifactInfo, String id, NodeTypeEnum type, boolean failIfexist, JanusGraphVertex parentVertex) {
133
134         if (artifactInfo.getUniqueId() == null || artifactInfo.getUniqueId().isEmpty()) {
135             String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(id, artifactInfo.getArtifactLabel());
136             artifactInfo.setUniqueId(uniqueId);
137         }
138
139         if (!validateParentType(type)) {
140             return StorageOperationStatus.GENERAL_ERROR;
141         }
142
143         ArtifactData artifactData = new ArtifactData(artifactInfo);
144
145         Either<JanusGraphVertex, JanusGraphOperationStatus> existArtifact = janusGraphGenericDao
146             .getVertexByProperty(artifactData.getUniqueIdKey(), artifactData.getUniqueId());
147         if (existArtifact.isRight()) {
148             if (existArtifact.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
149                 // create new node
150                 log.debug("Before adding artifact to graph {}", artifactData);
151                 if (artifactData.getArtifactDataDefinition().getArtifactUUID() == null || artifactData.getArtifactDataDefinition().getArtifactUUID().isEmpty())
152                     updateUUID(artifactData.getArtifactDataDefinition(), null, artifactData.getArtifactDataDefinition().getArtifactVersion());
153                 Either<JanusGraphVertex, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(artifactData);
154
155                 if (createNodeResult.isRight()) {
156                     JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
157                     log.debug("Failed to add artifact {} to graph. status is {}", artifactData.getArtifactDataDefinition().getArtifactName(), operationStatus);
158                     BeEcompErrorManager.getInstance().logBeFailedCreateNodeError("Add artifact", artifactData.getArtifactDataDefinition().getArtifactName(), String.valueOf(operationStatus));
159                     return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus);
160                 }
161
162                 // add heat parameters
163                 if (artifactInfo.getHeatParameters() != null && !artifactInfo.getHeatParameters().isEmpty() && !artifactInfo.getArtifactType().equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
164                     StorageOperationStatus addPropertiesStatus = heatParametersOperation.addPropertiesToGraph(artifactInfo.getListHeatParameters(), artifactData.getUniqueId().toString(), NodeTypeEnum.ArtifactRef);
165                     if (addPropertiesStatus != StorageOperationStatus.OK) {
166                         log.debug("Failed to create heat parameters on graph for artifact {}", artifactInfo.getArtifactName());
167                         return addPropertiesStatus;
168                     }
169                 }
170
171             } else {
172                 log.debug("Failed to check existance of artifact in graph for id {}", artifactData.getUniqueId());
173                 return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(existArtifact.right().value());
174             }
175         } else if (failIfexist) {
176             log.debug("Artifact {} already exist", artifactData.getUniqueId());
177             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ALREADY_EXIST);
178         }
179
180         // save logical artifact ref name on edge as property
181         Map<String, Object> properties = new HashMap<>();
182         properties.put(GraphEdgePropertiesDictionary.NAME.getProperty(), artifactInfo.getArtifactLabel());
183         if (artifactInfo.getArtifactGroupType() != null)
184             properties.put(GraphEdgePropertiesDictionary.GROUP_TYPE.getProperty(), artifactInfo.getArtifactGroupType().getType());
185         JanusGraphOperationStatus relation = janusGraphGenericDao
186             .createEdge(parentVertex, artifactData, GraphEdgeLabels.ARTIFACT_REF, properties);
187         if (!relation.equals(JanusGraphOperationStatus.OK)) {
188             log.debug("Failed to create relation in graph for id {} to new artifact", id);
189             return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(relation);
190         }
191
192         return StorageOperationStatus.OK;
193     }
194
195     private Either<ArtifactData, StorageOperationStatus> addArtifactToGraph(ArtifactDefinition artifactInfo, String id, NodeTypeEnum type, boolean failIfexist) {
196
197         if (artifactInfo.getUniqueId() == null || artifactInfo.getUniqueId().isEmpty()) {
198             String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(id, artifactInfo.getArtifactLabel());
199             artifactInfo.setUniqueId(uniqueId);
200         }
201
202         if (!validateParentType(type)) {
203             return Either.right(StorageOperationStatus.GENERAL_ERROR);
204         }
205
206         ArtifactData artifactData = new ArtifactData(artifactInfo);
207
208         Either<ArtifactData, JanusGraphOperationStatus> existArtifact = janusGraphGenericDao
209             .getNode(artifactData.getUniqueIdKey(), artifactData.getUniqueId(), ArtifactData.class);
210         if (existArtifact.isRight()) {
211             if (existArtifact.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
212                 // create new node
213                 log.debug("Before adding artifact to graph {}" , artifactData);
214                 if (artifactData.getArtifactDataDefinition().getArtifactUUID() == null || artifactData.getArtifactDataDefinition().getArtifactUUID().isEmpty())
215                     updateUUID(artifactData.getArtifactDataDefinition(), null, artifactData.getArtifactDataDefinition().getArtifactVersion());
216                 Either<ArtifactData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao
217                     .createNode(artifactData, ArtifactData.class);
218                 log.debug("After adding artifact to graph {}", artifactData);
219
220                 if (createNodeResult.isRight()) {
221                     JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
222                     log.debug("Failed to add artifact {} to graph. status is {}", artifactData.getArtifactDataDefinition().getArtifactName(), operationStatus);
223                     BeEcompErrorManager.getInstance().logBeFailedCreateNodeError("Add artifact", artifactData.getArtifactDataDefinition().getArtifactName(), String.valueOf(operationStatus));
224                     return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus));
225                 }
226                 artifactData = createNodeResult.left().value();
227
228                 // add heat parameters
229                 if (artifactInfo.getHeatParameters() != null && !artifactInfo.getHeatParameters().isEmpty() && !artifactInfo.getArtifactType().equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
230                     StorageOperationStatus addPropertiesStatus = heatParametersOperation.addPropertiesToGraph(artifactInfo.getListHeatParameters(), artifactData.getUniqueId().toString(), NodeTypeEnum.ArtifactRef);
231                     if (addPropertiesStatus != StorageOperationStatus.OK) {
232                         log.debug("Failed to create heat parameters on graph for artifact {}", artifactInfo.getArtifactName());
233                         return Either.right(addPropertiesStatus);
234                     }
235                 }
236
237             } else {
238                 log.debug("Failed to check existance of artifact in graph for id {}", artifactData.getUniqueId());
239                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(existArtifact.right().value()));
240             }
241         } else if (failIfexist) {
242             log.debug("Artifact {} already exist", artifactData.getUniqueId());
243             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
244                 JanusGraphOperationStatus.ALREADY_EXIST));
245         } else {
246             artifactData = existArtifact.left().value();
247         }
248
249         UniqueIdData parent = new UniqueIdData(type, id);
250
251         // save logical artifact ref name on edge as property
252         Map<String, Object> properties = new HashMap<>();
253         properties.put(GraphEdgePropertiesDictionary.NAME.getProperty(), artifactInfo.getArtifactLabel());
254         if (artifactInfo.getArtifactGroupType() != null)
255             properties.put(GraphEdgePropertiesDictionary.GROUP_TYPE.getProperty(), artifactInfo.getArtifactGroupType().getType());
256         Either<GraphRelation, JanusGraphOperationStatus> relation = janusGraphGenericDao
257             .createRelation(parent, artifactData, GraphEdgeLabels.ARTIFACT_REF, properties);
258         if (relation.isRight()) {
259             log.debug("Failed to create relation in graph fro id {} to new artifact", id);
260             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(relation.right().value()));
261         }
262
263         return Either.left(artifactData);
264     }
265
266     private boolean validateParentType(NodeTypeEnum type) {
267         boolean isValid = false;
268         switch (type) {
269         case Resource:
270         case InterfaceOperation:
271         case Service:
272         case ResourceInstance:
273             isValid = true;
274             break;
275         default:
276             log.debug("Not supported node type for artifact relation : {} ", type);
277         }
278         return isValid;
279     }
280
281
282     protected ArtifactDefinition convertArtifactDataToArtifactDefinition(ArtifactData artifactDefResult) {
283         log.debug("The object returned after create property is {}" ,artifactDefResult);
284
285         ArtifactDefinition propertyDefResult = new ArtifactDefinition(artifactDefResult.getArtifactDataDefinition());
286         List<HeatParameterDefinition> parameters = new ArrayList<>();
287         StorageOperationStatus heatParametersOfNode = heatParametersOperation.getHeatParametersOfNode(NodeTypeEnum.ArtifactRef, artifactDefResult.getUniqueId().toString(), parameters);
288         if ((heatParametersOfNode.equals(StorageOperationStatus.OK)) && !parameters.isEmpty()) {
289             propertyDefResult.setListHeatParameters(parameters);
290         }
291         return propertyDefResult;
292     }
293
294     @Override
295     public Either<ArtifactDefinition, StorageOperationStatus> updateArifactOnResource(ArtifactDefinition artifactInfo, String id, String artifactId, NodeTypeEnum type, boolean inTransaction) {
296         Either<ArtifactData, StorageOperationStatus> status = updateArtifactOnGraph(artifactInfo, artifactId, type, id);
297
298         if (status.isRight()) {
299             if (!inTransaction) {
300                 janusGraphGenericDao.rollback();
301             }
302             log.debug("Failed to update artifact {} of {} {}. status is {}", artifactId, type.getName(), id, status.right().value());
303             BeEcompErrorManager.getInstance().logBeFailedUpdateNodeError("Update Artifact", artifactId, String.valueOf(status.right().value()));
304             return Either.right(status.right().value());
305         } else {
306             if (!inTransaction) {
307                 janusGraphGenericDao.commit();
308             }
309             ArtifactData artifactData = status.left().value();
310
311             ArtifactDefinition artifactDefResult = convertArtifactDataToArtifactDefinition(artifactData);
312             log.debug(THE_RETURNED_ARTIFACT_DEFINTION_IS, artifactDefResult);
313             return Either.left(artifactDefResult);
314         }
315     }
316
317     @Override
318     public Either<ArtifactDefinition, StorageOperationStatus> removeArifactFromResource(String id, String artifactId, NodeTypeEnum type, boolean deleteMandatoryArtifact, boolean inTransaction) {
319         Either<ArtifactData, StorageOperationStatus> status = removeArtifactOnGraph(id, artifactId, type, deleteMandatoryArtifact);
320
321         if (status.isRight()) {
322             if (!inTransaction) {
323                 janusGraphGenericDao.rollback();
324             }
325             log.debug("Failed to delete artifact {} of resource {}", artifactId, id);
326
327             BeEcompErrorManager.getInstance().logBeFailedDeleteNodeError("Delete Artifact", artifactId, String.valueOf(status.right().value()));
328             return Either.right(status.right().value());
329         } else {
330             if (!inTransaction) {
331                 janusGraphGenericDao.commit();
332             }
333             ArtifactData artifactData = status.left().value();
334
335             ArtifactDefinition artifactDefResult = convertArtifactDataToArtifactDefinition(artifactData);
336             log.debug(THE_RETURNED_ARTIFACT_DEFINTION_IS , artifactDefResult);
337             return Either.left(artifactDefResult);
338         }
339     }
340
341     @SuppressWarnings("null")
342     private Either<ArtifactData, StorageOperationStatus> updateArtifactOnGraph(ArtifactDefinition artifactInfo, String artifactId, NodeTypeEnum type, String id) {
343
344         Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphGenericDao.getGraph();
345         if (graph.isRight()) {
346             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graph.right().value()));
347         }
348
349         JanusGraph tGraph = graph.left().value();
350
351         @SuppressWarnings("unchecked")
352         Iterable<JanusGraphVertex> verticesArtifact = tGraph.query().has(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ArtifactRef), artifactId).vertices();
353         Iterator<JanusGraphVertex> iterator = verticesArtifact.iterator();
354         if (!iterator.hasNext()) {
355             log.debug("No artifact node for id = {}", artifactId);
356             return Either.right(StorageOperationStatus.NOT_FOUND);
357         }
358         JanusGraphVertex artifactV = iterator.next();
359
360         Iterator<Edge> iterEdge = artifactV.edges(Direction.IN, GraphEdgeLabels.ARTIFACT_REF.getProperty());
361
362         int edgeCount = 0;
363         Edge edgeFromTo = null;
364         while (iterEdge.hasNext()) {
365             Edge edge = iterEdge.next();
366             Vertex vertexFrom = edge.outVertex();
367             String vertexId = vertexFrom.value(UniqueIdBuilder.getKeyByNodeType(type));
368             if (id.equals(vertexId)) {
369                 edgeFromTo = edge;
370             }
371             ++edgeCount;
372         }
373
374         if (isNeedUpdateHeatTime(artifactInfo)) {
375             artifactInfo.setHeatParamsUpdateDate(System.currentTimeMillis());
376         }
377
378         ArtifactData artifactData = new ArtifactData(artifactInfo);
379         if (edgeFromTo == null) {
380             log.debug("No relation between artifact  = {} and node with id = {}", artifactId, id);
381             return Either.right(StorageOperationStatus.GENERAL_ERROR);
382         }
383
384         Either<Boolean, StorageOperationStatus> setRelevantHeatParamIdRes = null;
385         if (edgeCount > 1) {
386             // need to remove relation, create new node
387             log.debug("artifactRef have more connection. Need to clone node");
388             log.debug("remove edge {}", edgeFromTo);
389             edgeFromTo.remove();
390             // update resource id in new artifact node
391             String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(id, artifactInfo.getArtifactLabel());
392             artifactInfo.setUniqueId(uniqueId);
393             // update UUID and artifact version
394             String oldChecksum = artifactV.valueOrNull(
395                 janusGraphGenericDao.getGraph().left().value().getPropertyKey(GraphPropertiesDictionary.ARTIFACT_CHECKSUM.getProperty()));
396             String oldVersion = artifactV.valueOrNull(
397                 janusGraphGenericDao.getGraph().left().value().getPropertyKey(GraphPropertiesDictionary.ARTIFACT_VERSION.getProperty()));
398             updateUUID(artifactInfo, oldChecksum, oldVersion);
399             log.debug("try to create new artifact ref node for id {}", uniqueId);
400             Either<ArtifactData, StorageOperationStatus> addedArtifactRes = addArtifactToGraph(artifactInfo, id, type, true);
401
402             if (addedArtifactRes.isLeft()) {
403                 // remove all relations between groups to the old artifact
404                 // add relation between the same groups to the new artifact
405                 StorageOperationStatus reassociateGroupsFromArtifact = groupOperation.dissociateAndAssociateGroupsFromArtifact(id, type, artifactId, addedArtifactRes.left().value(), true);
406                 if (reassociateGroupsFromArtifact != StorageOperationStatus.OK) {
407                     BeEcompErrorManager.getInstance().logInternalFlowError("UpdateArtifact", "Failed to reassociate groups to the new artifact", ErrorSeverity.ERROR);
408                     return Either.right(reassociateGroupsFromArtifact);
409                 }
410
411                 StorageOperationStatus reassociateGroupInstancesFromArtifact = groupInstanceOperation.dissociateAndAssociateGroupsInstanceFromArtifact(id, type, artifactId, addedArtifactRes.left().value());
412                 if (reassociateGroupInstancesFromArtifact != StorageOperationStatus.OK) {
413                     BeEcompErrorManager.getInstance().logInternalFlowError("UpdateArtifact", "Failed to reassociate group instances to the new artifact", ErrorSeverity.ERROR);
414                     return Either.right(reassociateGroupsFromArtifact);
415                 }
416
417                 // If artifact is heat env
418                 if (artifactInfo.getArtifactType().equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
419                     ArtifactData addedArtifact = addedArtifactRes.left().value();
420                     String newArtifactUniqueId = addedArtifact.getUniqueId();
421                     Either<HeatParameterValueData, StorageOperationStatus> updateResult = null;
422
423                     setRelevantHeatParamIdRes = setRelevantHeatParamId(artifactV, artifactInfo);
424                     if (setRelevantHeatParamIdRes.isRight()) {
425                         log.error("Failed to set relevant id to heat parameters for heat env artifact {}. Status is {}", artifactInfo.getUniqueId(), setRelevantHeatParamIdRes.right().value());
426                         return Either.right(setRelevantHeatParamIdRes.right().value());
427                     }
428                     for (HeatParameterDefinition heatEnvParam : artifactInfo.getListHeatParameters()) {
429                         updateResult = heatParametersOperation.updateHeatParameterValue(heatEnvParam, newArtifactUniqueId, id, artifactInfo.getArtifactLabel());
430                         if (updateResult.isRight()) {
431                             log.error("Failed to update heat parameter {}. Status is {}", heatEnvParam.getName(), updateResult.right().value());
432                             return Either.right(updateResult.right().value());
433                         }
434                     }
435
436                     Iterator<Edge> iterEdgeGeneratedFrom = artifactV.edges(Direction.OUT, GraphEdgeLabels.GENERATED_FROM.getProperty());
437
438                     if (!iterEdgeGeneratedFrom.hasNext()) {
439                         log.error("No heat artifact node for id = {}", artifactId);
440                         return Either.right(StorageOperationStatus.NOT_FOUND);
441                     }
442                     Edge edgeToHeat = iterEdgeGeneratedFrom.next();
443                     Vertex vertexIn = edgeToHeat.inVertex();
444                     String generatedFromArtifactId = vertexIn.value(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ArtifactRef));
445                     UniqueIdData generatedFromArtifactNode = new UniqueIdData(NodeTypeEnum.ArtifactRef, generatedFromArtifactId);
446                     Either<GraphRelation, JanusGraphOperationStatus> createRelationToGeneratedFromArtifactRes = janusGraphGenericDao
447                         .createRelation(addedArtifact, generatedFromArtifactNode, GraphEdgeLabels.GENERATED_FROM, null);
448                     if (createRelationToGeneratedFromArtifactRes.isRight()) {
449                         log.error("Failed to create relation from heat_env {} to heat {}", addedArtifact.getUniqueId(), generatedFromArtifactNode);
450                         return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createRelationToGeneratedFromArtifactRes.right().value()));
451                     }
452                 }
453             }
454             return addedArtifactRes;
455
456         } else {
457             if (edgeCount == 1) {
458                 String oldChecksum = artifactV.valueOrNull(
459                     janusGraphGenericDao.getGraph().left().value().getPropertyKey(GraphPropertiesDictionary.ARTIFACT_CHECKSUM.getProperty()));
460                 String oldVersion = artifactV.valueOrNull(
461                     janusGraphGenericDao.getGraph().left().value().getPropertyKey(GraphPropertiesDictionary.ARTIFACT_VERSION.getProperty()));
462                 updateUUID(artifactInfo, oldChecksum, oldVersion);
463                 // update exist
464                 Either<ArtifactData, JanusGraphOperationStatus> updatedArtifact = janusGraphGenericDao
465                     .updateNode(artifactData, ArtifactData.class);
466                 if (updatedArtifact.isRight()) {
467                     log.debug("failed to update artifact node for id {}", artifactData.getUniqueId());
468                     return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updatedArtifact.right().value()));
469                 }
470
471                 if (artifactInfo.getArtifactType().equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
472                     Either<HeatParameterValueData, StorageOperationStatus> updateResult = null;
473                     String artifactUniqueId = artifactInfo.getUniqueId();
474                     setRelevantHeatParamIdRes = setRelevantHeatParamId(artifactV, artifactInfo);
475                     if (setRelevantHeatParamIdRes.isRight()) {
476                         log.error("Failed to set relevant id to heat parameters for heat env artifact {}. Status is {}", artifactInfo.getUniqueId(), setRelevantHeatParamIdRes.right().value());
477                         return Either.right(setRelevantHeatParamIdRes.right().value());
478                     }
479                     for (HeatParameterDefinition heatEnvParam : artifactInfo.getListHeatParameters()) {
480                         updateResult = heatParametersOperation.updateHeatParameterValue(heatEnvParam, artifactUniqueId, id, artifactInfo.getArtifactLabel());
481                         if (updateResult.isRight()) {
482                             log.error("Failed to update heat parameter {}. Status is {}", heatEnvParam.getName(), updateResult.right().value());
483                             return Either.right(updateResult.right().value());
484                         }
485                     }
486                 } else {
487                     if (artifactData.getArtifactDataDefinition().getArtifactChecksum() == null) {
488                         // update heat parameters only if it is not heat env
489                         if (artifactInfo.getGeneratedFromId() == null) {
490                             StorageOperationStatus operationStatus = heatParametersOperation.updateHeatParameters(artifactInfo.getListHeatParameters());
491                             if (operationStatus != StorageOperationStatus.OK) {
492                                 return Either.right(operationStatus);
493                             }
494                         }
495                     } else {
496                         Either<List<HeatParameterDefinition>, StorageOperationStatus> deleteParameters = heatParametersOperation.deleteAllHeatParametersAssociatedToNode(NodeTypeEnum.ArtifactRef, artifactInfo.getUniqueId());
497                         if (deleteParameters.isRight()) {
498                             log.debug("failed to update heat parameters for artifact id {}", artifactData.getUniqueId());
499                             return Either.right(StorageOperationStatus.GENERAL_ERROR);
500                         }
501
502                         StorageOperationStatus addParameters = heatParametersOperation.addPropertiesToGraph(artifactInfo.getListHeatParameters(), artifactId, NodeTypeEnum.ArtifactRef);
503                         if (!addParameters.equals(StorageOperationStatus.OK)) {
504                             log.debug("failed to update heat parameters for artifact id {}", artifactData.getUniqueId());
505                             return Either.right(StorageOperationStatus.GENERAL_ERROR);
506                         }
507
508                     }
509                 }
510
511                 return Either.left(updatedArtifact.left().value());
512             } else {
513                 log.debug("No relevent edges for artifact = {}", artifactId);
514                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
515             }
516         }
517     }
518
519     private boolean isNeedUpdateHeatTime(ArtifactDefinition artifactInfo) {
520         if (artifactInfo.getArtifactType().equals(ArtifactTypeEnum.HEAT.getType()) || artifactInfo.getArtifactType().equals(ArtifactTypeEnum.HEAT_NET.getType()) || artifactInfo.getArtifactType().equals(ArtifactTypeEnum.HEAT_VOL.getType())) {
521             return true;
522         }
523         return false;
524     }
525
526     private Either<Boolean, StorageOperationStatus> setRelevantHeatParamId(JanusGraphVertex artifactV, ArtifactDefinition artifactInfo) {
527
528         Map<String, String> heatParametersHM = new HashMap<>();
529
530         Iterator<Edge> iterHeat = artifactV.edges(Direction.OUT, GraphEdgeLabels.GENERATED_FROM.getProperty());
531         if (!iterHeat.hasNext()) {
532             log.debug("No edges with label GENERATED_FROM for the node {}" , artifactInfo.getUniqueId());
533             return Either.right(StorageOperationStatus.NOT_FOUND);
534         }
535         Edge heat = iterHeat.next();
536         Vertex heatVertex = heat.inVertex();
537         String heatUniqueId = (String) heatVertex.value(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ArtifactRef));
538
539         Either<List<ImmutablePair<HeatParameterData, GraphEdge>>, JanusGraphOperationStatus> getHeatParametersRes = janusGraphGenericDao
540             .getChildrenNodes(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), heatUniqueId, GraphEdgeLabels.HEAT_PARAMETER,
541                 NodeTypeEnum.HeatParameter, HeatParameterData.class);
542         if (getHeatParametersRes.isRight()) {
543             log.debug("No heat parameters for heat artifact {}", heatUniqueId);
544             return Either.right(StorageOperationStatus.NOT_FOUND);
545         }
546         List<ImmutablePair<HeatParameterData, GraphEdge>> heatParameters = getHeatParametersRes.left().value();
547         if (heatParameters == null) {
548             log.debug("No heat parameters for heat artifact {}", heatUniqueId);
549             return Either.right(StorageOperationStatus.NOT_FOUND);
550         }
551         for (ImmutablePair<HeatParameterData, GraphEdge> heatParamEdge : heatParameters) {
552             HeatParameterData heatParam = heatParamEdge.getLeft();
553             heatParametersHM.put(heatParam.getName(), (String) heatParam.getUniqueId());
554         }
555         String curName = null;
556         for (HeatParameterDefinition heatEnvParam : artifactInfo.getListHeatParameters()) {
557             curName = heatEnvParam.getName();
558             if (heatParametersHM.containsKey(curName)) {
559                 heatEnvParam.setUniqueId(heatParametersHM.get(curName));
560             }
561         }
562         return Either.left(true);
563     }
564
565     private Either<ArtifactData, StorageOperationStatus> removeArtifactOnGraph(String id, String artifactId, NodeTypeEnum type, boolean deleteMandatoryArtifact) {
566         Either<JanusGraph, StorageOperationStatus> graph = janusGraphGenericDao.getGraph()
567                 .right()
568                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
569         if (graph.isRight()) {
570             return Either.right(graph.right().value());
571         }
572
573         JanusGraph tGraph = graph.left().value();
574         Either<ArtifactData, StorageOperationStatus> artifactData = janusGraphGenericDao
575             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ArtifactRef), artifactId, ArtifactData.class)
576                 .right()
577                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
578         if (artifactData.isRight()) {
579             log.debug("Failed to retrieve  artifact for id = {}", artifactId);
580             return Either.right(artifactData.right().value());
581         }
582         ArtifactDataDefinition artifactDefinition = artifactData.left().value().getArtifactDataDefinition();
583         boolean isMandatory = false;
584         if ((artifactDefinition.getMandatory() || artifactDefinition.getServiceApi()) && !deleteMandatoryArtifact) {
585             isMandatory = true;
586         }
587
588         @SuppressWarnings("unchecked")
589         Iterable<JanusGraphVertex> verticesArtifact = tGraph.query().has(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.ArtifactRef), artifactId).vertices();
590         Iterator<JanusGraphVertex> iterator = verticesArtifact.iterator();
591         if (!iterator.hasNext()) {
592             log.debug("No artifact node for id = {}", artifactId);
593             return Either.right(StorageOperationStatus.NOT_FOUND);
594         }
595         Vertex artifactV = iterator.next();
596         Iterator<Edge> iterEdge = artifactV.edges(Direction.IN, GraphEdgeLabels.ARTIFACT_REF.getProperty());
597         int edgeCount = 0;
598         Edge edgeFromTo = null;
599         while (iterEdge.hasNext()) {
600             Edge edge = iterEdge.next();
601             Vertex vertexFrom = edge.outVertex();
602             String vertexId = vertexFrom.value(UniqueIdBuilder.getKeyByNodeType(type));
603             if (id.equals(vertexId)) {
604                 edgeFromTo = edge;
605             }
606             ++edgeCount;
607         }
608         if (edgeFromTo == null) {
609             log.debug("No relation between artifact  = {} and node with id = {}", artifactId, id);
610             return Either.right(StorageOperationStatus.GENERAL_ERROR);
611         }
612
613         // need to remove relation from resource/interface
614
615         log.debug("remove edge {}", edgeFromTo);
616         if (!isMandatory || (isMandatory && edgeCount > 1)) {
617             edgeFromTo.remove();
618         }
619
620         // delete edges from all groups under the component id which related to
621         // this artifact.
622         // Also in case it is a mandatory artifact.
623         Either<List<GraphRelation>, StorageOperationStatus> dissociateAllGroups = groupOperation.dissociateAllGroupsFromArtifactOnGraph(id, type, artifactId);
624         if (dissociateAllGroups.isRight()) {
625             StorageOperationStatus status = dissociateAllGroups.right().value();
626             if (status != StorageOperationStatus.NOT_FOUND && status != StorageOperationStatus.OK) {
627                 return Either.right(status);
628             }
629         }
630
631         if (edgeCount == 1) {
632             // remove artifactRef node
633             log.debug("Remove artifactRef node from graph");
634             Either<List<HeatParameterDefinition>, StorageOperationStatus> deleteStatus = heatParametersOperation.deleteAllHeatParametersAssociatedToNode(NodeTypeEnum.ArtifactRef, artifactId);
635             if (deleteStatus.isRight()) {
636                 log.error("failed to delete heat parameters of artifact {}", artifactId);
637                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
638             }
639
640             StorageOperationStatus deleteValuesStatus = heatParametersOperation.deleteAllHeatValuesAssociatedToNode(NodeTypeEnum.ArtifactRef, artifactId);
641             if (!deleteValuesStatus.equals(StorageOperationStatus.OK)) {
642                 log.error("failed to delete heat values of artifact {}", artifactId);
643                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
644             }
645             if (!isMandatory) {
646                 artifactV.remove();
647             }
648         } else {
649             log.debug("artifactRef have more connection. ArtifactRef node will not be removed ");
650         }
651
652         return Either.left(artifactData.left().value());
653
654     }
655
656     /**
657      *
658      * @param parentId
659      * @param parentType
660      * @param inTransaction
661      * @return
662      */
663     public Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getArtifacts(String parentId, NodeTypeEnum parentType, boolean inTransaction) {
664         Either<Map<String, ArtifactDefinition>, StorageOperationStatus> result = null;
665         try {
666             Either<JanusGraph, JanusGraphOperationStatus> graph = janusGraphGenericDao.getGraph();
667             if (graph.isRight()) {
668                 log.debug("Failed to work with graph {}", graph.right().value());
669                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(graph.right().value()));
670             }
671             JanusGraph tGraph = graph.left().value();
672             @SuppressWarnings("unchecked")
673             Iterable<JanusGraphVertex> vertices = tGraph.query().has(UniqueIdBuilder.getKeyByNodeType(parentType), parentId).vertices();
674             if (vertices == null) {
675                 log.debug("No nodes for type {}  for id = {}", parentType, parentId);
676                 result = Either.right(StorageOperationStatus.NOT_FOUND);
677                 return result;
678             }
679             Iterator<JanusGraphVertex> iterator = vertices.iterator();
680
681             Map<String, ArtifactDefinition> artifactMap = new HashMap<>();
682             while (iterator.hasNext()) {
683                 Vertex vertex = iterator.next();
684                 Iterator<Edge> iteratorEdge = vertex.edges(Direction.OUT, GraphEdgeLabels.ARTIFACT_REF.getProperty());
685
686                 if (iteratorEdge != null) {
687
688                     while (iteratorEdge.hasNext()) {
689                         Edge edge = iteratorEdge.next();
690
691                         Vertex artifactV = edge.inVertex();
692
693                         Map<String, Object> properties = this.janusGraphGenericDao.getProperties(artifactV);
694                         ArtifactData artifact = GraphElementFactory.createElement(NodeTypeEnum.ArtifactRef.getName(), GraphElementTypeEnum.Node, properties, ArtifactData.class);
695                         if (artifact != null) {
696
697                             ArtifactDefinition artifactDefinition = new ArtifactDefinition(artifact.getArtifactDataDefinition());
698                             Iterator<Edge> edgesGeneratedFrom = artifactV.edges(Direction.OUT, GraphEdgeLabels.GENERATED_FROM.getProperty());
699                             if (edgesGeneratedFrom != null && edgesGeneratedFrom.hasNext()) {
700                                 JanusGraphVertex inVertex = (JanusGraphVertex) edgesGeneratedFrom.next().inVertex();
701                                 String artifactIdGeneratedFrom = (String) janusGraphGenericDao
702                                     .getProperty(inVertex, GraphPropertiesDictionary.UNIQUE_ID.getProperty());
703                                 artifactDefinition.setGeneratedFromId(artifactIdGeneratedFrom);
704                             }
705                             List<HeatParameterDefinition> heatParams = new ArrayList<>();
706                             StorageOperationStatus heatParametersStatus = heatParametersOperation.getHeatParametersOfNode(NodeTypeEnum.ArtifactRef, artifactDefinition.getUniqueId(), heatParams);
707                             if (!heatParametersStatus.equals(StorageOperationStatus.OK)) {
708                                 log.debug("failed to get heat parameters for node {}  {}", parentType.getName(), parentId);
709                                 return Either.right(heatParametersStatus);
710                             }
711                             if (!heatParams.isEmpty()) {
712                                 artifactDefinition.setListHeatParameters(heatParams);
713                             }
714                             artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition);
715                             log.debug("Artifact was added to list {}", artifact.getUniqueId());
716                         }
717                     }
718                 }
719             }
720             result = Either.left(artifactMap);
721             return result;
722         } finally {
723             if (!inTransaction) {
724                 if (result == null || result.isRight()) {
725                     this.janusGraphGenericDao.rollback();
726                 } else {
727                     this.janusGraphGenericDao.commit();
728                 }
729
730             }
731         }
732
733     }
734
735     private void updateUUID(ArtifactDataDefinition artifactData, String oldChecksum, String oldVesrion) {
736         if (oldVesrion == null || oldVesrion.isEmpty())
737             oldVesrion = "0";
738
739         String currentChecksum = artifactData.getArtifactChecksum();
740         if (oldChecksum == null || oldChecksum.isEmpty()) {
741             if (currentChecksum != null) {
742                 generateUUID(artifactData, oldVesrion);
743             }
744         } else if ((currentChecksum != null && !currentChecksum.isEmpty()) && !oldChecksum.equals(currentChecksum)) {
745             generateUUID(artifactData, oldVesrion);
746         }
747
748     }
749
750     private void generateUUID(ArtifactDataDefinition artifactData, String oldVesrion) {
751
752         UUID uuid = UUID.randomUUID();
753         artifactData.setArtifactUUID(uuid.toString());
754         MDC.put("serviceInstanceID", uuid.toString());
755         updateVersionAndDate(artifactData, oldVesrion);
756     }
757
758     private void updateVersionAndDate(ArtifactDataDefinition artifactData, String oldVesrion) {
759         long time = System.currentTimeMillis();
760         artifactData.setPayloadUpdateDate(time);
761         int newVersion = new Integer(oldVesrion).intValue();
762         newVersion++;
763         artifactData.setArtifactVersion(String.valueOf(newVersion));
764     }
765
766 }