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