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