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