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