re base code
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsontitan / operations / NodeTemplateOperation.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.jsontitan.operations;
22
23 import com.thinkaurelius.titan.core.TitanVertex;
24 import fj.data.Either;
25 import org.apache.commons.collections.CollectionUtils;
26 import org.apache.commons.collections.MapUtils;
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.apache.commons.lang3.tuple.Pair;
30 import org.apache.tinkerpop.gremlin.structure.Direction;
31 import org.apache.tinkerpop.gremlin.structure.Edge;
32 import org.openecomp.sdc.be.config.BeEcompErrorManager;
33 import org.openecomp.sdc.be.config.ConfigurationManager;
34 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
35 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
36 import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum;
37 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
38 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
39 import org.openecomp.sdc.be.dao.jsongraph.utils.JsonParserUtils;
40 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
41 import org.openecomp.sdc.be.datatypes.elements.*;
42 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
43 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
44 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
45 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
46 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
47 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
48 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
49 import org.openecomp.sdc.be.model.*;
50 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
51 import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate;
52 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
53 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
54 import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum;
55 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
56 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
57 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
58 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
59 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
60 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
61 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
62 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
63 import org.openecomp.sdc.common.log.wrappers.Logger;
64 import org.openecomp.sdc.common.util.ValidationUtils;
65
66 import java.io.IOException;
67 import java.util.*;
68 import java.util.Map.Entry;
69 import java.util.function.BiConsumer;
70 import java.util.function.BiPredicate;
71 import java.util.stream.Collectors;
72
73 @org.springframework.stereotype.Component("node-template-operation")
74 public class NodeTemplateOperation extends BaseOperation {
75     private static final String FAILED_TO_FETCH_CONTAINER_VERTEX_ERROR = "Failed to fetch container vertex {} error {}";
76         private static final String FAILED_TO_UPDATE_TOPOLOGY_TEMPLATE_WITH_NEW_COMPONENT_INSTANCE = "Failed to update topology template {} with new component instance {}. ";
77         private static final String ARTIFACT_PLACEHOLDER_TYPE = "type";
78     private static final String ARTIFACT_PLACEHOLDER_DISPLAY_NAME = "displayName";
79     private static final Object ARTIFACT_PLACEHOLDER_DESCRIPTION = "description";
80     public static final String HEAT_ENV_NAME = "heatEnv";
81     public static final String HEAT_VF_ENV_NAME = "VfHeatEnv";
82     public static final String HEAT_ENV_SUFFIX = "env";
83     private static Integer defaultHeatTimeout;
84     public static final Integer NON_HEAT_TIMEOUT = 0;
85
86     private static final Logger log = Logger.getLogger(NodeTemplateOperation.class.getName());
87
88     public NodeTemplateOperation() {
89         defaultHeatTimeout = ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultHeatArtifactTimeoutMinutes();
90         if ((defaultHeatTimeout == null) || (defaultHeatTimeout < 1)) {
91             defaultHeatTimeout = 60;
92         }
93     }
94
95     public static Integer getDefaultHeatTimeout() {
96         return defaultHeatTimeout;
97     }
98
99     public Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> addComponentInstanceToTopologyTemplate(TopologyTemplate container, ToscaElement originToscaElement, String instanceNumberSuffix, ComponentInstance componentInstance,
100             boolean allowDeleted, User user) {
101
102         Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> result = null;
103         Either<TopologyTemplate, StorageOperationStatus> addComponentInstanceRes = null;
104         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Going to create component instance {} in component {}", componentInstance, container.getUniqueId());
105         ComponentInstanceDataDefinition componentInstanceData = null;
106         Either<String, StorageOperationStatus> newInstanceNameRes = null;
107
108         Either<GraphVertex, TitanOperationStatus> metadataVertex = titanDao.getVertexById(container.getUniqueId(), JsonParseFlagEnum.ParseJson);
109         if (metadataVertex.isRight()) {
110             TitanOperationStatus status = metadataVertex.right().value();
111             if (status == TitanOperationStatus.NOT_FOUND) {
112                 status = TitanOperationStatus.INVALID_ID;
113             }
114             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
115         }
116
117         if (result == null) {
118
119             newInstanceNameRes = buildValidateInstanceName(container, originToscaElement, componentInstance, instanceNumberSuffix);
120             if (newInstanceNameRes.isRight()) {
121                 result = Either.right(newInstanceNameRes.right().value());
122             }
123         }
124         if (result == null) {
125             componentInstanceData = buildComponentInstanceDataDefinition(componentInstance, container.getUniqueId(), newInstanceNameRes.left().value(), true, originToscaElement);
126
127             addComponentInstanceRes = addComponentInstanceToTopologyTemplate(container, originToscaElement, componentInstanceData, metadataVertex.left().value(), allowDeleted, user);
128
129             if (addComponentInstanceRes.isRight()) {
130                 StorageOperationStatus status = addComponentInstanceRes.right().value();
131                 if (status == StorageOperationStatus.NOT_FOUND) {
132                     status = StorageOperationStatus.INVALID_ID;
133                 }
134                 result = Either.right(status);
135             }
136             if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
137                 TopologyTemplate updatedContainer = addComponentInstanceRes.left().value();
138                 result = addServerCapAndReqToProxyServerInstance(updatedContainer, componentInstance, componentInstanceData);
139
140             }
141         }
142         if (result == null) {
143             result = Either.left(new ImmutablePair<>(addComponentInstanceRes.left().value(), componentInstanceData.getUniqueId()));
144         }
145         return result;
146     }
147
148     private Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> addServerCapAndReqToProxyServerInstance(TopologyTemplate updatedContainer, ComponentInstance componentInstance,
149
150             ComponentInstanceDataDefinition componentInstanceData) {
151
152         Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> result;
153
154         Map<String, MapListCapabilityDataDefinition> calcCap = updatedContainer.getCalculatedCapabilities();
155         Map<String, MapListRequirementDataDefinition> calcReg = updatedContainer.getCalculatedRequirements();
156         Map<String, MapCapabilityProperty> calcCapProp = updatedContainer.getCalculatedCapabilitiesProperties();
157
158         Map<String, List<CapabilityDefinition>> additionalCap = componentInstance.getCapabilities();
159         Map<String, List<RequirementDefinition>> additionalReq = componentInstance.getRequirements();
160
161         MapListCapabilityDataDefinition allCalculatedCap = calcCap == null || !calcCap.containsKey(componentInstanceData.getUniqueId()) ? new MapListCapabilityDataDefinition() : calcCap.get(componentInstanceData.getUniqueId());
162         /******** capability ****************************/
163         StorageOperationStatus status = deleteToscaDataDeepElementsBlockOfToscaElement(updatedContainer.getUniqueId(), EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, componentInstanceData.getUniqueId());
164         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
165             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove calculated capabilty  for instance {} in container {}. error {] ", componentInstanceData.getUniqueId(), updatedContainer.getUniqueId(), status);
166             return Either.right(status);
167         }
168
169         if (additionalCap != null && !additionalCap.isEmpty()) {
170
171             Map<String, ListCapabilityDataDefinition> serverCap = additionalCap.entrySet().stream()
172                     .collect(Collectors.toMap(Map.Entry::getKey, en -> new ListCapabilityDataDefinition(en.getValue().stream().map(CapabilityDataDefinition::new).collect(Collectors.toList()))));
173
174             serverCap.entrySet().forEach(entryPerType -> {
175                 entryPerType.getValue().getListToscaDataDefinition().forEach(cap -> {
176                     cap.addToPath(componentInstance.getUniqueId());
177                     allCalculatedCap.add(entryPerType.getKey(), cap);
178                 });
179             });
180
181             status = addToscaDataDeepElementsBlockToToscaElement(updatedContainer.getUniqueId(), EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, allCalculatedCap, componentInstance.getUniqueId());
182
183             /******** capability property ****************************/
184             status = deleteToscaDataDeepElementsBlockOfToscaElement(updatedContainer.getUniqueId(), EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, componentInstanceData.getUniqueId());
185             if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
186                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove calculated capabilty properties for instance {} in container {}. error {] ", componentInstanceData.getUniqueId(), updatedContainer.getUniqueId(), status);
187                 return Either.right(status);
188             }
189
190             MapCapabilityProperty allCalculatedCapProp = calcCapProp == null || !calcCapProp.containsKey(componentInstanceData.getUniqueId()) ? new MapCapabilityProperty() : calcCapProp.get(componentInstanceData.getUniqueId());
191
192             additionalCap.forEach(new BiConsumer<String, List<CapabilityDefinition>>() {
193                 @Override
194                 public void accept(String s, List<CapabilityDefinition> caps) {
195
196                     if (caps != null && !caps.isEmpty()) {
197
198                         MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition();
199
200                         for (CapabilityDefinition cap : caps) {
201                             List<ComponentInstanceProperty> capPrps = cap.getProperties();
202                             if (capPrps != null) {
203
204                                 for (ComponentInstanceProperty cip : capPrps) {
205                                     dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip));
206                                 }
207
208                                 StringBuffer sb = new StringBuffer(componentInstance.getUniqueId());
209                                 sb.append(ModelConverter.CAP_PROP_DELIM);
210
211                                 sb.append(cap.getOwnerId());
212
213                                 sb.append(ModelConverter.CAP_PROP_DELIM).append(s).append(ModelConverter.CAP_PROP_DELIM).append(cap.getName());
214                                 allCalculatedCapProp.put(sb.toString(), dataToCreate);
215                             }
216                         }
217
218                     }
219
220                 }
221             });
222
223             status = addToscaDataDeepElementsBlockToToscaElement(updatedContainer.getUniqueId(), EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, allCalculatedCapProp, componentInstance.getUniqueId());
224         }
225
226         /******** Requirements property ****************************/
227         if (additionalReq != null && !additionalReq.isEmpty()) {
228
229             MapListRequirementDataDefinition allCalculatedReq = calcReg == null || !calcReg.containsKey(componentInstanceData.getUniqueId()) ? new MapListRequirementDataDefinition() : calcReg.get(componentInstanceData.getUniqueId());
230             status = deleteToscaDataDeepElementsBlockOfToscaElement(updatedContainer.getUniqueId(), EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, componentInstanceData.getUniqueId());
231             if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
232                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove calculated Requirements for instance {} in container {}. error {] ", componentInstanceData.getUniqueId(), updatedContainer.getUniqueId(), status);
233                 return Either.right(status);
234             }
235
236             Map<String, ListRequirementDataDefinition> serverReq = additionalReq.entrySet().stream()
237                     .collect(Collectors.toMap(Map.Entry::getKey, en -> new ListRequirementDataDefinition(en.getValue().stream().map(RequirementDataDefinition::new).collect(Collectors.toList()))));
238
239             serverReq.entrySet().forEach(entryPerType -> {
240                 entryPerType.getValue().getListToscaDataDefinition().forEach(cap -> {
241                     cap.addToPath(componentInstance.getUniqueId());
242                     allCalculatedReq.add(entryPerType.getKey(), cap);
243                 });
244             });
245
246             status = addToscaDataDeepElementsBlockToToscaElement(updatedContainer.getUniqueId(), EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, allCalculatedReq, componentInstance.getUniqueId());
247
248         }
249
250         Either<ToscaElement, StorageOperationStatus> updatedComponentInstanceRes = topologyTemplateOperation.getToscaElement(updatedContainer.getUniqueId());
251         if (updatedComponentInstanceRes.isRight()) {
252             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch updated topology template {} with new component instance {}. ", updatedContainer.getName(), componentInstance.getName());
253             result = Either.right(updatedComponentInstanceRes.right().value());
254         }
255         result = Either.left(new ImmutablePair<>((TopologyTemplate) updatedComponentInstanceRes.left().value(), componentInstanceData.getUniqueId()));
256         return result;
257     }
258
259     private Either<String, StorageOperationStatus> buildValidateInstanceName(TopologyTemplate container, ToscaElement originToscaElement, ComponentInstance componentInstance, String instanceNumberSuffix) {
260
261         Either<String, StorageOperationStatus> result = null;
262         String instanceName = componentInstance.getName();
263         if (StringUtils.isEmpty(instanceName) || instanceName.equalsIgnoreCase(originToscaElement.getName()) || componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
264             instanceName = buildComponentInstanceName(instanceNumberSuffix, instanceName);
265         } else if (!isUniqueInstanceName(container, componentInstance.getName())) {
266             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create component instance with name {} on component container {}. The instance with the same name already exists. ", componentInstance.getName(), container.getName());
267             result = Either.right(StorageOperationStatus.ENTITY_ALREADY_EXISTS);
268         }
269         if (result == null) {
270             result = Either.left(instanceName);
271         }
272         return result;
273     }
274
275     public Either<TopologyTemplate, StorageOperationStatus> addComponentInstanceToTopologyTemplate(TopologyTemplate container, ToscaElement originToscaElement, ComponentInstanceDataDefinition componentInstance, GraphVertex metadataVertex,
276             boolean allowDeleted, User user) {
277
278         Either<TopologyTemplate, StorageOperationStatus> result = null;
279         Either<ToscaElement, StorageOperationStatus> updateContainerComponentRes = null;
280         String containerComponentId = container.getUniqueId();
281         CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to create component instance {} in component {}", componentInstance, containerComponentId);
282         String instOriginComponentId = componentInstance.getComponentUid();
283         Either<GraphVertex, TitanOperationStatus> updateElement = null;
284
285         Boolean isDeleted = (Boolean) originToscaElement.getMetadataValue(JsonPresentationFields.IS_DELETED);
286
287         if (!allowDeleted && (isDeleted != null) && isDeleted) {
288             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component {} is already deleted. Cannot add component instance", instOriginComponentId);
289             result = Either.right(StorageOperationStatus.INVALID_ID);
290         }
291         Boolean isArchived = originToscaElement.isArchived();
292         if ( isArchived != null && isArchived ){
293             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to create instance {}. Origin {} component is archived . ", componentInstance.getName(), originToscaElement.getName());
294             result = Either.right(StorageOperationStatus.COMPONENT_IS_ARCHIVED);
295         }
296
297         if (result == null) {
298             container.addComponentInstance(componentInstance);
299             metadataVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
300             topologyTemplateOperation.fillToscaElementVertexData(metadataVertex, container, JsonParseFlagEnum.ParseAll);
301             updateElement = titanDao.updateVertex(metadataVertex);
302             if (updateElement.isRight()) {
303                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_UPDATE_TOPOLOGY_TEMPLATE_WITH_NEW_COMPONENT_INSTANCE, container.getName(), componentInstance.getName());
304                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value()));
305             }
306         }
307         if (result == null) {
308             Either<GraphVertex, StorageOperationStatus> addToscaDataRes = addComponentInstanceToscaDataToContainerComponent(originToscaElement, componentInstance, updateElement.left().value(), user);
309             if (addToscaDataRes.isRight()) {
310                 result = Either.right(addToscaDataRes.right().value());
311             }
312         }
313         if (result == null) {
314             StorageOperationStatus createInstanceEdge = createInstanceEdge(metadataVertex, componentInstance);
315             result = createInstanceEdge == StorageOperationStatus.OK ? null : Either.right(createInstanceEdge);
316         }
317
318         if (result == null) {
319             updateContainerComponentRes = topologyTemplateOperation.getToscaElement(containerComponentId);
320             if (updateContainerComponentRes.isRight()) {
321                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch updated topology template {} with new component instance {}. ", container.getName(), componentInstance.getName());
322                 result = Either.right(updateContainerComponentRes.right().value());
323             }
324         }
325         if (result == null) {
326             result = Either.left((TopologyTemplate) updateContainerComponentRes.left().value());
327         }
328         return result;
329     }
330
331     public Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> updateComponentInstanceMetadataOfTopologyTemplate(TopologyTemplate container, ToscaElement originToscaElement, ComponentInstance componentInstance) {
332
333         Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> result = null;
334         Either<ToscaElement, StorageOperationStatus> updateContainerComponentRes = null;
335
336         String containerComponentId = container.getUniqueId();
337         CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update component instance metadata {} of container component {}", componentInstance, containerComponentId);
338         ComponentInstanceDataDefinition componentInstanceData = null;
339
340         Either<GraphVertex, TitanOperationStatus> metadataVertex = titanDao.getVertexById(container.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
341         if (metadataVertex.isRight()) {
342             TitanOperationStatus status = metadataVertex.right().value();
343             if (status == TitanOperationStatus.NOT_FOUND) {
344                 status = TitanOperationStatus.INVALID_ID;
345             }
346             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
347         }
348         if (result == null) {
349             componentInstanceData = buildComponentInstanceDataDefinition(componentInstance, container.getUniqueId(), componentInstance.getName(), false, originToscaElement);
350             container.addComponentInstance(componentInstanceData);
351             metadataVertex.left().value().setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
352             topologyTemplateOperation.fillToscaElementVertexData(metadataVertex.left().value(), container, JsonParseFlagEnum.ParseAll);
353             Either<GraphVertex, TitanOperationStatus> updateElement = titanDao.updateVertex(metadataVertex.left().value());
354             if (updateElement.isRight()) {
355                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_UPDATE_TOPOLOGY_TEMPLATE_WITH_NEW_COMPONENT_INSTANCE, container.getName(), componentInstance.getName());
356                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value()));
357             }
358         }
359         if (result == null) {
360             updateContainerComponentRes = topologyTemplateOperation.getToscaElement(containerComponentId);
361             if (updateContainerComponentRes.isRight()) {
362                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch updated topology template {} with updated component instance {}. ", container.getName(), componentInstance.getName());
363                 result = Either.right(updateContainerComponentRes.right().value());
364             }
365         }
366         if (result == null) {
367             result = Either.left(new ImmutablePair<>((TopologyTemplate) updateContainerComponentRes.left().value(), componentInstanceData.getUniqueId()));
368         }
369         return result;
370     }
371
372     public Either<TopologyTemplate, StorageOperationStatus> updateComponentInstanceMetadataOfTopologyTemplate(TopologyTemplate container, ComponentParametersView filter) {
373
374         Either<TopologyTemplate, StorageOperationStatus> result = null;
375         Either<ToscaElement, StorageOperationStatus> updateContainerComponentRes = null;
376
377         String containerComponentId = container.getUniqueId();
378         CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update component instance metadata  of container component {}", containerComponentId);
379
380         Either<GraphVertex, TitanOperationStatus> metadataVertex = titanDao.getVertexById(container.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
381         if (metadataVertex.isRight()) {
382             TitanOperationStatus status = metadataVertex.right().value();
383             if (status == TitanOperationStatus.NOT_FOUND) {
384                 status = TitanOperationStatus.INVALID_ID;
385             }
386             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
387         }
388         if (result == null) {
389             metadataVertex.left().value().setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
390             topologyTemplateOperation.fillToscaElementVertexData(metadataVertex.left().value(), container, JsonParseFlagEnum.ParseAll);
391             Either<GraphVertex, TitanOperationStatus> updateElement = titanDao.updateVertex(metadataVertex.left().value());
392             if (updateElement.isRight()) {
393                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update topology template {}. ", container.getName());
394                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value()));
395             }
396         }
397         if (result == null) {
398             updateContainerComponentRes = topologyTemplateOperation.getToscaElement(containerComponentId, filter);
399             if (updateContainerComponentRes.isRight()) {
400                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch updated topology template {}. ", container.getName());
401                 result = Either.right(updateContainerComponentRes.right().value());
402             }
403         }
404         if (result == null) {
405             result = Either.left((TopologyTemplate) updateContainerComponentRes.left().value());
406         }
407         return result;
408     }
409
410     public Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> deleteComponentInstanceFromTopologyTemplate(TopologyTemplate container, String componentInstanceId) {
411
412         Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> result = null;
413         Either<ToscaElement, StorageOperationStatus> updateContainerComponentRes = null;
414
415         String containerComponentId = container.getUniqueId();
416         CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update component instance metadata {} of container component {}", componentInstanceId, containerComponentId);
417
418         Either<GraphVertex, TitanOperationStatus> metadataVertex = titanDao.getVertexById(container.getUniqueId(), JsonParseFlagEnum.ParseMetadata);
419         if (metadataVertex.isRight()) {
420             TitanOperationStatus status = metadataVertex.right().value();
421             if (status == TitanOperationStatus.NOT_FOUND) {
422                 status = TitanOperationStatus.INVALID_ID;
423             }
424             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
425         }
426         GraphVertex containerV = null;
427         ComponentInstanceDataDefinition removedComponentInstance = null;
428         if (result == null) {
429             removedComponentInstance = container.getComponentInstances().remove(componentInstanceId);
430             containerV = metadataVertex.left().value();
431             StorageOperationStatus status = removeRelationsOfInstance(container, componentInstanceId, containerV);
432             if (status != StorageOperationStatus.OK) {
433                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete relation for component instance {} in container. error {}", componentInstanceId, container.getUniqueId(), status);
434                 result = Either.right(status);
435             }
436
437             containerV.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
438             topologyTemplateOperation.fillToscaElementVertexData(containerV, container, JsonParseFlagEnum.ParseAll);
439             Either<GraphVertex, TitanOperationStatus> updateElement = titanDao.updateVertex(containerV);
440             if (updateElement.isRight()) {
441                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_UPDATE_TOPOLOGY_TEMPLATE_WITH_NEW_COMPONENT_INSTANCE, container.getName(), componentInstanceId);
442                 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value()));
443             }
444         }
445         if (result == null) {
446             StorageOperationStatus status = deleteComponentInstanceToscaDataFromContainerComponent(containerV, componentInstanceId);
447             if (status != StorageOperationStatus.OK) {
448                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete data  for instance {} in container {}. error {] ", componentInstanceId, container.getUniqueId(), status);
449                 return Either.right(status);
450             }
451             ComponentInstance componentInstance = new ComponentInstance(removedComponentInstance);
452             StorageOperationStatus createInstanceEdge = removeInstanceEdge(containerV, componentInstance);
453             result = createInstanceEdge == StorageOperationStatus.OK ? null : Either.right(createInstanceEdge);
454         }
455         if (result == null) {
456             updateContainerComponentRes = topologyTemplateOperation.getToscaElement(containerComponentId);
457             if (updateContainerComponentRes.isRight()) {
458                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch updated topology template {} after deleting the component instance {}. ", container.getName(), componentInstanceId);
459                 result = Either.right(updateContainerComponentRes.right().value());
460             }
461         }
462         if (result == null) {
463             result = Either.left(new ImmutablePair<>((TopologyTemplate) updateContainerComponentRes.left().value(), componentInstanceId));
464         }
465         return result;
466     }
467
468     private StorageOperationStatus removeRelationsOfInstance(TopologyTemplate container, String ciToRemove, GraphVertex containerV) {
469         CompositionDataDefinition composition = container.getCompositions().get(JsonConstantKeysEnum.COMPOSITION.getValue());
470         if (composition != null) {
471             Map<String, RelationshipInstDataDefinition> relations = composition.getRelations();
472             if (MapUtils.isNotEmpty(relations)) {
473                 Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.CALCULATED_CAPABILITIES);
474                 if (capResult.isRight()) {
475                     return capResult.right().value();
476
477                 }
478                 Map<String, MapListCapabilityDataDefinition> calculatedCapabilty = capResult.left().value().getRight();
479
480                 Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capFullResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.FULLFILLED_CAPABILITIES);
481                 if (capFullResult.isRight()) {
482                     return capFullResult.right().value();
483
484                 }
485                 Map<String, MapListCapabilityDataDefinition> fullFilledCapabilty = capFullResult.left().value().getRight();
486
487                 Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS);
488                 if (reqResult.isRight()) {
489                     return reqResult.right().value();
490                 }
491                 Map<String, MapListRequirementDataDefinition> calculatedRequirement = reqResult.left().value().getRight();
492
493                 Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqFullResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.FULLFILLED_REQUIREMENTS);
494                 if (reqResult.isRight()) {
495                     return reqResult.right().value();
496                 }
497                 Map<String, MapListRequirementDataDefinition> fullfilledRequirement = reqFullResult.left().value().getRight();
498
499                 Iterator<Entry<String, RelationshipInstDataDefinition>> iterator = relations.entrySet().iterator();
500                 while (iterator.hasNext()) {
501                     Entry<String, RelationshipInstDataDefinition> relation = iterator.next();
502                     RelationshipInstDataDefinition relationToDelete = relation.getValue();
503                     if (relationToDelete.getFromId().equals(ciToRemove) || relationToDelete.getToId().equals(ciToRemove)) {
504                         iterator.remove();
505                         if (relationToDelete.getFromId().equals(ciToRemove)) {
506                             updateCalculatedRequirementsAfterDeleteRelation(calculatedRequirement, fullfilledRequirement, ciToRemove, relationToDelete, null);
507                             updateCalculatedCapabiltyAfterDeleteRelation(calculatedCapabilty, fullFilledCapabilty, relationToDelete.getToId(), relationToDelete, null);
508                         }
509                         if (relationToDelete.getToId().equals(ciToRemove)) {
510                             updateCalculatedRequirementsAfterDeleteRelation(calculatedRequirement, fullfilledRequirement, relationToDelete.getFromId(), relationToDelete, null);
511                             updateCalculatedCapabiltyAfterDeleteRelation(calculatedCapabilty, fullFilledCapabilty, ciToRemove, relationToDelete, null);
512                         }
513                     }
514                 }
515                 return updateAllAndCalculatedCapReqOnGraph(container.getUniqueId(), containerV, capResult, capFullResult, reqResult, reqFullResult);
516             }
517         }
518         return StorageOperationStatus.OK;
519     }
520
521     private StorageOperationStatus deleteComponentInstanceToscaDataFromContainerComponent(GraphVertex containerV, String componentInstanceId) {
522         StorageOperationStatus status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, componentInstanceId);
523         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
524             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove calculated capabilty  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
525             return status;
526         }
527         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, componentInstanceId);
528         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
529             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove calculated capabilty properties for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
530             return status;
531         }
532         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, componentInstanceId);
533         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
534             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove calculated requirement  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
535             return status;
536         }
537         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.FULLFILLED_CAPABILITIES, VertexTypeEnum.FULLFILLED_CAPABILITIES, componentInstanceId);
538         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
539             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove fullfilled capabilities  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
540             return status;
541         }
542         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.FULLFILLED_REQUIREMENTS, VertexTypeEnum.FULLFILLED_REQUIREMENTS, componentInstanceId);
543         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
544             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove fullfilled requirement  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
545             return status;
546         }
547         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.INST_ATTRIBUTES, VertexTypeEnum.INST_ATTRIBUTES, componentInstanceId);
548         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
549             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove attributes for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
550             return status;
551         }
552         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.INST_PROPERTIES, VertexTypeEnum.INST_PROPERTIES, componentInstanceId);
553         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
554             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove properties for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
555             return status;
556         }
557         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.INST_INPUTS, VertexTypeEnum.INST_INPUTS, componentInstanceId);
558         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
559             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove instance inputs  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
560             return status;
561         }
562         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS, componentInstanceId);
563         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
564             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove fullfilled requirement  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
565             return status;
566         }
567         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS, VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS, componentInstanceId);
568         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
569             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove instance deployment artifacts  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
570             return status;
571         }
572         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.INSTANCE_ARTIFACTS, VertexTypeEnum.INSTANCE_ARTIFACTS, componentInstanceId);
573         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
574             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove instance artifacts  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
575             return status;
576         }
577         status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.EXTERNAL_REFS, VertexTypeEnum.EXTERNAL_REF, componentInstanceId);
578         if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
579             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove instance external refs  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
580             return status;
581         }
582         return StorageOperationStatus.OK;
583     }
584
585     protected Either<GraphVertex, StorageOperationStatus> addComponentInstanceToscaDataToContainerComponent(ToscaElement originToscaElement, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex, User user) {
586
587         Either<GraphVertex, StorageOperationStatus> result;
588         StorageOperationStatus status;
589         if (originToscaElement.getToscaType() == ToscaElementTypeEnum.NODE_TYPE) {
590             status = addComponentInstanceToscaDataToNodeTypeContainer((NodeType) originToscaElement, componentInstance, updatedContainerVertex, user, HEAT_VF_ENV_NAME);
591         } else {
592             status = addComponentInstanceToscaDataToTopologyTemplateContainer((TopologyTemplate) originToscaElement, componentInstance, updatedContainerVertex);
593         }
594         if (status == StorageOperationStatus.OK) {
595             result = Either.left(updatedContainerVertex);
596         } else {
597             result = Either.right(status);
598         }
599         return result;
600     }
601
602     private StorageOperationStatus addComponentInstanceToscaDataToTopologyTemplateContainer(TopologyTemplate originTopologyTemplate, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) {
603
604         StorageOperationStatus status;
605
606         status = addCalculatedCapReqFromTopologyTemplate(originTopologyTemplate, componentInstance, updatedContainerVertex);
607
608         if (status != StorageOperationStatus.OK) {
609
610             return status;
611         }
612
613         MapPropertiesDataDefinition instInputs = new MapPropertiesDataDefinition(originTopologyTemplate.getInputs());
614         MapPropertiesDataDefinition instInputsAsProperties = turnInputsIntoProperties(instInputs);
615
616         status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.INST_INPUTS, VertexTypeEnum.INST_INPUTS, instInputsAsProperties, componentInstance.getUniqueId());
617         if (status != StorageOperationStatus.OK) {
618             return status;
619         }
620
621         return status;
622     }
623     
624     private MapPropertiesDataDefinition turnInputsIntoProperties(MapPropertiesDataDefinition instInput){
625         if (instInput.getMapToscaDataDefinition() != null) {
626             for (PropertyDataDefinition currProp : instInput.getMapToscaDataDefinition().values()){
627                 String temp = currProp.getValue();
628                 currProp.setValue(currProp.getDefaultValue());
629                 currProp.setDefaultValue(temp);
630             }
631         }
632         return instInput;
633     }
634
635     private StorageOperationStatus addCalculatedCapReqFromTopologyTemplate(TopologyTemplate originTopologyTemplate, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) {
636         Map<String, MapListCapabilityDataDefinition> calculatedCapabilities = originTopologyTemplate.getCalculatedCapabilities();
637
638         if (calculatedCapabilities != null) {
639             MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition();
640             calculatedCapabilities.entrySet().forEach(enntryPerInstance -> {
641                 Map<String, ListCapabilityDataDefinition> mapByType = enntryPerInstance.getValue().getMapToscaDataDefinition();
642                 mapByType.entrySet().forEach(entryPerType -> {
643                     entryPerType.getValue().getListToscaDataDefinition().forEach(cap -> {
644                         cap.addToPath(componentInstance.getUniqueId());
645                         allCalculatedCap.add(entryPerType.getKey(), cap);
646                     });
647                 });
648             });
649
650             StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, allCalculatedCap,
651                     componentInstance.getUniqueId());
652
653             if (calculatedResult != StorageOperationStatus.OK) {
654                 return calculatedResult;
655             }
656             MapListCapabilityDataDefinition fullCalculatedCap = new MapListCapabilityDataDefinition();
657             calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_CAPABILITIES, VertexTypeEnum.FULLFILLED_CAPABILITIES, fullCalculatedCap, componentInstance.getUniqueId());
658
659             if (calculatedResult != StorageOperationStatus.OK) {
660                 return calculatedResult;
661             }
662         }
663         Map<String, MapListRequirementDataDefinition> calculatedRequirements = originTopologyTemplate.getCalculatedRequirements();
664         if (calculatedRequirements != null) {
665
666             MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition();
667             calculatedRequirements.entrySet().forEach(enntryPerInstance -> {
668                 Map<String, ListRequirementDataDefinition> mapByType = enntryPerInstance.getValue().getMapToscaDataDefinition();
669                 mapByType.entrySet().forEach(entryPerType -> {
670                     entryPerType.getValue().getListToscaDataDefinition().forEach(req -> {
671                         req.addToPath(componentInstance.getUniqueId());
672                         allCalculatedReq.add(entryPerType.getKey(), req);
673                     });
674                 });
675             });
676
677             StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, allCalculatedReq,
678                     componentInstance.getUniqueId());
679             if (calculatedResult != StorageOperationStatus.OK) {
680                 return calculatedResult;
681             }
682             MapListRequirementDataDefinition fullCalculatedReq = new MapListRequirementDataDefinition();
683             calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_REQUIREMENTS, VertexTypeEnum.FULLFILLED_REQUIREMENTS, fullCalculatedReq, componentInstance.getUniqueId());
684             if (calculatedResult != StorageOperationStatus.OK) {
685                 return calculatedResult;
686             }
687         }
688
689         Map<String, MapCapabilityProperty> calculatedCapabilitiesProperties = originTopologyTemplate.getCalculatedCapabilitiesProperties();
690         Map<String, MapPropertiesDataDefinition> updateKeyMap = new HashMap<>();
691
692         if (calculatedCapabilitiesProperties != null && !calculatedCapabilitiesProperties.isEmpty()) {
693             for (MapCapabilityProperty map : calculatedCapabilitiesProperties.values()) {
694                 for (Entry<String, MapPropertiesDataDefinition> entry : map.getMapToscaDataDefinition().entrySet()) {
695                     String newKey = (componentInstance.getUniqueId() + ModelConverter.CAP_PROP_DELIM + entry.getKey());
696                     updateKeyMap.put(newKey, entry.getValue());
697                 }
698             }
699             MapCapabilityProperty MapCapabilityProperty = new MapCapabilityProperty(updateKeyMap);
700             StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, MapCapabilityProperty,
701                     componentInstance.getUniqueId());
702             if (calculatedResult != StorageOperationStatus.OK) {
703                 return calculatedResult;
704             }
705         }
706         return StorageOperationStatus.OK;
707     }
708
709     private StorageOperationStatus addComponentInstanceToscaDataToNodeTypeContainer(NodeType originNodeType, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex, User user, String envType) {
710
711         MapPropertiesDataDefinition instProperties = new MapPropertiesDataDefinition(originNodeType.getProperties());
712
713         StorageOperationStatus status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.INST_PROPERTIES, VertexTypeEnum.INST_PROPERTIES, instProperties, componentInstance.getUniqueId());
714         if (status != StorageOperationStatus.OK) {
715             return status;
716         }
717
718         MapPropertiesDataDefinition instAttributes = new MapPropertiesDataDefinition(originNodeType.getAttributes());
719
720         status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.INST_ATTRIBUTES, VertexTypeEnum.INST_ATTRIBUTES, instAttributes, componentInstance.getUniqueId());
721
722         if (status != StorageOperationStatus.OK) {
723             return status;
724         }
725
726         return addCalculatedCapReqFromNodeType(originNodeType, componentInstance, updatedContainerVertex);
727     }
728
729     public MapArtifactDataDefinition prepareInstDeploymentArtifactPerInstance(Map<String, ArtifactDataDefinition> deploymentArtifacts, String componentInstanceId, User user, String envType) {
730         if (deploymentArtifacts != null && envType.equals(HEAT_VF_ENV_NAME)) {
731             Map<String, ArtifactDataDefinition> instDeploymentArtifacts = new HashMap<>();
732
733             deploymentArtifacts.entrySet().forEach(e -> {
734                 ArtifactDataDefinition artifact = e.getValue();
735                 String type = artifact.getArtifactType();
736                 if (type.equalsIgnoreCase(ArtifactTypeEnum.HEAT.getType()) || type.equalsIgnoreCase(ArtifactTypeEnum.HEAT_NET.getType()) || type.equalsIgnoreCase(ArtifactTypeEnum.HEAT_VOL.getType())) {
737                     ArtifactDataDefinition artifactEnv = createArtifactPlaceHolderInfo(artifact, componentInstanceId, user, envType);
738                     instDeploymentArtifacts.put(artifactEnv.getArtifactLabel(), artifactEnv);
739                 }
740             });
741
742             deploymentArtifacts.putAll(instDeploymentArtifacts);
743
744             return new MapArtifactDataDefinition(deploymentArtifacts);
745
746         }
747         return null;
748     }
749
750     @SuppressWarnings({ "unchecked" })
751     private ArtifactDataDefinition createArtifactPlaceHolderInfo(ArtifactDataDefinition artifactHeat, String componentId, User user, String heatEnvType) {
752         Map<String, Object> deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration().getDeploymentResourceInstanceArtifacts();
753         if (deploymentResourceArtifacts == null) {
754             log.debug("no deployment artifacts are configured for generated artifacts");
755             return null;
756         }
757         Map<String, Object> placeHolderData = (Map<String, Object>) deploymentResourceArtifacts.get(heatEnvType);
758         if (placeHolderData == null) {
759             log.debug("no env type {} are configured for generated artifacts", heatEnvType);
760             return null;
761         }
762
763         String envLabel = (artifactHeat.getArtifactLabel() + HEAT_ENV_SUFFIX).toLowerCase();
764
765         ArtifactDataDefinition artifactInfo = new ArtifactDataDefinition();
766
767         String artifactName = (String) placeHolderData.get(ARTIFACT_PLACEHOLDER_DISPLAY_NAME);
768         String artifactType = (String) placeHolderData.get(ARTIFACT_PLACEHOLDER_TYPE);
769         String artifactDescription = (String) placeHolderData.get(ARTIFACT_PLACEHOLDER_DESCRIPTION);
770
771         artifactInfo.setArtifactDisplayName(artifactName);
772         artifactInfo.setArtifactLabel(envLabel);
773         artifactInfo.setArtifactType(artifactType);
774         artifactInfo.setDescription(artifactDescription);
775         artifactInfo.setArtifactGroupType(artifactHeat.getArtifactGroupType());
776         setDefaultArtifactTimeout(artifactHeat.getArtifactGroupType(), artifactInfo);
777         artifactInfo.setGeneratedFromId(artifactHeat.getUniqueId());
778         // clone heat parameters in case of heat env only not VF heat env
779         if (heatEnvType.equals(HEAT_ENV_NAME)) {
780             artifactInfo.setHeatParameters(artifactHeat.getHeatParameters());
781         }
782         setArtifactPlaceholderCommonFields(componentId, user, artifactInfo);
783
784         return artifactInfo;
785     }
786
787     public void setDefaultArtifactTimeout(ArtifactGroupTypeEnum groupType, ArtifactDataDefinition artifactInfo) {
788         if (groupType.equals(ArtifactGroupTypeEnum.DEPLOYMENT)) {
789             artifactInfo.setTimeout(defaultHeatTimeout);
790         } else {
791             artifactInfo.setTimeout(NON_HEAT_TIMEOUT);
792         }
793     }
794
795     private void setArtifactPlaceholderCommonFields(String resourceId, User user, ArtifactDataDefinition artifactInfo) {
796         String uniqueId = null;
797
798         if (resourceId != null) {
799             uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId.toLowerCase(), artifactInfo.getArtifactLabel().toLowerCase());
800             artifactInfo.setUniqueId(uniqueId);
801         }
802         artifactInfo.setUserIdCreator(user.getUserId());
803         String fullName = user.getFullName();
804         artifactInfo.setUpdaterFullName(fullName);
805
806         long time = System.currentTimeMillis();
807
808         artifactInfo.setCreatorFullName(fullName);
809         artifactInfo.setCreationDate(time);
810
811         artifactInfo.setLastUpdateDate(time);
812         artifactInfo.setUserIdLastUpdater(user.getUserId());
813
814         artifactInfo.setMandatory(true);
815     }
816
817     /**
818      *
819      * @param originNodeType
820      * @param componentInstance
821      * @param updatedContainerVertex
822      * @return
823      */
824     private StorageOperationStatus addCalculatedCapReqFromNodeType(NodeType originNodeType, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) {
825
826         Map<String, ListCapabilityDataDefinition> capabilities = originNodeType.getCapabilties();
827         MapListCapabilityDataDefinition allCalculatedCap = prepareCalculatedCapabiltyForNodeType(capabilities, componentInstance);
828         StorageOperationStatus calculatedResult;
829         if (allCalculatedCap != null) {
830             calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, allCalculatedCap, componentInstance.getUniqueId());
831
832             if (calculatedResult != StorageOperationStatus.OK) {
833                 return calculatedResult;
834             }
835         }
836         Map<String, MapPropertiesDataDefinition> capabiltiesProperties = originNodeType.getCapabiltiesProperties();
837         if (capabiltiesProperties != null) {
838             Map<String, MapPropertiesDataDefinition> updateKeyMap = capabiltiesProperties.entrySet().stream().collect(Collectors.toMap(e -> createCapPropertyKey(e.getKey(), componentInstance.getUniqueId()), Entry::getValue));
839             MapCapabilityProperty MapCapabilityProperty = new MapCapabilityProperty(updateKeyMap);
840             calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, MapCapabilityProperty, componentInstance.getUniqueId());
841             if (calculatedResult != StorageOperationStatus.OK) {
842                 return calculatedResult;
843             }
844         }
845
846         MapListCapabilityDataDefinition fullCalculatedCap = new MapListCapabilityDataDefinition();
847         calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_CAPABILITIES, VertexTypeEnum.FULLFILLED_CAPABILITIES, fullCalculatedCap, componentInstance.getUniqueId());
848
849         if (calculatedResult != StorageOperationStatus.OK) {
850             return calculatedResult;
851         }
852
853         Map<String, ListRequirementDataDefinition> requirements = originNodeType.getRequirements();
854
855         MapListRequirementDataDefinition allCalculatedReq = prepareCalculatedRequirementForNodeType(requirements, componentInstance);
856
857         StorageOperationStatus status;
858         if (allCalculatedReq != null) {
859             status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, allCalculatedReq, componentInstance.getUniqueId());
860             if (status != StorageOperationStatus.OK) {
861                 return status;
862             }
863         }
864         MapListRequirementDataDefinition fullCalculatedReq = new MapListRequirementDataDefinition();
865         status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_REQUIREMENTS, VertexTypeEnum.FULLFILLED_REQUIREMENTS, fullCalculatedReq, componentInstance.getUniqueId());
866         return StorageOperationStatus.OK;
867
868     }
869
870     public static String createCapPropertyKey(String key, String instanceId) {
871         StringBuffer sb = new StringBuffer(instanceId);
872         sb.append(ModelConverter.CAP_PROP_DELIM).append(instanceId).append(ModelConverter.CAP_PROP_DELIM).append(key);
873         return sb.toString();
874     }
875
876     /**
877      * Prepares a map of capabilities lists Produces a deep copy of the received map of capabilities Sets values to the specific fields according to received component instance
878      * 
879      * @param capabilities
880      * @param componentInstance
881      * @return
882      */
883     public MapListCapabilityDataDefinition prepareCalculatedCapabiltyForNodeType(Map<String, ListCapabilityDataDefinition> capabilities, ComponentInstanceDataDefinition componentInstance) {
884         if (capabilities != null) {
885             MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition();
886
887             capabilities.entrySet().forEach(e -> {
888                 List<CapabilityDataDefinition> listCapabilities = e.getValue().getListToscaDataDefinition().stream().map(CapabilityDataDefinition::new).collect(Collectors.toList());
889                 listCapabilities.forEach(cap -> {
890                     cap.setSource(componentInstance.getComponentUid());
891                     cap.addToPath(componentInstance.getUniqueId());
892                     cap.setOwnerId(componentInstance.getUniqueId());
893                     cap.setOwnerName(componentInstance.getName());
894                     cap.setLeftOccurrences(cap.getMaxOccurrences());
895                     allCalculatedCap.add(e.getKey(), cap);
896                 });
897             });
898             return allCalculatedCap;
899         }
900         return null;
901     }
902
903     /**
904      * Prepares a map of requirements lists Produces a deep copy of the received map of requirements Sets values to the specific fields according to received component instance
905      * 
906      * @param requirements
907      * @param componentInstance
908      * @return
909      */
910     public MapListRequirementDataDefinition prepareCalculatedRequirementForNodeType(Map<String, ListRequirementDataDefinition> requirements, ComponentInstanceDataDefinition componentInstance) {
911         if (requirements != null) {
912             MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition();
913
914             requirements.entrySet().forEach(e -> {
915                 List<RequirementDataDefinition> listRequirements = e.getValue().getListToscaDataDefinition().stream().map(RequirementDataDefinition::new).collect(Collectors.toList());
916                 listRequirements.forEach(req -> {
917                     req.setSource(componentInstance.getComponentUid());
918                     req.addToPath(componentInstance.getUniqueId());
919                     req.setOwnerId(componentInstance.getUniqueId());
920                     req.setOwnerName(componentInstance.getName());
921                     req.setLeftOccurrences(req.getMaxOccurrences());
922                     allCalculatedReq.add(e.getKey(), req);
923                 });
924             });
925             return allCalculatedReq;
926         }
927         return null;
928     }
929
930     public StorageOperationStatus addGroupInstancesToComponentInstance(Component containerComponent, ComponentInstanceDataDefinition componentInstance, List<GroupDefinition> groups, Map<String, List<ArtifactDefinition>> groupInstancesArtifacts) {
931
932         StorageOperationStatus result = null;
933         Map<String, GroupInstanceDataDefinition> groupInstanceToCreate = new HashMap<>();
934         if (groupInstancesArtifacts != null && CollectionUtils.isNotEmpty(groups)) {
935             for (Map.Entry<String, List<ArtifactDefinition>> groupArtifacts : groupInstancesArtifacts.entrySet()) {
936                 Optional<GroupDefinition> groupOptional = groups.stream().filter(g -> g.getUniqueId().equals(groupArtifacts.getKey())).findFirst();
937                 if (groupOptional.isPresent()) {
938                     GroupInstanceDataDefinition groupInstance = buildGroupInstanceDataDefinition((GroupDataDefinition) groupOptional.get(), (ComponentInstanceDataDefinition) componentInstance, null);
939                     groupInstance.setGroupInstanceArtifacts(groupArtifacts.getValue().stream().map(ArtifactDataDefinition::getUniqueId).collect(Collectors.toList()));
940                     groupInstance.setGroupInstanceArtifactsUuid(groupArtifacts.getValue().stream().map(ArtifactDataDefinition::getArtifactUUID).collect(Collectors.toList()));
941                     groupInstanceToCreate.put(groupInstance.getName(), groupInstance);
942                 }
943             }
944         }
945         if (MapUtils.isNotEmpty(groupInstanceToCreate)) {
946             result = addToscaDataDeepElementsBlockToToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS, new MapDataDefinition<>(groupInstanceToCreate), componentInstance.getUniqueId());
947         }
948         if (result == null) {
949             result = StorageOperationStatus.OK;
950         }
951         return result;
952     }
953
954     private ComponentInstanceDataDefinition buildComponentInstanceDataDefinition(ComponentInstance resourceInstance, String containerComponentId, String instanceNewName, boolean generateUid, ToscaElement originToscaElement) {
955         String ciOriginComponentUid = resourceInstance.getComponentUid();
956
957         if (!ValidationUtils.validateStringNotEmpty(resourceInstance.getCustomizationUUID())) {
958             resourceInstance.setCustomizationUUID(generateCustomizationUUID());
959         }
960         ComponentInstanceDataDefinition dataDefinition = new ComponentInstanceDataDefinition(resourceInstance);
961
962         Long creationDate = resourceInstance.getCreationTime();
963         Long modificationTime;
964         if (creationDate == null) {
965             creationDate = System.currentTimeMillis();
966             modificationTime = creationDate;
967         } else {
968             modificationTime = System.currentTimeMillis();
969         }
970         dataDefinition.setComponentUid(ciOriginComponentUid);
971         dataDefinition.setCreationTime(creationDate);
972         dataDefinition.setModificationTime(modificationTime);
973         if (StringUtils.isNotEmpty(instanceNewName)) {
974             dataDefinition.setName(instanceNewName);
975             resourceInstance.setName(instanceNewName);
976         }
977         if (StringUtils.isNotEmpty(dataDefinition.getName()))
978             dataDefinition.setNormalizedName(ValidationUtils.normalizeComponentInstanceName(dataDefinition.getName()));
979         dataDefinition.setIcon(resourceInstance.getIcon());
980         if (generateUid) {
981             dataDefinition.setUniqueId(UniqueIdBuilder.buildResourceInstanceUniuqeId(containerComponentId, ciOriginComponentUid, dataDefinition.getNormalizedName()));
982             resourceInstance.setUniqueId(dataDefinition.getUniqueId());
983         }
984         if (StringUtils.isEmpty(dataDefinition.getComponentVersion()) && originToscaElement != null)
985             dataDefinition.setComponentVersion((String) originToscaElement.getMetadataValue(JsonPresentationFields.VERSION));
986         if (StringUtils.isEmpty(dataDefinition.getComponentName()) && originToscaElement != null)
987             dataDefinition.setComponentName((String) originToscaElement.getMetadataValue(JsonPresentationFields.NAME));
988         if (originToscaElement != null && dataDefinition.getToscaComponentName() == null)
989             dataDefinition.setToscaComponentName((String) originToscaElement.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME));
990         if (dataDefinition.getOriginType() == null && originToscaElement != null) {
991             ResourceTypeEnum resourceType = originToscaElement.getResourceType();
992             OriginTypeEnum originType = OriginTypeEnum.findByValue(resourceType.name());
993             dataDefinition.setOriginType(originType);
994         }
995         if (dataDefinition.getOriginType() == OriginTypeEnum.ServiceProxy)
996             dataDefinition.setIsProxy(true);
997
998         return dataDefinition;
999     }
1000
1001     private Boolean isUniqueInstanceName(TopologyTemplate container, String instanceName) {
1002         Boolean isUniqueName = true;
1003         try {
1004             isUniqueName = !container.getComponentInstances().values().stream().filter(ci -> ci.getName() != null && ci.getName().equals(instanceName)).findAny().isPresent();
1005
1006         } catch (Exception e) {
1007             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occured during fetching component instance with name {} from component container {}. {} ", instanceName, container.getName(), e.getMessage());
1008         }
1009         return isUniqueName;
1010     }
1011
1012     private String buildComponentInstanceName(String instanceSuffixNumber, String instanceName) {
1013         return instanceName + " " + (instanceSuffixNumber == null ? 0 : instanceSuffixNumber);
1014     }
1015
1016     public Either<RequirementCapabilityRelDef, StorageOperationStatus> associateResourceInstances(String componentId, RequirementCapabilityRelDef relation) {
1017         List<RequirementCapabilityRelDef> relations = new ArrayList<>();
1018         relations.add(relation);
1019         Either<List<RequirementCapabilityRelDef>, StorageOperationStatus> associateResourceInstances = associateResourceInstances(componentId, relations);
1020         if (associateResourceInstances.isRight()) {
1021             return Either.right(associateResourceInstances.right().value());
1022         }
1023         return Either.left(associateResourceInstances.left().value().get(0));
1024     }
1025
1026     @SuppressWarnings({ "unchecked" })
1027     public <T extends ToscaDataDefinition> Either<List<RequirementCapabilityRelDef>, StorageOperationStatus> associateResourceInstances(String componentId, List<RequirementCapabilityRelDef> relations) {
1028
1029         Either<GraphVertex, TitanOperationStatus> containerVEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll);
1030         if (containerVEither.isRight()) {
1031             TitanOperationStatus error = containerVEither.right().value();
1032             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FETCH_CONTAINER_VERTEX_ERROR, componentId, error);
1033             return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
1034         }
1035         GraphVertex containerV = containerVEither.left().value();
1036         Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.CALCULATED_CAPABILITIES);
1037         if (capResult.isRight()) {
1038             return Either.right(capResult.right().value());
1039
1040         }
1041         Map<String, MapListCapabilityDataDefinition> calculatedCapabilty = capResult.left().value().getRight();
1042
1043         Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capFullResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.FULLFILLED_CAPABILITIES);
1044         if (capResult.isRight()) {
1045             return Either.right(capResult.right().value());
1046
1047         }
1048         Map<String, MapListCapabilityDataDefinition> fullFilledCapabilty = capFullResult.left().value().getRight();
1049
1050         Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS);
1051         if (reqResult.isRight()) {
1052             return Either.right(reqResult.right().value());
1053         }
1054         Map<String, MapListRequirementDataDefinition> calculatedRequirement = reqResult.left().value().getRight();
1055
1056         Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqFullResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.FULLFILLED_REQUIREMENTS);
1057         if (reqResult.isRight()) {
1058             return Either.right(reqResult.right().value());
1059         }
1060         Map<String, MapListRequirementDataDefinition> fullfilledRequirement = reqFullResult.left().value().getRight();
1061
1062         Map<String, CompositionDataDefinition> jsonComposition = (Map<String, CompositionDataDefinition>) containerV.getJson();
1063         CompositionDataDefinition compositionDataDefinition = jsonComposition.get(JsonConstantKeysEnum.COMPOSITION.getValue());
1064
1065         StorageOperationStatus status;
1066         List<RequirementCapabilityRelDef> relationsList = new ArrayList<>();
1067         for (RequirementCapabilityRelDef relation : relations) {
1068             List<CapabilityRequirementRelationship> relationshipsResult = new ArrayList<>();
1069             String fromNode = relation.getFromNode();
1070             String toNode = relation.getToNode();
1071             List<CapabilityRequirementRelationship> relationships = relation.getRelationships();
1072             if (relationships == null || relationships.isEmpty()) {
1073                 BeEcompErrorManager.getInstance().logBeFailedAddingResourceInstanceError("AssociateResourceInstances - missing relationship", fromNode, componentId);
1074                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No requirement definition sent in order to set the relation between {} to {}", fromNode, toNode);
1075                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT));
1076             }
1077
1078             for (CapabilityRequirementRelationship immutablePair : relationships) {
1079                 String requirement = immutablePair.getRelation().getRequirement();
1080
1081                 Either<Map<JsonPresentationFields, T>, StorageOperationStatus> associateRes = connectInstancesInContainer(fromNode, toNode, immutablePair.getRelation(), relation.isOriginUI(), calculatedCapabilty, calculatedRequirement,
1082                         fullFilledCapabilty, fullfilledRequirement, compositionDataDefinition, containerV.getUniqueId());
1083
1084                 if (associateRes.isRight()) {
1085                     status = associateRes.right().value();
1086                     BeEcompErrorManager.getInstance().logBeFailedAddingResourceInstanceError("AssociateResourceInstances - missing relationship", fromNode, componentId);
1087                     CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to associate resource instance {} to resource instance {}. status is {}", fromNode, toNode, status);
1088                     return Either.right(status);
1089                 }
1090
1091                 RelationshipInstDataDefinition relationshipInstData = (RelationshipInstDataDefinition) associateRes.left().value().get(JsonPresentationFields.RELATIONSHIP);
1092                 RelationshipImpl relationshipImplResult = new RelationshipImpl();
1093                 relationshipImplResult.setType(relationshipInstData.getType());
1094                 RelationshipInfo requirementAndRelationshipPair = new RelationshipInfo(requirement, relationshipImplResult);
1095                 requirementAndRelationshipPair.setCapability(immutablePair.getRelation().getCapability());
1096                 requirementAndRelationshipPair.setRequirement(immutablePair.getRelation().getRequirement());
1097                 requirementAndRelationshipPair.setCapabilityOwnerId(relationshipInstData.getCapabilityOwnerId());
1098                 requirementAndRelationshipPair.setRequirementOwnerId(relationshipInstData.getRequirementOwnerId());
1099                 requirementAndRelationshipPair.setCapabilityUid(immutablePair.getRelation().getCapabilityUid());
1100                 requirementAndRelationshipPair.setRequirementUid(immutablePair.getRelation().getRequirementUid());
1101                 requirementAndRelationshipPair.setId(relationshipInstData.getUniqueId());
1102                 CapabilityRequirementRelationship capReqRel = new CapabilityRequirementRelationship();
1103                 capReqRel.setRelation(requirementAndRelationshipPair);
1104                 capReqRel.setCapability((CapabilityDataDefinition) associateRes.left().value().get(JsonPresentationFields.CAPAPILITY));
1105                 capReqRel.setRequirement((RequirementDataDefinition) associateRes.left().value().get(JsonPresentationFields.REQUIREMENT));
1106                 relationshipsResult.add(capReqRel);
1107                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "update customization UUID for from CI {} and to CI {}", relation.getFromNode(), relation.getToNode());
1108                 status = updateCustomizationUUID(relation.getFromNode(), compositionDataDefinition);
1109                 if (status != StorageOperationStatus.OK) {
1110                     return Either.right(status);
1111                 }
1112                 status = updateCustomizationUUID(relation.getToNode(), compositionDataDefinition);
1113                 if (status != StorageOperationStatus.OK) {
1114                     return Either.right(status);
1115                 }
1116             }
1117             RequirementCapabilityRelDef reqCapRelDef = new RequirementCapabilityRelDef(relation);
1118             reqCapRelDef.setRelationships(relationshipsResult);
1119             relationsList.add(reqCapRelDef);
1120         }
1121         // update metadata of container and composition json
1122         status = updateAllAndCalculatedCapReqOnGraph(componentId, containerV, capResult, capFullResult, reqResult, reqFullResult);
1123         if (status != StorageOperationStatus.OK) {
1124             return Either.right(status);
1125         }
1126
1127         return Either.left(relationsList);
1128     }
1129
1130     private StorageOperationStatus updateAllAndCalculatedCapReqOnGraph(String componentId, GraphVertex containerV, Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capResult,
1131             Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capFullResult, Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqResult,
1132             Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqFullResult) {
1133         containerV.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
1134         Either<GraphVertex, TitanOperationStatus> updateElement = titanDao.updateVertex(containerV);
1135         if (updateElement.isRight()) {
1136             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update topology template {} with new relations error {}. ", componentId, updateElement.right().value());
1137             return DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value());
1138         }
1139         // update cap/req jsons, fulfilled cap/req jsons!!!!!
1140         Either<GraphVertex, TitanOperationStatus> status;
1141         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Update calculated capabilty for container {}", containerV.getUniqueId());
1142         status = updateOrCopyOnUpdate(capResult.left().value().getLeft(), containerV, EdgeLabelEnum.CALCULATED_CAPABILITIES);
1143         if (status.isRight()) {
1144             TitanOperationStatus error = status.right().value();
1145             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update calculated capabilty for container {} error {}", containerV.getUniqueId(), error);
1146             return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
1147         }
1148
1149         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Update calculated requirement for container {}", containerV.getUniqueId());
1150         status = updateOrCopyOnUpdate(reqResult.left().value().getLeft(), containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS);
1151         if (status.isRight()) {
1152             TitanOperationStatus error = status.right().value();
1153             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update calculated requiremnt for container {} error {}", containerV.getUniqueId(), error);
1154             return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
1155         }
1156
1157         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Update fullfilled capabilty for container {}", containerV.getUniqueId());
1158         status = updateOrCopyOnUpdate(capFullResult.left().value().getLeft(), containerV, EdgeLabelEnum.FULLFILLED_CAPABILITIES);
1159         if (status.isRight()) {
1160             TitanOperationStatus error = status.right().value();
1161             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update fullfilled capabilty for container {} error {}", containerV.getUniqueId(), error);
1162             return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
1163         }
1164
1165         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Update fullfilled requirement for container {}", containerV.getUniqueId());
1166         status = updateOrCopyOnUpdate(reqFullResult.left().value().getLeft(), containerV, EdgeLabelEnum.FULLFILLED_REQUIREMENTS);
1167         if (status.isRight()) {
1168             TitanOperationStatus error = status.right().value();
1169             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update fullfilled requirement for container {} error {}", containerV.getUniqueId(), error);
1170             return DaoStatusConverter.convertTitanStatusToStorageStatus(error);
1171         }
1172         return StorageOperationStatus.OK;
1173     }
1174
1175     @SuppressWarnings({ "unchecked" })
1176     public Either<RequirementCapabilityRelDef, StorageOperationStatus> dissociateResourceInstances(String componentId, RequirementCapabilityRelDef requirementDef) {
1177         if (requirementDef.getRelationships() == null) {
1178             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No relation pair in request [ {} ]", requirementDef);
1179             return Either.right(StorageOperationStatus.BAD_REQUEST);
1180         }
1181
1182         String fromResInstanceUid = requirementDef.getFromNode();
1183         String toResInstanceUid = requirementDef.getToNode();
1184
1185         Either<GraphVertex, TitanOperationStatus> containerVEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll);
1186         if (containerVEither.isRight()) {
1187             TitanOperationStatus error = containerVEither.right().value();
1188             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FETCH_CONTAINER_VERTEX_ERROR, componentId, error);
1189             return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
1190         }
1191         GraphVertex containerV = containerVEither.left().value();
1192
1193         // DE191707 - validations
1194         Map<String, CompositionDataDefinition> jsonComposition = (Map<String, CompositionDataDefinition>) containerV.getJson();
1195         CompositionDataDefinition compositionDataDefinition = jsonComposition.get(JsonConstantKeysEnum.COMPOSITION.getValue());
1196         Map<String, ComponentInstanceDataDefinition> componentInstances = compositionDataDefinition.getComponentInstances();
1197         ComponentInstanceDataDefinition ciFrom = componentInstances.get(fromResInstanceUid);
1198         if (ciFrom == null) {
1199             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "FROM instance {} isn't under container {}", fromResInstanceUid, componentId);
1200             return Either.right(StorageOperationStatus.NOT_FOUND);
1201
1202         }
1203         ComponentInstanceDataDefinition ciTo = componentInstances.get(toResInstanceUid);
1204         if (ciFrom == ciTo) {
1205             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "TO instance {} isn't under container {}", toResInstanceUid, componentId);
1206             return Either.right(StorageOperationStatus.NOT_FOUND);
1207
1208         }
1209         Map<String, RelationshipInstDataDefinition> relations = compositionDataDefinition.getRelations();
1210
1211         List<CapabilityRequirementRelationship> relationPairList = requirementDef.getRelationships();
1212         Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.CALCULATED_CAPABILITIES);
1213         if (capResult.isRight()) {
1214             return Either.right(capResult.right().value());
1215         }
1216         Map<String, MapListCapabilityDataDefinition> calculatedCapability = capResult.left().value().getRight();
1217
1218         Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capFullResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.FULLFILLED_CAPABILITIES);
1219         if (capResult.isRight()) {
1220             return Either.right(capResult.right().value());
1221
1222         }
1223         Map<String, MapListCapabilityDataDefinition> fulfilledCapability = capFullResult.left().value().getRight();
1224
1225         Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS);
1226         if (reqResult.isRight()) {
1227             return Either.right(reqResult.right().value());
1228         }
1229         Map<String, MapListRequirementDataDefinition> calculatedRequirement = reqResult.left().value().getRight();
1230
1231         Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqFullResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.FULLFILLED_REQUIREMENTS);
1232         if (reqResult.isRight()) {
1233             return Either.right(reqResult.right().value());
1234         }
1235         Map<String, MapListRequirementDataDefinition> fulfilledRequirement = reqFullResult.left().value().getRight();
1236
1237         for (CapabilityRequirementRelationship relationPair : relationPairList) {
1238             Iterator<Entry<String, RelationshipInstDataDefinition>> iterator = relations.entrySet().iterator();
1239             boolean isDeleted = false;
1240             while (iterator.hasNext()) {
1241                 Entry<String, RelationshipInstDataDefinition> entryInJson = iterator.next();
1242                 RelationshipInstDataDefinition relationInJson = entryInJson.getValue();
1243                 if (relationInJson.getFromId().equals(fromResInstanceUid) && relationInJson.getToId().equals(toResInstanceUid) && relationInJson.getUniqueId().equals(relationPair.getRelation().getId())) {
1244                     if (relationPair.getRelation().equalsTo(relationInJson)) {
1245                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Remove relation from {} to {} capability {} capOwnerId {} reqOwnerId {} ", toResInstanceUid, componentId, relationInJson.getType(), relationInJson.getCapabilityOwnerId(),
1246                                 relationInJson.getRequirementOwnerId());
1247                         iterator.remove();
1248
1249                         // update calculated cap/req
1250                         StorageOperationStatus status = updateCalculatedCapabiltyAfterDeleteRelation(calculatedCapability, fulfilledCapability, toResInstanceUid, relationInJson, relationPair);
1251                         if (status != StorageOperationStatus.OK) {
1252                             return Either.right(status);
1253                         }
1254                         status = updateCalculatedRequirementsAfterDeleteRelation(calculatedRequirement, fulfilledRequirement, fromResInstanceUid, relationInJson, relationPair);
1255                         if (status != StorageOperationStatus.OK) {
1256                             return Either.right(status);
1257                         }
1258                         isDeleted = true;
1259                     }
1260                 }
1261             }
1262             if (!isDeleted) {
1263                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No relation to delete from {} to {} capabilty {} capOwnerId {} reqOwnerId {} ", toResInstanceUid, componentId, relationPair.getCapability(),
1264                         relationPair.getRelation().getCapabilityOwnerId(), relationPair.getRelation().getRequirementOwnerId());
1265                 return Either.right(StorageOperationStatus.NOT_FOUND);
1266             }
1267         }
1268         StorageOperationStatus status = updateCustomizationUUID(fromResInstanceUid, compositionDataDefinition);
1269         if (status != StorageOperationStatus.OK) {
1270             return Either.right(status);
1271         }
1272         status = updateCustomizationUUID(toResInstanceUid, compositionDataDefinition);
1273         if (status != StorageOperationStatus.OK) {
1274             return Either.right(status);
1275         }
1276
1277         // update jsons
1278         // update metadata of container and composition json
1279         status = updateAllAndCalculatedCapReqOnGraph(componentId, containerV, capResult, capFullResult, reqResult, reqFullResult);
1280         if (status != StorageOperationStatus.OK) {
1281             return Either.right(status);
1282         }
1283
1284         return Either.left(requirementDef);
1285     }
1286
1287     /**
1288      * Retrieves fulfilled requirement according to relation and received predicate
1289      * 
1290      * @param componentId
1291      * @param instanceId
1292      * @param foundRelation
1293      * @param predicate
1294      * @return
1295      */
1296     public Either<RequirementDataDefinition, StorageOperationStatus> getFulfilledRequirementByRelation(String componentId, String instanceId, RequirementCapabilityRelDef foundRelation,
1297             BiPredicate<RelationshipInfo, RequirementDataDefinition> predicate) {
1298
1299         Either<RequirementDataDefinition, StorageOperationStatus> result = null;
1300         Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> reqFullResult = null;
1301         MapListRequirementDataDefinition reqMapOfLists = null;
1302         Optional<RequirementDataDefinition> foundRequirement;
1303         RelationshipInfo relationshipInfo = foundRelation.resolveSingleRelationship().getRelation();
1304         Either<GraphVertex, TitanOperationStatus> containerVEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll);
1305         if (containerVEither.isRight()) {
1306             TitanOperationStatus error = containerVEither.right().value();
1307             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FETCH_CONTAINER_VERTEX_ERROR, componentId, error);
1308             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
1309         }
1310         if (result == null) {
1311             GraphVertex containerV = containerVEither.left().value();
1312             reqFullResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.FULLFILLED_REQUIREMENTS);
1313             if (reqFullResult.isRight()) {
1314                 result = Either.right(reqFullResult.right().value());
1315             }
1316         }
1317         if (result == null) {
1318             Map<String, MapListRequirementDataDefinition> fulfilledRequirement = reqFullResult.left().value().getRight();
1319             reqMapOfLists = fulfilledRequirement.get(instanceId);
1320             if (reqMapOfLists == null) {
1321                 result = Either.right(StorageOperationStatus.NOT_FOUND);
1322             }
1323         }
1324         if (result == null && reqMapOfLists != null) {
1325             for (ListRequirementDataDefinition requirements : reqMapOfLists.getMapToscaDataDefinition().values()) {
1326                 foundRequirement = requirements.getListToscaDataDefinition().stream().filter(req -> predicate.test(relationshipInfo, req)).findFirst();
1327                 if (foundRequirement.isPresent()) {
1328                     result = Either.left(foundRequirement.get());
1329                 }
1330             }
1331         }
1332         return result;
1333     }
1334
1335     /**
1336      * Retrieves fulfilled capability according to relation and received predicate
1337      * 
1338      * @param componentId
1339      * @param instanceId
1340      * @param foundRelation
1341      * @param predicate
1342      * @return
1343      */
1344     public Either<CapabilityDataDefinition, StorageOperationStatus> getFulfilledCapabilityByRelation(String componentId, String instanceId, RequirementCapabilityRelDef foundRelation,
1345             BiPredicate<RelationshipInfo, CapabilityDataDefinition> predicate) {
1346
1347         Either<CapabilityDataDefinition, StorageOperationStatus> result = null;
1348         Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> capFullResult = null;
1349         MapListCapabilityDataDefinition capMapOfLists = null;
1350         Optional<CapabilityDataDefinition> foundRequirement;
1351
1352         RelationshipInfo relationshipInfo = foundRelation.resolveSingleRelationship().getRelation();
1353         Either<GraphVertex, TitanOperationStatus> containerVEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll);
1354         if (containerVEither.isRight()) {
1355             TitanOperationStatus error = containerVEither.right().value();
1356             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FETCH_CONTAINER_VERTEX_ERROR, componentId, error);
1357             result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
1358         }
1359         if (result == null) {
1360             GraphVertex containerV = containerVEither.left().value();
1361             capFullResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.FULLFILLED_CAPABILITIES);
1362             if (capFullResult.isRight()) {
1363                 result = Either.right(capFullResult.right().value());
1364             }
1365         }
1366         if (result == null) {
1367             Map<String, MapListCapabilityDataDefinition> fulfilledCapability = capFullResult.left().value().getRight();
1368             capMapOfLists = fulfilledCapability.get(instanceId);
1369             if (capMapOfLists == null) {
1370                 result = Either.right(StorageOperationStatus.NOT_FOUND);
1371             }
1372         }
1373         if (result == null && capMapOfLists != null) {
1374             for (ListCapabilityDataDefinition capabilities : capMapOfLists.getMapToscaDataDefinition().values()) {
1375                 foundRequirement = capabilities.getListToscaDataDefinition().stream().filter(cap -> predicate.test(relationshipInfo, cap)).findFirst();
1376                 if (foundRequirement.isPresent()) {
1377                     result = Either.left(foundRequirement.get());
1378                 }
1379             }
1380         }
1381         return result;
1382     }
1383
1384     private StorageOperationStatus updateCalculatedRequirementsAfterDeleteRelation(Map<String, MapListRequirementDataDefinition> calculatedRequirement, Map<String, MapListRequirementDataDefinition> fullFilledRequirement, String fromResInstanceUid,
1385             RelationshipInstDataDefinition relation, CapabilityRequirementRelationship relationship) {
1386         StorageOperationStatus status;
1387         String hereIsTheKey = null;
1388         MapListRequirementDataDefinition reqByInstance = calculatedRequirement.get(fromResInstanceUid);
1389         if (reqByInstance == null || reqByInstance.findKeyByItemUidMatch(relation.getRequirementId()) == null) {
1390             // move from fulfilled
1391             status = moveFromFullFilledRequirement(calculatedRequirement, fullFilledRequirement, fromResInstanceUid, relation, hereIsTheKey, relationship);
1392         } else {
1393             hereIsTheKey = reqByInstance.findKeyByItemUidMatch(relation.getRequirementId());
1394             ListRequirementDataDefinition reqByType = reqByInstance.findByKey(hereIsTheKey);
1395             Optional<RequirementDataDefinition> requirementOptional = reqByType.getListToscaDataDefinition().stream()
1396                     .filter(req -> req.getOwnerId().equals(relation.getRequirementOwnerId()) && req.getName().equals(relation.getRequirement()) && req.getUniqueId().equals(relation.getRequirementId())).findFirst();
1397
1398             if (requirementOptional.isPresent()) {
1399
1400                 RequirementDataDefinition requirement = requirementOptional.get();
1401                 String leftOccurrences = requirement.getLeftOccurrences();
1402                 if (leftOccurrences != null && !leftOccurrences.equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
1403                     Integer leftIntValue = Integer.parseInt(leftOccurrences);
1404                     ++leftIntValue;
1405                     requirement.setLeftOccurrences(String.valueOf(leftIntValue));
1406                 }
1407                 if (relationship != null) {
1408                     relationship.setRequirement(requirement);
1409                 }
1410                 status = StorageOperationStatus.OK;
1411             } else {
1412                 // move from fulfilled
1413                 status = moveFromFullFilledRequirement(calculatedRequirement, fullFilledRequirement, fromResInstanceUid, relation, hereIsTheKey, relationship);
1414             }
1415         }
1416         return status;
1417     }
1418
1419     private StorageOperationStatus updateCalculatedCapabiltyAfterDeleteRelation(Map<String, MapListCapabilityDataDefinition> calculatedCapability, Map<String, MapListCapabilityDataDefinition> fullFilledCapability, String toResInstanceUid,
1420             RelationshipInstDataDefinition relation, CapabilityRequirementRelationship relationship) {
1421         StorageOperationStatus status;
1422         String hereIsTheKey = null;
1423         MapListCapabilityDataDefinition capByInstance = calculatedCapability.get(toResInstanceUid);
1424         if (capByInstance == null || capByInstance.findKeyByItemUidMatch(relation.getCapabilityId()) == null) {
1425             // move from fulfilled
1426             status = moveFromFullFilledCapabilty(calculatedCapability, fullFilledCapability, toResInstanceUid, relation, hereIsTheKey, relationship);
1427         } else {
1428             hereIsTheKey = capByInstance.findKeyByItemUidMatch(relation.getCapabilityId());
1429             ListCapabilityDataDefinition capByType = capByInstance.findByKey(hereIsTheKey);
1430             Optional<CapabilityDataDefinition> capabilityOptional = capByType.getListToscaDataDefinition().stream().filter(cap -> cap.getOwnerId().equals(relation.getCapabilityOwnerId()) && cap.getUniqueId().equals(relation.getCapabilityId()))
1431                     .findFirst();
1432
1433             if (capabilityOptional.isPresent()) {
1434
1435                 CapabilityDataDefinition capability = capabilityOptional.get();
1436                 String leftOccurrences = capability.getLeftOccurrences();
1437                 if (leftOccurrences != null && !leftOccurrences.equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
1438                     Integer leftIntValue = Integer.parseInt(leftOccurrences);
1439                     ++leftIntValue;
1440                     capability.setLeftOccurrences(String.valueOf(leftIntValue));
1441                 }
1442                 if (relationship != null) {
1443                     relationship.setCapability(capability);
1444                 }
1445                 status = StorageOperationStatus.OK;
1446             } else {
1447                 // move from fulfilled
1448                 status = moveFromFullFilledCapabilty(calculatedCapability, fullFilledCapability, toResInstanceUid, relation, hereIsTheKey, relationship);
1449             }
1450         }
1451         return status;
1452     }
1453
1454     private StorageOperationStatus moveFromFullFilledCapabilty(Map<String, MapListCapabilityDataDefinition> calculatedCapability, Map<String, MapListCapabilityDataDefinition> fullFilledCapability, String toResInstanceUid,
1455             RelationshipInstDataDefinition relation, String hereIsTheKey, CapabilityRequirementRelationship relationship) {
1456         MapListCapabilityDataDefinition capByInstance = fullFilledCapability.get(toResInstanceUid);
1457         if (capByInstance == null) {
1458             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No capability in fulfilled list for instance {} ", toResInstanceUid);
1459             return StorageOperationStatus.GENERAL_ERROR;
1460         }
1461         if (null == hereIsTheKey)
1462             hereIsTheKey = capByInstance.findKeyByItemUidMatch(relation.getCapabilityId());
1463         if (null == hereIsTheKey) {
1464             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No capability with id {} in fulfilled list for instance {} ", relation.getCapabilityId(), toResInstanceUid);
1465             return StorageOperationStatus.GENERAL_ERROR;
1466         }
1467         ListCapabilityDataDefinition capByType = capByInstance.findByKey(hereIsTheKey);
1468         Iterator<CapabilityDataDefinition> iterator = capByType.getListToscaDataDefinition().iterator();
1469         boolean found = false;
1470         while (iterator.hasNext()) {
1471             CapabilityDataDefinition cap = iterator.next();
1472             if (cap.getOwnerId().equals(relation.getCapabilityOwnerId()) && cap.getUniqueId().equals(relation.getCapabilityId())) {
1473                 found = true;
1474                 iterator.remove();
1475                 // return to calculated list
1476                 String leftOccurrences = cap.getLeftOccurrences();
1477                 Integer leftIntValue = Integer.parseInt(leftOccurrences);
1478                 ++leftIntValue;
1479                 cap.setLeftOccurrences(String.valueOf(leftIntValue));
1480
1481                 MapListCapabilityDataDefinition mapListCapaDataDef = calculatedCapability.get(toResInstanceUid);
1482                 if (mapListCapaDataDef == null) {
1483                     mapListCapaDataDef = new MapListCapabilityDataDefinition();
1484                 }
1485                 ListCapabilityDataDefinition findByKey = mapListCapaDataDef.findByKey(hereIsTheKey);
1486                 if (findByKey == null) {
1487                     findByKey = new ListCapabilityDataDefinition();
1488                     mapListCapaDataDef.put(hereIsTheKey, findByKey);
1489                 }
1490                 findByKey.add(cap);
1491                 if (relationship != null)
1492                     relationship.setCapability(cap);
1493                 break;
1494             }
1495         }
1496         if (!found) {
1497             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No capability type {} with ownerId {} in fulfilled list for instance {} ", hereIsTheKey, relation.getCapabilityOwnerId(), toResInstanceUid);
1498             return StorageOperationStatus.GENERAL_ERROR;
1499         }
1500         return StorageOperationStatus.OK;
1501     }
1502
1503     private StorageOperationStatus moveFromFullFilledRequirement(Map<String, MapListRequirementDataDefinition> calculatedRequirement, Map<String, MapListRequirementDataDefinition> fullFilledRequirement, String fromResInstanceUid,
1504             RelationshipInstDataDefinition relation, String hereIsTheKey, CapabilityRequirementRelationship relationship) {
1505         MapListRequirementDataDefinition reqByInstance = fullFilledRequirement.get(fromResInstanceUid);
1506         if (reqByInstance == null) {
1507             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No requirement in fullfilled list for instance {} ", fromResInstanceUid);
1508             return StorageOperationStatus.GENERAL_ERROR;
1509         }
1510         if (null == hereIsTheKey)
1511             hereIsTheKey = reqByInstance.findKeyByItemUidMatch(relation.getRequirementId());
1512         if (null == hereIsTheKey) {
1513             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No requirement with id {} in fulfilled list for instance {} ", relation.getRequirementId(), fromResInstanceUid);
1514             return StorageOperationStatus.GENERAL_ERROR;
1515         }
1516         ListRequirementDataDefinition reqByType = reqByInstance.findByKey(hereIsTheKey);
1517         Iterator<RequirementDataDefinition> iterator = reqByType.getListToscaDataDefinition().iterator();
1518         boolean found = false;
1519         while (iterator.hasNext()) {
1520             RequirementDataDefinition req = iterator.next();
1521             if (req.getOwnerId().equals(relation.getRequirementOwnerId()) && req.getName().equals(relation.getRequirement()) && req.getUniqueId().equals(relation.getRequirementId())) {
1522                 found = true;
1523                 iterator.remove();
1524                 // return to calculated list
1525                 String leftOccurrences = req.getLeftOccurrences();
1526                 Integer leftIntValue = Integer.parseInt(leftOccurrences);
1527                 ++leftIntValue;
1528                 req.setLeftOccurrences(String.valueOf(leftIntValue));
1529
1530                 MapListRequirementDataDefinition mapListReqDataDef = calculatedRequirement.get(fromResInstanceUid);
1531                 if (mapListReqDataDef == null) {
1532                     mapListReqDataDef = new MapListRequirementDataDefinition();
1533                 }
1534                 ListRequirementDataDefinition findByKey = mapListReqDataDef.findByKey(hereIsTheKey);
1535                 if (findByKey == null) {
1536                     findByKey = new ListRequirementDataDefinition();
1537                     mapListReqDataDef.put(hereIsTheKey, findByKey);
1538                 }
1539                 findByKey.add(req);
1540                 if (relationship != null)
1541                     relationship.setRequirement(req);
1542                 break;
1543             }
1544         }
1545         if (!found) {
1546             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No requirement type {} with ownerId {} in fulfilled list for instance {} ", hereIsTheKey, relation.getRequirementOwnerId(), fromResInstanceUid);
1547             return StorageOperationStatus.GENERAL_ERROR;
1548         }
1549         return StorageOperationStatus.OK;
1550
1551     }
1552
1553     public StorageOperationStatus updateCustomizationUUID(String componentInstanceId, CompositionDataDefinition compositionDataDefinition) {
1554         ComponentInstanceDataDefinition componentInstance = compositionDataDefinition.getComponentInstances().get(componentInstanceId);
1555
1556         if (componentInstance == null) {
1557             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component instance by id {} from map of instances ", componentInstanceId);
1558             return StorageOperationStatus.NOT_FOUND;
1559         }
1560         UUID uuid = UUID.randomUUID();
1561         componentInstance.setCustomizationUUID(uuid.toString());
1562
1563         return StorageOperationStatus.OK;
1564     }
1565
1566     public <T extends ToscaDataDefinition> Either<Map<JsonPresentationFields, T>, StorageOperationStatus> connectInstancesInContainer(String fromResInstanceUid, String toResInstanceUid, RelationshipInfo relationPair, boolean originUI,
1567             Map<String, MapListCapabilityDataDefinition> calculatedCapabilty, Map<String, MapListRequirementDataDefinition> calculatedRequirement, Map<String, MapListCapabilityDataDefinition> fullfilledCapabilty,
1568             Map<String, MapListRequirementDataDefinition> fullfilledRequirement, CompositionDataDefinition compositionDataDefinition, String containerId) {
1569         String requirement = relationPair.getRequirement();
1570         Map<String, ComponentInstanceDataDefinition> componentInstances = compositionDataDefinition.getComponentInstances();
1571
1572         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Going to associate resource instance {} to resource instance {} under component {}. Requirement is {}.", fromResInstanceUid, toResInstanceUid, containerId, requirement);
1573
1574         ComponentInstanceDataDefinition fromResourceInstData = componentInstances.get(fromResInstanceUid);
1575         if (fromResourceInstData == null) {
1576             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find from resource instance {}.", fromResInstanceUid);
1577             return Either.right(StorageOperationStatus.NOT_FOUND);
1578         }
1579         ComponentInstanceDataDefinition toResourceInstData = componentInstances.get(toResInstanceUid);
1580         if (toResourceInstData == null) {
1581             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find to resource instance {}.", toResInstanceUid);
1582             return Either.right(StorageOperationStatus.NOT_FOUND);
1583         }
1584
1585         Either<Map<JsonPresentationFields, T>, StorageOperationStatus> reqVsCap = connectRequirementVsCapability(fromResourceInstData, toResourceInstData, relationPair, originUI, calculatedCapabilty, calculatedRequirement, fullfilledCapabilty,
1586                 fullfilledRequirement, containerId);
1587         if (reqVsCap.isRight()) {
1588             StorageOperationStatus status = reqVsCap.right().value();
1589             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to connect requirement {} between resource instance {} to resource instance {}. status is {}", requirement, fromResInstanceUid, toResInstanceUid, status);
1590             return Either.right(status);
1591         }
1592         Map<JsonPresentationFields, T> relationship = reqVsCap.left().value();
1593
1594         // add to json new relations
1595         compositionDataDefinition.addRelation(((RelationshipInstDataDefinition) relationship.get(JsonPresentationFields.RELATIONSHIP)).getUniqueId(), (RelationshipInstDataDefinition) relationship.get(JsonPresentationFields.RELATIONSHIP));
1596
1597         return Either.left(relationship);
1598     }
1599
1600     private Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, StorageOperationStatus> fetchContainerCalculatedCapability(GraphVertex containerV, EdgeLabelEnum capLabel) {
1601
1602         Either<Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>>, TitanOperationStatus> calculatedCapabiltyEither = getDataAndVertexFromGraph(containerV, capLabel);
1603         if (calculatedCapabiltyEither.isRight()) {
1604             TitanOperationStatus error = calculatedCapabiltyEither.right().value();
1605             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch calculated capabilties for container {}.", containerV.getUniqueId(), error);
1606             return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
1607         }
1608         Pair<GraphVertex, Map<String, MapListCapabilityDataDefinition>> calculatedCapabilty = calculatedCapabiltyEither.left().value();
1609         return Either.left(calculatedCapabilty);
1610     }
1611
1612     private Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, StorageOperationStatus> fetchContainerCalculatedRequirement(GraphVertex containerV, EdgeLabelEnum reqLabel) {
1613         Either<Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>>, TitanOperationStatus> calculatedRequirementEither = getDataAndVertexFromGraph(containerV, reqLabel);
1614         if (calculatedRequirementEither.isRight()) {
1615             TitanOperationStatus error = calculatedRequirementEither.right().value();
1616             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch calculated requirements for container {}.", containerV.getUniqueId(), error);
1617             return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
1618         }
1619         Pair<GraphVertex, Map<String, MapListRequirementDataDefinition>> calculatedRequirement = calculatedRequirementEither.left().value();
1620         return Either.left(calculatedRequirement);
1621     }
1622
1623     @SuppressWarnings("unchecked")
1624     private <T extends ToscaDataDefinition> Either<Map<JsonPresentationFields, T>, StorageOperationStatus> connectRequirementVsCapability(ComponentInstanceDataDefinition fromResInstance, ComponentInstanceDataDefinition toResInstance,
1625             RelationshipInfo relationPair, boolean originUI, Map<String, MapListCapabilityDataDefinition> calculatedCapabilty, Map<String, MapListRequirementDataDefinition> calculatedRequirement,
1626             Map<String, MapListCapabilityDataDefinition> fullfilledCapabilty, Map<String, MapListRequirementDataDefinition> fullfilledRequirement, String containerId) {
1627         String type = relationPair.getRelationship().getType();
1628         // capability
1629
1630         String toInstId = toResInstance.getUniqueId();
1631         MapListCapabilityDataDefinition MapListCapabilityDataDefinition = calculatedCapabilty.get(toInstId);
1632         Map<JsonPresentationFields, T> capReqRelationship = new EnumMap<>(JsonPresentationFields.class);
1633
1634         if (MapListCapabilityDataDefinition == null) {
1635             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch calculated capabilities for instance {} in container {}.", toInstId, containerId);
1636             return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1637         }
1638         ListCapabilityDataDefinition listCapabilityDataDefinition = MapListCapabilityDataDefinition.getMapToscaDataDefinition().get(type);
1639         if (listCapabilityDataDefinition == null) {
1640             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch calculated capabilities for type {} for instance {} in container {}.", type, toInstId, containerId);
1641             return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1642         }
1643         CapabilityDataDefinition capabilityForRelation = null;
1644         Iterator<CapabilityDataDefinition> iteratorCap = listCapabilityDataDefinition.getListToscaDataDefinition().iterator();
1645         while (iteratorCap.hasNext()) {
1646             CapabilityDataDefinition cap = iteratorCap.next();
1647             if (cap.getUniqueId().equals(relationPair.getCapabilityUid()) && cap.getOwnerId().equals(relationPair.getCapabilityOwnerId())) {
1648                 capabilityForRelation = cap;
1649                 capReqRelationship.put(JsonPresentationFields.CAPAPILITY, (T) capabilityForRelation);
1650                 String leftOccurrences = cap.getLeftOccurrences();
1651                 if (leftOccurrences != null && !leftOccurrences.equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
1652                     Integer leftIntValue = Integer.parseInt(leftOccurrences);
1653                     if (leftIntValue > 0) {
1654                         --leftIntValue;
1655                         capabilityForRelation.setLeftOccurrences(String.valueOf(leftIntValue));
1656                         if (leftIntValue == 0) {
1657                             // remove from calculated
1658                             iteratorCap.remove();
1659                             // move to fulfilled
1660                             MapListCapabilityDataDefinition mapListCapabiltyFullFilledInst = fullfilledCapabilty.get(toInstId);
1661                             if (mapListCapabiltyFullFilledInst == null) {
1662                                 mapListCapabiltyFullFilledInst = new MapListCapabilityDataDefinition();
1663                                 fullfilledCapabilty.put(toInstId, mapListCapabiltyFullFilledInst);
1664                             }
1665
1666                             ListCapabilityDataDefinition listCapabilityFull = mapListCapabiltyFullFilledInst.findByKey(type);
1667                             if (listCapabilityFull == null) {
1668                                 listCapabilityFull = new ListCapabilityDataDefinition();
1669                                 mapListCapabiltyFullFilledInst.put(type, listCapabilityFull);
1670                             }
1671                             listCapabilityFull.add(capabilityForRelation);
1672                         }
1673                         break;
1674                     } else {
1675                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No left occurrences capabilty {} to {} in container {}.", capabilityForRelation.getType(), toInstId, containerId);
1676                         return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1677                     }
1678                 }
1679             }
1680         }
1681         if (capabilityForRelation == null) {
1682             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch capabilty for type {} for instance {} in container {}.", type, toInstId, containerId);
1683             return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1684         }
1685
1686         // requirements
1687         String fromInstId = fromResInstance.getUniqueId();
1688         MapListRequirementDataDefinition mapListRequirementDataDefinition = calculatedRequirement.get(fromInstId);
1689         if (mapListRequirementDataDefinition == null) {
1690             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch calculated requirements for instance {} in container {}.", fromInstId, containerId);
1691             return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1692         }
1693         ListRequirementDataDefinition listRequirementDataDefinition = mapListRequirementDataDefinition.getMapToscaDataDefinition().get(type);
1694         if (listRequirementDataDefinition == null) {
1695             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch calculated requirements for type {} for instance {} in container {}.", type, fromInstId, containerId);
1696             return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1697         }
1698
1699         RequirementDataDefinition requirementForRelation = null;
1700         Iterator<RequirementDataDefinition> iteratorReq = listRequirementDataDefinition.getListToscaDataDefinition().iterator();
1701         while (iteratorReq.hasNext()) {
1702             RequirementDataDefinition req = iteratorReq.next();
1703             if (req.getUniqueId().equals(relationPair.getRequirementUid()) && req.getOwnerId().equals(relationPair.getRequirementOwnerId())) {
1704                 requirementForRelation = req;
1705                 capReqRelationship.put(JsonPresentationFields.REQUIREMENT, (T) requirementForRelation);
1706                 String leftOccurrences = req.getLeftOccurrences();
1707                 if (leftOccurrences != null && !leftOccurrences.equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
1708                     Integer leftIntValue = Integer.parseInt(leftOccurrences);
1709                     if (leftIntValue > 0) {
1710                         --leftIntValue;
1711                         req.setLeftOccurrences(String.valueOf(leftIntValue));
1712                         if (leftIntValue == 0) {
1713                             // remove from calculated
1714                             iteratorReq.remove();
1715                             // move to fulfilled
1716                             MapListRequirementDataDefinition mapListRequirementFullFilledInst = fullfilledRequirement.get(fromInstId);
1717                             if (mapListRequirementFullFilledInst == null) {
1718                                 mapListRequirementFullFilledInst = new MapListRequirementDataDefinition();
1719                                 fullfilledRequirement.put(fromInstId, mapListRequirementFullFilledInst);
1720                             }
1721
1722                             ListRequirementDataDefinition listRequirementFull = mapListRequirementFullFilledInst.findByKey(type);
1723                             if (listRequirementFull == null) {
1724                                 listRequirementFull = new ListRequirementDataDefinition();
1725                                 mapListRequirementFullFilledInst.put(type, listRequirementFull);
1726                             }
1727                             listRequirementFull.add(requirementForRelation);
1728                         }
1729                         break;
1730                     } else {
1731                         CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No left occurrences requirement {} from {} to {} in container {}.", requirementForRelation.getCapability(), fromInstId, toInstId, containerId);
1732                         return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1733                     }
1734                 }
1735             }
1736         }
1737         if (requirementForRelation == null) {
1738             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch requirement for type {} for instance {} in container {}.", type, toInstId, containerId);
1739             return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1740         }
1741         if (!capabilityForRelation.getType().equals(requirementForRelation.getCapability())) {
1742             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "No macth for capability from type {} and requirement {} from {} to {} in container {}.", capabilityForRelation.getType(), requirementForRelation.getCapability(), fromInstId, toInstId,
1743                     containerId);
1744             return Either.right(StorageOperationStatus.MATCH_NOT_FOUND);
1745         }
1746
1747         RelationshipInstDataDefinition relationshipTypeData = buildRelationshipInstData(fromInstId, toInstId, relationPair, originUI);
1748         if (requirementForRelation.getRelationship() != null)
1749             relationshipTypeData.setType(requirementForRelation.getRelationship());
1750         capReqRelationship.put(JsonPresentationFields.RELATIONSHIP, (T) relationshipTypeData);
1751         return Either.left(capReqRelationship);
1752     }
1753
1754     private RelationshipInstDataDefinition buildRelationshipInstData(String fromResInstanceUid, String toInstId, RelationshipInfo relationPair, boolean originUI) {
1755
1756         RelationshipInstDataDefinition relationshipInstData = new RelationshipInstDataDefinition();
1757         relationshipInstData.setUniqueId(UniqueIdBuilder.buildRelationsipInstInstanceUid(fromResInstanceUid, toInstId));
1758
1759         relationshipInstData.setType(relationPair.getRelationship().getType());
1760         Long creationDate = System.currentTimeMillis();
1761         relationshipInstData.setCreationTime(creationDate);
1762         relationshipInstData.setModificationTime(creationDate);
1763         relationshipInstData.setCapabilityOwnerId(relationPair.getCapabilityOwnerId());
1764         relationshipInstData.setRequirementOwnerId(relationPair.getRequirementOwnerId());
1765         relationshipInstData.setCapabilityId(relationPair.getCapabilityUid());
1766         relationshipInstData.setRequirementId(relationPair.getRequirementUid());
1767         relationshipInstData.setFromId(fromResInstanceUid);
1768         relationshipInstData.setToId(toInstId);
1769         relationshipInstData.setRequirement(relationPair.getRequirement());
1770         relationshipInstData.setCapability(relationPair.getCapability());
1771         relationshipInstData.setOriginUI(originUI);
1772
1773         return relationshipInstData;
1774     }
1775
1776     public StorageOperationStatus associateComponentInstancesToComponent(Component containerComponent, Map<ComponentInstance, Resource> resourcesInstancesMap, GraphVertex containerVertex, boolean allowDeleted) {
1777
1778         StorageOperationStatus result = null;
1779         String containerId = containerComponent.getUniqueId();
1780         Map<String, ComponentInstanceDataDefinition> instancesJsonData = null;
1781         Either<GraphVertex, TitanOperationStatus> updateElement = null;
1782         if (!validateInstanceNames(resourcesInstancesMap)) {
1783             result = StorageOperationStatus.INCONSISTENCY;
1784         }
1785         if (result == null) {
1786             if (!validateInstanceNames(resourcesInstancesMap)) {
1787                 result = StorageOperationStatus.INCONSISTENCY;
1788             }
1789         }
1790         if (result == null && !allowDeleted) {
1791             if (!validateDeletedResources(resourcesInstancesMap)) {
1792                 result = StorageOperationStatus.INCONSISTENCY;
1793             }
1794         }
1795         if (result == null) {
1796             instancesJsonData = convertToComponentInstanceDataDefinition(resourcesInstancesMap, containerId);
1797         }
1798         if (result == null && MapUtils.isNotEmpty(instancesJsonData)) {
1799             containerVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
1800             Map<String, CompositionDataDefinition> compositions = new HashMap<>();
1801             CompositionDataDefinition composition = new CompositionDataDefinition();
1802             composition.setComponentInstances(instancesJsonData);
1803             compositions.put(JsonConstantKeysEnum.COMPOSITION.getValue(), composition);
1804             containerVertex.setJson(compositions);
1805             updateElement = titanDao.updateVertex(containerVertex);
1806             if (updateElement.isRight()) {
1807                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update topology template {} with new component instances. ", containerComponent.getName());
1808                 result = DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value());
1809             }
1810         }
1811         if (result == null && updateElement != null) {
1812             GraphVertex vertexC = updateElement.left().value();
1813             instancesJsonData.entrySet().forEach(i ->createInstanceEdge(vertexC, i.getValue()));
1814             result = StorageOperationStatus.OK;
1815         }
1816         return result;
1817     }
1818
1819     private Map<String, ComponentInstanceDataDefinition> convertToComponentInstanceDataDefinition(Map<ComponentInstance, Resource> resourcesInstancesMap, String containerId) {
1820
1821         Map<String, ComponentInstanceDataDefinition> instances = new HashMap<>();
1822         for (Entry<ComponentInstance, Resource> entry : resourcesInstancesMap.entrySet()) {
1823             ComponentInstanceDataDefinition instance = buildComponentInstanceDataDefinition(entry.getKey(), containerId, null, true, ModelConverter.convertToToscaElement(entry.getValue()));
1824             instances.put(instance.getUniqueId(), instance);
1825         }
1826         return instances;
1827     }
1828
1829     private boolean validateDeletedResources(Map<ComponentInstance, Resource> resourcesInstancesMap) {
1830         boolean result = true;
1831         for (Resource resource : resourcesInstancesMap.values()) {
1832             if (resource.getIsDeleted() != null && resource.getIsDeleted()) {
1833                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component {} is already deleted. Cannot add component instance. ", resource.getName());
1834                 result = false;
1835                 break;
1836             }
1837         }
1838         return result;
1839     }
1840
1841     private boolean validateInstanceNames(Map<ComponentInstance, Resource> resourcesInstancesMap) {
1842         boolean result = true;
1843         Set<String> names = new HashSet<>();
1844         for (ComponentInstance instance : resourcesInstancesMap.keySet()) {
1845             if (StringUtils.isEmpty(instance.getName())) {
1846                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component instance {} name is empty. Cannot add component instance. ", instance.getUniqueId());
1847                 result = false;
1848                 break;
1849             } else if (names.contains(instance.getName())) {
1850                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component instance with the name {} already exsists. Cannot add component instance. ", instance.getName());
1851                 result = false;
1852                 break;
1853             } else {
1854                 names.add(instance.getName());
1855             }
1856         }
1857         return result;
1858     }
1859
1860     public StorageOperationStatus addDeploymentArtifactsToInstance(String toscaElementId, String instanceId, Map<String, ArtifactDataDefinition> instDeplArtifacts) {
1861         return addArtifactsToInstance(toscaElementId, instanceId, instDeplArtifacts, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS, VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS);
1862     }
1863
1864     public StorageOperationStatus addInformationalArtifactsToInstance(String toscaElementId, String instanceId, Map<String, ArtifactDataDefinition> instDeplArtifacts) {
1865         return addArtifactsToInstance(toscaElementId, instanceId, instDeplArtifacts, EdgeLabelEnum.INSTANCE_ARTIFACTS, VertexTypeEnum.INSTANCE_ARTIFACTS);
1866     }
1867
1868     public StorageOperationStatus addArtifactsToInstance(String toscaElementId, String instanceId, Map<String, ArtifactDataDefinition> instDeplArtifacts, EdgeLabelEnum edgeLabel, VertexTypeEnum vertexType) {
1869         Either<GraphVertex, TitanOperationStatus> metadataVertex = titanDao.getVertexById(toscaElementId, JsonParseFlagEnum.NoParse);
1870         if (metadataVertex.isRight()) {
1871             TitanOperationStatus status = metadataVertex.right().value();
1872             if (status == TitanOperationStatus.NOT_FOUND) {
1873                 status = TitanOperationStatus.INVALID_ID;
1874             }
1875             return DaoStatusConverter.convertTitanStatusToStorageStatus(status);
1876         }
1877         MapArtifactDataDefinition instArtifacts = new MapArtifactDataDefinition(instDeplArtifacts);
1878         return addToscaDataDeepElementsBlockToToscaElement(metadataVertex.left().value(), edgeLabel, vertexType, instArtifacts, instanceId);
1879
1880     }
1881
1882     @SuppressWarnings({ "unchecked" })
1883     public StorageOperationStatus generateCustomizationUUIDOnInstance(String componentId, String instanceId) {
1884         Either<GraphVertex, TitanOperationStatus> metadataVertex = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll);
1885         if (metadataVertex.isRight()) {
1886             TitanOperationStatus status = metadataVertex.right().value();
1887             if (status == TitanOperationStatus.NOT_FOUND) {
1888                 status = TitanOperationStatus.INVALID_ID;
1889             }
1890             return DaoStatusConverter.convertTitanStatusToStorageStatus(status);
1891         }
1892         GraphVertex metaVertex = metadataVertex.left().value();
1893         Map<String, CompositionDataDefinition> json = (Map<String, CompositionDataDefinition>) metaVertex.getJson();
1894         CompositionDataDefinition compositionDataDefinition = json.get(JsonConstantKeysEnum.COMPOSITION.getValue());
1895         StorageOperationStatus status = updateCustomizationUUID(instanceId, compositionDataDefinition);
1896         if (status != StorageOperationStatus.OK) {
1897             log.debug("Failed to update customization UUID for instance {} in component {} error {}", instanceId, componentId, status);
1898             return status;
1899         }
1900         Either<GraphVertex, TitanOperationStatus> updateVertex = titanDao.updateVertex(metaVertex);
1901         if (updateVertex.isRight()) {
1902             log.debug("Failed to update vertex of component {} error {}", componentId, updateVertex.right().value());
1903             return DaoStatusConverter.convertTitanStatusToStorageStatus(updateVertex.right().value());
1904         }
1905         return StorageOperationStatus.OK;
1906     }
1907
1908     public StorageOperationStatus generateCustomizationUUIDOnInstanceGroup(String componentId, String instanceId, List<String> groupInstances) {
1909         if (groupInstances != null) {
1910             Either<Map<String, MapGroupsDataDefinition>, TitanOperationStatus> dataFromGraph = getDataFromGraph(componentId, EdgeLabelEnum.INST_GROUPS);
1911             if (dataFromGraph.isRight()) {
1912                 return DaoStatusConverter.convertTitanStatusToStorageStatus(dataFromGraph.right().value());
1913             }
1914             MapGroupsDataDefinition grInstPerInstance = dataFromGraph.left().value().get(instanceId);
1915             if (grInstPerInstance == null) {
1916                 log.debug("No  instance groups for instance {} in component {}", instanceId, componentId);
1917                 return StorageOperationStatus.NOT_FOUND;
1918             }
1919             for (String instGroupForUpdate : groupInstances) {
1920                 GroupInstanceDataDefinition groupInst = grInstPerInstance.findByKey(instGroupForUpdate);
1921                 if (groupInst == null) {
1922                     log.debug("No group instance {} in group list  for instance {} in component {}", instGroupForUpdate, instanceId, componentId);
1923                     continue;
1924                 }
1925                 UUID uuid = UUID.randomUUID();
1926                 groupInst.setCustomizationUUID(uuid.toString());
1927             }
1928
1929         }
1930         return StorageOperationStatus.OK;
1931     }
1932
1933     public StorageOperationStatus addGroupInstancesToComponentInstance(Component containerComponent, ComponentInstance componentInstance, List<GroupInstance> groupInstances) {
1934
1935         return addToscaDataDeepElementsBlockToToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS,
1936                 new MapDataDefinition<>(groupInstances.stream().collect(Collectors.toMap(GroupInstanceDataDefinition::getName, gi -> gi))), componentInstance.getUniqueId());
1937     }
1938
1939     public StorageOperationStatus addDeploymentArtifactsToComponentInstance(Component containerComponent, ComponentInstance componentInstance, Map<String, ArtifactDefinition> deploymentArtifacts) {
1940
1941         return addToscaDataDeepElementsBlockToToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS, VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS, new MapDataDefinition<>(deploymentArtifacts),
1942                 componentInstance.getUniqueId());
1943     }
1944
1945     public StorageOperationStatus updateComponentInstanceProperty(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property) {
1946
1947         List<String> pathKeys = new ArrayList<>();
1948         pathKeys.add(componentInstanceId);
1949         return updateToscaDataDeepElementOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_PROPERTIES, VertexTypeEnum.INST_PROPERTIES, property, pathKeys, JsonPresentationFields.NAME);
1950     }
1951
1952     public StorageOperationStatus updateComponentInstanceCapabilityProperty(Component containerComponent, String componentInstanceId, String capabilityUniqueId, ComponentInstanceProperty property) {
1953         List<String> pathKeys = new ArrayList<>();
1954         pathKeys.add(componentInstanceId);
1955         pathKeys.add(capabilityUniqueId);
1956         return updateToscaDataDeepElementOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, property, pathKeys, JsonPresentationFields.NAME);
1957     }
1958
1959     public StorageOperationStatus overrideComponentCapabilitiesProperties(Component containerComponent, Map<String, MapCapabilityProperty> capabilityPropertyMap) {
1960         return overrideToscaDataOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, capabilityPropertyMap);
1961     }
1962
1963     public StorageOperationStatus addComponentInstanceProperty(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property) {
1964         List<String> pathKeys = new ArrayList<>();
1965         pathKeys.add(componentInstanceId);
1966         return addToscaDataDeepElementToToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_PROPERTIES, VertexTypeEnum.INST_PROPERTIES, property, pathKeys, JsonPresentationFields.NAME);
1967     }
1968
1969     public StorageOperationStatus updateComponentInstanceProperties(Component containerComponent, String componentInstanceId, List<ComponentInstanceProperty> properties) {
1970         List<String> pathKeys = new ArrayList<>();
1971         pathKeys.add(componentInstanceId);
1972         return updateToscaDataDeepElementsOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_PROPERTIES, VertexTypeEnum.INST_PROPERTIES, properties, pathKeys, JsonPresentationFields.NAME);
1973     }
1974
1975     public StorageOperationStatus updateComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) {
1976
1977         List<String> pathKeys = new ArrayList<>();
1978         pathKeys.add(componentInstanceId);
1979         return updateToscaDataDeepElementOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_INPUTS, VertexTypeEnum.INST_INPUTS, property, pathKeys, JsonPresentationFields.NAME);
1980     }
1981
1982     public StorageOperationStatus updateComponentInstanceInputs(Component containerComponent, String componentInstanceId, List<ComponentInstanceInput> properties) {
1983         List<String> pathKeys = new ArrayList<>();
1984         pathKeys.add(componentInstanceId);
1985         return updateToscaDataDeepElementsOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_INPUTS, VertexTypeEnum.INST_INPUTS, properties, pathKeys, JsonPresentationFields.NAME);
1986     }
1987
1988     public StorageOperationStatus addComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) {
1989         List<String> pathKeys = new ArrayList<>();
1990         pathKeys.add(componentInstanceId);
1991         return addToscaDataDeepElementToToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_INPUTS, VertexTypeEnum.INST_INPUTS, property, pathKeys, JsonPresentationFields.NAME);
1992     }
1993
1994     public StorageOperationStatus createInstanceEdge(GraphVertex metadataVertex, ComponentInstanceDataDefinition componentInstance) {
1995         String instUniqueId = componentInstance.getUniqueId();
1996
1997         // create edge between container and origin ( in case of proxy this edge will be to ProxyService node type)
1998         StorageOperationStatus result = createOrUpdateInstanceEdge(metadataVertex, EdgeLabelEnum.INSTANCE_OF, componentInstance.getComponentUid(), instUniqueId).either(v -> StorageOperationStatus.OK,
1999                  DaoStatusConverter::convertTitanStatusToStorageStatus);
2000
2001         if (result == StorageOperationStatus.OK && componentInstance.getIsProxy()) {
2002                 // create edge between container and service origin
2003                 result = createOrUpdateInstanceEdge(metadataVertex, EdgeLabelEnum.PROXY_OF, componentInstance.getSourceModelUid(), instUniqueId)
2004                         .either(v -> StorageOperationStatus.OK, DaoStatusConverter::convertTitanStatusToStorageStatus);
2005         }
2006         return result;
2007     }
2008
2009     public StorageOperationStatus createAllottedOfEdge(String componentId, String instanceId, String serviceUUID) {
2010         Either<GraphVertex, TitanOperationStatus> vertexById = titanDao.getVertexById(componentId);
2011         if ( vertexById.isRight() ){
2012             log.debug("Failed to fetch component metadata vertex for id {} error {}", componentId, vertexById.right().value());
2013             return DaoStatusConverter.convertTitanStatusToStorageStatus(vertexById.right().value());
2014         }
2015         GraphVertex metadataVertex = vertexById.left().value(); 
2016
2017         EnumMap<GraphPropertyEnum, Object> props = new EnumMap<>(GraphPropertyEnum.class);
2018         props.put(GraphPropertyEnum.UUID, serviceUUID);
2019         props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
2020   
2021         EnumMap<GraphPropertyEnum, Object> hasNot = new EnumMap<>(GraphPropertyEnum.class);
2022         hasNot.put(GraphPropertyEnum.IS_DELETED, true);
2023
2024         Either<List<GraphVertex>, TitanOperationStatus> byCriteria = titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, props,hasNot, JsonParseFlagEnum.ParseMetadata );
2025         if ( byCriteria.isRight() ){
2026             log.debug("Failed to fetch vertex by criteria {} error {}", props, byCriteria.right().value());
2027             return DaoStatusConverter.convertTitanStatusToStorageStatus(byCriteria.right().value());
2028         }
2029         List<GraphVertex> vertecies = byCriteria.left().value();
2030         StorageOperationStatus result = StorageOperationStatus.OK;
2031         if ( vertecies != null ){
2032             GraphVertex serviceVertex = vertecies.get(0);
2033             //remove previous edges
2034             
2035             log.debug("Try to create or update edge between resource {} and service {} ", metadataVertex, serviceVertex.getUniqueId());
2036             // create edge between container and service reference
2037             result = createOrUpdateInstanceEdge(metadataVertex, EdgeLabelEnum.ALLOTTED_OF, serviceVertex.getUniqueId(), instanceId).either(v -> StorageOperationStatus.OK,
2038                     DaoStatusConverter::convertTitanStatusToStorageStatus);
2039         }
2040         return result;
2041     }
2042     
2043     
2044     public StorageOperationStatus removeInstanceEdge(GraphVertex metadataVertex, ComponentInstanceDataDefinition componentInstance) {
2045         String instUniqueId = componentInstance.getUniqueId();
2046
2047         // create edge between container and origin ( in case of proxy this edge will be to ProxyService node type)
2048         StorageOperationStatus result = removeOrUpdateInstanceEdge(metadataVertex, EdgeLabelEnum.INSTANCE_OF, componentInstance.getComponentUid(), instUniqueId)
2049                 .either(v -> StorageOperationStatus.OK,
2050                 DaoStatusConverter::convertTitanStatusToStorageStatus);
2051
2052         if (componentInstance.getIsProxy()) {
2053             // create edge between container and service origin
2054             result = removeOrUpdateInstanceEdge(metadataVertex, EdgeLabelEnum.PROXY_OF, componentInstance.getSourceModelUid(), instUniqueId)
2055                     .either(v -> StorageOperationStatus.OK, DaoStatusConverter::convertTitanStatusToStorageStatus);
2056         }
2057         return result;
2058     }
2059
2060     private Either<GraphVertex, TitanOperationStatus> createOrUpdateInstanceEdge(GraphVertex metadataVertex, EdgeLabelEnum edgeLabel, String componentUid, String instUniqueId) {
2061         Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
2062         properties.put(GraphPropertyEnum.UNIQUE_ID, componentUid);
2063
2064         return titanDao.getEdgeByChildrenVertexProperties(metadataVertex, edgeLabel, properties)
2065                 .left()
2066                 .bind(v -> addInstanceToPropertyOnEdge(instUniqueId, v, metadataVertex))
2067                 .right()
2068                 .bind(s -> createInstanceEdge(metadataVertex, edgeLabel, componentUid, instUniqueId, s));
2069     }
2070
2071     private Either<GraphVertex, TitanOperationStatus> removeOrUpdateInstanceEdge(GraphVertex metadataVertex, EdgeLabelEnum edgeLabel, String componentUid, String instUniqueId) {
2072         Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class);
2073         properties.put(GraphPropertyEnum.UNIQUE_ID, componentUid);
2074
2075         return titanDao.getEdgeByChildrenVertexProperties(metadataVertex, edgeLabel, properties).left().bind(v -> removeInstanceFromPropertyOnEdge(instUniqueId, v, metadataVertex)).right()
2076                 .map(err -> removeInstanceEdgeLogError(metadataVertex, edgeLabel, componentUid, err));
2077     }
2078
2079     private Either<GraphVertex, TitanOperationStatus> addInstanceToPropertyOnEdge(String instUniqueId, Edge edge, GraphVertex metadataVertex) {
2080         // edge exist need to add instance id to list on edge's property
2081         List<String> property = (List<String>) titanDao.getProperty(edge, EdgePropertyEnum.INSTANCES);
2082         if (property == null) {
2083             property = new ArrayList<>();
2084         }
2085         Optional<String> findFirst = property.stream().filter(a -> a.equals(instUniqueId)).findFirst();
2086         if (!findFirst.isPresent()) {
2087             property.add(instUniqueId);
2088         }
2089         try {
2090             String jsonArr = JsonParserUtils.toJson(property);
2091             log.debug("Update INSTANCES edge property with value {} ", jsonArr );
2092             
2093             edge.property(EdgePropertyEnum.INSTANCES.getProperty(), jsonArr);
2094         } catch (IOException e) {
2095            log.debug("Failed to convert INSTANCES edge property to json for container {}", metadataVertex.getUniqueId(), e );
2096            return Either.right(TitanOperationStatus.GENERAL_ERROR);
2097         }
2098         return Either.left(metadataVertex);
2099     }
2100
2101     private Either<GraphVertex, TitanOperationStatus> removeInstanceFromPropertyOnEdge(String instUniqueId, Edge edge, GraphVertex metadataVertex) {
2102         // edge exist need to add instance id to list on edge's property
2103         List<String> property = (List<String>) titanDao.getProperty(edge, EdgePropertyEnum.INSTANCES);
2104         if (property == null) {
2105             property = new ArrayList<>();
2106         }
2107         Optional<String> findFirst = property.stream().filter(a -> a.equals(instUniqueId)).findFirst();
2108         if (findFirst.isPresent()) {
2109             property.remove(instUniqueId);
2110         }
2111         if (property.isEmpty()) {
2112             // For last instance need to remove edge
2113             edge.remove();
2114         } else {
2115             try {
2116                 String jsonArr = JsonParserUtils.toJson(property);
2117                 edge.property(EdgePropertyEnum.INSTANCES.getProperty(), jsonArr);
2118             } catch (IOException e) {
2119                log.debug("Failed to convert INSTANCES edge property to json for container {}", metadataVertex.getUniqueId(), e );
2120                return Either.right(TitanOperationStatus.GENERAL_ERROR);
2121             }
2122         }
2123         return Either.left(metadataVertex);
2124     }
2125
2126     private Either<GraphVertex, TitanOperationStatus> createInstanceEdge(GraphVertex metadataVertex, EdgeLabelEnum edgeLabel, String componentUid, String instUniqueId, TitanOperationStatus retrieveEdgeStatus) {
2127         if (retrieveEdgeStatus == TitanOperationStatus.NOT_FOUND) {
2128             // create new edge
2129             Either<GraphVertex, TitanOperationStatus> vertexById = titanDao.getVertexById(componentUid);
2130             if (vertexById.isRight()) {
2131                 return vertexById;
2132             }
2133             GraphVertex originVertex = vertexById.left().value();
2134             Map<EdgePropertyEnum, Object> edgeProps = new EnumMap<>(EdgePropertyEnum.class);
2135             List<String> instList = new ArrayList<>();
2136             instList.add(instUniqueId);
2137             edgeProps.put(EdgePropertyEnum.INSTANCES, instList);
2138
2139             log.debug("Create new edge {} between {} and {} and properties {} ", edgeLabel, metadataVertex.getUniqueId(), originVertex.getUniqueId(), edgeProps);
2140             TitanOperationStatus edgeResult = titanDao.createEdge(metadataVertex, originVertex, edgeLabel, edgeProps);
2141             return edgeResult == TitanOperationStatus.OK ? Either.left(metadataVertex) : Either.right(edgeResult);
2142         }
2143         // error
2144         log.debug("Failed to fetch edge with label {} and to vertex with id {} error {} ", edgeLabel, componentUid, retrieveEdgeStatus);
2145         return Either.right(retrieveEdgeStatus);
2146     }
2147
2148     private TitanOperationStatus removeInstanceEdgeLogError(GraphVertex metadataVertex, EdgeLabelEnum edgeLabel, String componentUid, TitanOperationStatus retrieveEdgeStatus) {
2149         if (retrieveEdgeStatus == TitanOperationStatus.NOT_FOUND) {
2150             log.debug("No edge {} to remove between container {} and origin {}", edgeLabel, metadataVertex.getUniqueId(), componentUid);
2151         } else {
2152             // error
2153             log.debug("Failed to fetch edge with label {} and to vertex with id {} error {} ", edgeLabel, componentUid, retrieveEdgeStatus);
2154         }
2155         return retrieveEdgeStatus;
2156     }
2157
2158     public void removeAllAllotedEdges(String uniqueId) {
2159         Either<GraphVertex, TitanOperationStatus> vertexById = titanDao.getVertexById(uniqueId);
2160         if (vertexById.isLeft()) {
2161             GraphVertex originVertex = vertexById.left().value();
2162             TitanVertex vertex = originVertex.getVertex();
2163             Iterator<Edge> edges = vertex.edges(Direction.OUT, EdgeLabelEnum.ALLOTTED_OF.name());
2164             while ( edges != null && edges.hasNext() ){
2165                 Edge edge = edges.next();
2166                 edge.remove();
2167             }
2168         }
2169     }
2170 }