Added oparent to sdc main
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / merge / utils / MergeInstanceUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 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.components.merge.utils;
22
23 import fj.data.Either;
24 import org.apache.commons.lang3.StringUtils;
25 import org.apache.commons.lang3.tuple.ImmutablePair;
26 import org.openecomp.sdc.be.components.impl.utils.ExceptionUtils;
27 import org.openecomp.sdc.be.components.merge.instance.RelationMergeInfo;
28 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
29 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
30 import org.openecomp.sdc.be.model.*;
31 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
32 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
33 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
34 import org.openecomp.sdc.common.log.wrappers.Logger;
35
36 import java.util.*;
37 import java.util.function.Function;
38 import java.util.function.Predicate;
39 import java.util.stream.Collectors;
40
41 import static java.util.Collections.emptyMap;
42 import static java.util.Collections.singletonList;
43 import static org.openecomp.sdc.be.dao.utils.MapUtil.toMap;
44
45 /**
46  * This class is Utils class but it should be bean
47  * @author dr2032
48  *
49  */
50 @org.springframework.stereotype.Component
51 public class MergeInstanceUtils {
52     private static final Logger log = Logger.getLogger(MergeInstanceUtils.class);
53     
54     private final ToscaOperationFacade toscaOperationFacade;
55     private final ExceptionUtils exceptionUtils;
56
57     public MergeInstanceUtils(ToscaOperationFacade toscaOperationFacade, ExceptionUtils exceptionUtils) {
58         this.toscaOperationFacade = toscaOperationFacade;
59         this.exceptionUtils = exceptionUtils;
60     }
61
62     /**
63      * @param container containing new component instance
64      * @param origInstanceNode old component (in case of PROXY it should be actual service)
65      * @param newInstanceId - ID of new instance of the component
66      * @param oldCapabilitiesOwnerIds the old capabilities owner ids
67      * @return a map of capability owner IDs of old component instance to capability owner IDs of the new component instance
68      */
69     public Map<String, String> mapOldToNewCapabilitiesOwnerIds(Component container,
70                                                                Component origInstanceNode,
71                                                                String newInstanceId,
72                                                                List<String> oldCapabilitiesOwnerIds) {
73
74         Map<String, String> resultMap;
75
76         if (ModelConverter.isAtomicComponent(origInstanceNode) || isCVFC(origInstanceNode)) {
77             resultMap = prepareMapForAtomicComponent(newInstanceId, oldCapabilitiesOwnerIds);
78         }
79         else {
80             resultMap = prepareMapForNonAtomicComponent(container, origInstanceNode, newInstanceId, oldCapabilitiesOwnerIds);
81         }
82
83         return resultMap;
84     }
85
86     /**
87      * @param oldInstance the old instance to find its capabilities owner ids
88      * @param newInstance the new instance to find its capabilities owner ids
89      * @return a map between capability owner IDs of old component instance to capability owner IDs of the new component instance
90      */
91     public Map<String, String> mapOldToNewCapabilitiesOwnerIds(ComponentInstance oldInstance, ComponentInstance newInstance) {
92         List<CapabilityOwner> prevCapabilityOwners  = getInstanceAtomicBuildingBlocks(oldInstance).getCapabilitiesOwners();
93         List<CapabilityOwner> newCapOwners  = getInstanceAtomicBuildingBlocks(newInstance).getCapabilitiesOwners();
94         return getCapabilitiesOwnerMapping(prevCapabilityOwners, newCapOwners);
95     }
96
97     /**
98      * @param oldResource - old version of the Resource
99      * @param newResource - new version of the same Resource
100      * @return list of updated Relations created in UI
101      */
102     public List<RequirementCapabilityRelDef> updateUiRelationsInResource(Resource oldResource, Resource newResource) {
103         Map<String, ComponentInstance> mapOldComponentInstances = buildComponentInstanceMap(oldResource, ComponentInstance::getUniqueId);
104         Map<String, ComponentInstance> mapNewComponentInstances = buildComponentInstanceMap(newResource, ComponentInstance::getName);
105
106         return getUpdatedCapReqDefs(oldResource,
107                 mapOldComponentInstances,
108                 mapNewComponentInstances,
109                 RequirementCapabilityRelDef::isOriginUI);
110     }
111
112     /**
113      *
114      * @param componentInstance the instance which its building blocks are to be returned
115      * @return the atomic building (groups and instances) blocks which the given component instance is a composition of
116      */
117     public ComponentInstanceBuildingBlocks getInstanceAtomicBuildingBlocks(ComponentInstance componentInstance) {
118         if (componentInstance == null) {
119             return ComponentInstanceBuildingBlocks.empty();
120         }
121         String componentId = componentInstance.getActualComponentUid();
122         Component component = toscaOperationFacade.getToscaElement(componentId).left().on(err -> exceptionUtils.rollBackAndThrow(err, componentId));
123         return getInstanceAtomicBuildingBlocks(componentInstance, component);
124     }
125
126     /**
127      *
128      * @param componentInstance the instance which its building blocks are to be returned
129      * @param component the type thar the given component instance was created from
130      * @return the atomic building blocks (groups and instances) which the given component instance is a composition of
131      */
132     public ComponentInstanceBuildingBlocks getInstanceAtomicBuildingBlocks(ComponentInstance componentInstance, Component component) {
133         if (componentInstance == null || component == null) {
134             return ComponentInstanceBuildingBlocks.empty();
135         }
136         ComponentInstanceBuildingBlocks instanceBuildingBlocks;
137         if (ModelConverter.isAtomicComponent(component) || isCVFC(component)) {
138             if (componentInstance.getIsProxy()) {
139                 // Component is proxy and it doesn't contain required data
140                 instanceBuildingBlocks = getInstanceAtomicBuildingBlocks(componentInstance);
141             }
142             else {
143                 instanceBuildingBlocks = ComponentInstanceBuildingBlocks.of(new ArrayList<>(), singletonList(componentInstance));
144             }
145             return instanceBuildingBlocks;
146         }
147         else {
148             instanceBuildingBlocks = recursiveScanForAtomicBuildingBlocks(component);
149             if(org.apache.commons.collections.MapUtils.isNotEmpty(component.getCapabilities()) || org.apache.commons.collections.MapUtils.isNotEmpty(component.getRequirements())) {
150                 ComponentInstanceBuildingBlocks nonAtomicBlocks = ComponentInstanceBuildingBlocks.of(new ArrayList<>(), singletonList(componentInstance));
151                 return ComponentInstanceBuildingBlocks.merge(instanceBuildingBlocks, nonAtomicBlocks);
152             }
153             return instanceBuildingBlocks;
154         
155         }
156     }
157
158     public RelationMergeInfo mapRelationCapability(RequirementCapabilityRelDef relDef, List<CapabilityOwner> capsOwners) {
159         String ownerId = relDef.resolveSingleRelationship().getRelation().getCapabilityOwnerId();
160         return createCapabilityRelationMergeInfo(capsOwners, ownerId, relDef);
161     }
162
163     public RelationMergeInfo mapRelationRequirement(RequirementCapabilityRelDef relDef, List<ComponentInstance> vfcInstances) {
164         String ownerId = relDef.resolveSingleRelationship().getRelation().getRequirementOwnerId();
165         return createRequirementRelationMergeInfo(vfcInstances, ownerId, relDef);
166     }
167
168
169     public RequirementCapabilityRelDef restoreCapabilityRelation(RelationMergeInfo oldCapInfo,
170                                                                  String newInstanceId,
171                                                                  Map<String, CapabilityOwner> capOwnerByName,
172                                                                  Component updatedContainerComponent) {
173         String oldCapOwnerName = oldCapInfo.getCapOwnerName();
174
175         CapabilityOwner newCapOwner = capOwnerByName.get(oldCapOwnerName);
176         if (newCapOwner != null) {
177             // Append relation to updated container
178             RequirementCapabilityRelDef oldRelDef = oldCapInfo.getRelDef();
179             oldRelDef.setToNode(newInstanceId);
180             RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation();
181             oldRelationshipInfo.setCapabilityOwnerId(newCapOwner.getUniqueId());
182             oldRelationshipInfo.getRelationship().setType(oldCapInfo.getCapReqType());
183             String capabilityUid = retrieveCapabilityUid(oldCapInfo.getCapReqName(), newCapOwner);
184             oldRelationshipInfo.setCapabilityUid(capabilityUid);
185             if (updatedContainerComponent != null) {
186                 updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef);
187             }
188             return oldRelDef;
189         } else {
190             log.debug("#restoreCapabilityRelation - Skip relation since it was not found VFC Instance with name {}", oldCapOwnerName);
191             return null;
192         }
193     }
194
195
196
197     public RequirementCapabilityRelDef restoreRequirementRelation(RelationMergeInfo oldReqInfo,
198                                                                   String newInstanceId,
199                                                                   Map<String, ComponentInstance> vfciMap,
200                                                                   Component updatedContainerComponent) {
201         String oldVfcInstanceName = oldReqInfo.getCapOwnerName();
202
203         ComponentInstance newVfcInstance = vfciMap.get(oldReqInfo.getCapOwnerName());
204         if (newVfcInstance != null) {
205             // Append relation to updated container
206             RequirementCapabilityRelDef oldRelDef = oldReqInfo.getRelDef();
207             oldRelDef.setFromNode(newInstanceId);
208
209             RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation();
210             oldRelationshipInfo.setRequirementOwnerId(newVfcInstance.getUniqueId());
211             oldRelationshipInfo.getRelationship().setType(oldReqInfo.getCapReqType());
212
213             String vfcUid = newVfcInstance.getComponentUid();
214             Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(vfcUid);
215
216             if(eitherComponent.isLeft()) {
217                 String requirementUid = retrieveRequirementUid(oldReqInfo.getCapReqName() , eitherComponent.left().value());
218                 oldRelationshipInfo.setRequirementUid(requirementUid);
219             }
220             else {
221                 log.debug("#restoreRequirementCapabilityRelDef - Unexpected error: resource was not loaded for VF ID: {}", vfcUid);
222             }
223
224             if (updatedContainerComponent != null) {
225                 updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef);
226             }
227             return oldRelDef;
228         }
229         else {
230             log.debug("#restoreRequirementCapabilityRelDef - Skip relation since it was not found VFC Instance with name {}", oldVfcInstanceName);
231             return null;
232         }
233     }
234
235     private List<ComponentInstance> getVfcInstances(ComponentInstance componentInstance) {
236         return getInstanceAtomicBuildingBlocks(componentInstance).getVfcInstances();
237     }
238
239     private Map<String, String> getCapabilitiesOwnerMapping(List<CapabilityOwner> oldCapOwners, List<CapabilityOwner> newCapOwners) {
240         Map<String, CapabilityOwner> newCapOwnerNameMap = toMap(newCapOwners, CapabilityOwner::getName, (p1, p2) -> p1);
241         return oldCapOwners.stream()
242                 .filter(oldCapOwner -> newCapOwnerNameMap.containsKey(oldCapOwner.getName()))
243                 .collect(Collectors.toMap(CapabilityOwner::getUniqueId, oldCapOwner -> newCapOwnerNameMap.get(oldCapOwner.getName()).getUniqueId(), (p1, p2) -> p1));
244     }
245
246     private static boolean isCVFC(Component component) {
247         ComponentTypeEnum componentType = component.getComponentType();
248         if (!componentType.equals(ComponentTypeEnum.RESOURCE)) {
249             return false;
250         }
251         Resource resource = (Resource) component;
252         ResourceTypeEnum resourceType = resource.getResourceType();
253         return resourceType == ResourceTypeEnum.CVFC;
254     }
255
256
257     private RequirementCapabilityRelDef mergeCapRelDefs(RequirementCapabilityRelDef capRelDefFrom, RequirementCapabilityRelDef capRelDefTo) {
258         if (capRelDefFrom == capRelDefTo) {
259             return capRelDefFrom;
260         }
261         else if (capRelDefFrom == null) {
262             return capRelDefTo;
263         }
264         else if (capRelDefTo == null) {
265             return capRelDefFrom;
266         }
267         
268         RelationshipInfo relationshipInfoFrom = capRelDefFrom.resolveSingleRelationship().getRelation();
269         RelationshipInfo relationshipInfoTo = capRelDefTo.resolveSingleRelationship().getRelation();
270         
271         relationshipInfoFrom.setCapabilityOwnerId(relationshipInfoTo.getCapabilityOwnerId());
272         relationshipInfoFrom.setCapabilityUid(relationshipInfoTo.getCapabilityUid());
273         
274         return capRelDefFrom;
275     }
276     
277
278
279     private Map<String, ComponentInstance> buildComponentInstanceMap(Resource oldRresource, Function<ComponentInstance, String> getKeyFunc) {
280         return oldRresource.getComponentInstances().stream()
281                 .collect(Collectors.toMap(getKeyFunc, Function.identity(), (p1, p2) -> p1));
282     }
283
284     private List<RequirementCapabilityRelDef> getUpdatedCapReqDefs(Resource oldResource,
285                                                                    Map<String, ComponentInstance> mapOldComponentInstances,
286                                                                    Map<String, ComponentInstance> mapNewComponentInstances,
287                                                                    Predicate<? super RequirementCapabilityRelDef> filter) {
288         return oldResource.getComponentInstancesRelations().stream()
289                         .filter(filter)
290                         .map(rel -> createRelationMergeInfoPair(rel, mapOldComponentInstances))
291                         .map(infoPair -> restoreRequirementCapabilityRelDef(infoPair, mapNewComponentInstances))
292                         .filter(Objects::nonNull)
293                         .collect(Collectors.toList());
294     }
295
296     private ImmutablePair<RelationMergeInfo, RelationMergeInfo> createRelationMergeInfoPair(RequirementCapabilityRelDef reqCapDef,
297                                                                                             Map<String, ComponentInstance> mapOldComponentInstances) {
298         
299         ComponentInstance oldComponentInstanceFrom = mapOldComponentInstances.get(reqCapDef.getFromNode());
300         RelationMergeInfo fromRelationMergeInfo = createRequirmentRelationMergeInfo(oldComponentInstanceFrom, reqCapDef);
301         
302         ComponentInstance oldComponentInstanceTo = mapOldComponentInstances.get(reqCapDef.getToNode());
303         RelationMergeInfo toRelationMergeInfo = createCapabilityRelationMergeInfo(oldComponentInstanceTo, reqCapDef);
304         return new ImmutablePair<>(fromRelationMergeInfo, toRelationMergeInfo);
305     }
306
307     private RelationMergeInfo createRequirmentRelationMergeInfo(ComponentInstance componentInstance, RequirementCapabilityRelDef reqCapDef ) {
308         
309         List<ComponentInstance> vfcInstances = getVfcInstances(componentInstance);
310         if  (vfcInstances != null) { 
311             return mapRelationRequirement(reqCapDef, vfcInstances);
312         }
313         else {
314             log.debug("#createRelationMergeInfo - It's unexpected that vfc instnaces were not found for {}", componentInstance);
315             return null;
316         }
317     }
318
319     private RelationMergeInfo createCapabilityRelationMergeInfo(ComponentInstance componentInstance,
320                                                       RequirementCapabilityRelDef reqCapDef) {
321         List<CapabilityOwner> capabilityOwners = getInstanceAtomicBuildingBlocks(componentInstance).getCapabilitiesOwners();
322         return mapRelationCapability(reqCapDef, capabilityOwners);
323     }
324
325     
326     private RequirementCapabilityRelDef restoreRequirementCapabilityRelDef(ImmutablePair<RelationMergeInfo, RelationMergeInfo> mergeInfoPair, Map<String, ComponentInstance> mapNewComponentInstances) {
327         RequirementCapabilityRelDef capRelDefFrom = restoreRequirementRelDef(mergeInfoPair, mapNewComponentInstances);
328         RequirementCapabilityRelDef capRelDefTo = restoreCapabilityRelDef(mergeInfoPair, mapNewComponentInstances);
329
330         return mergeCapRelDefs(capRelDefFrom, capRelDefTo);
331     }
332
333     private RequirementCapabilityRelDef restoreRequirementRelDef(ImmutablePair<RelationMergeInfo, RelationMergeInfo> mergeInfoPair, Map<String, ComponentInstance> mapNewComponentInstances) {
334         RequirementCapabilityRelDef capRelDefFrom;
335         RelationMergeInfo mergeInfoFrom = mergeInfoPair.getLeft();
336         if (mergeInfoFrom != null) {
337             ComponentInstance newComponentInstanceFrom = mapNewComponentInstances.get(mergeInfoFrom.getCapOwnerName());
338             capRelDefFrom = restoreRequirementRelDef(newComponentInstanceFrom, mergeInfoFrom,  newComponentInstanceFrom.getUniqueId());
339         }
340         else {
341             capRelDefFrom = null;
342         }
343         return capRelDefFrom;
344     }
345
346     private RequirementCapabilityRelDef restoreCapabilityRelDef(ImmutablePair<RelationMergeInfo, RelationMergeInfo> mergeInfoPair, Map<String, ComponentInstance> mapNewComponentInstances) {
347         RequirementCapabilityRelDef capRelDefTo;
348         RelationMergeInfo mergeInfoTo = mergeInfoPair.getRight();
349         if (mergeInfoTo != null) {
350             ComponentInstance newComponentInstanceTo = mapNewComponentInstances.get(mergeInfoTo.getCapOwnerName());
351             capRelDefTo = restoreCapabilityRelDef(newComponentInstanceTo, mergeInfoTo, newComponentInstanceTo.getUniqueId());
352         }
353         else {
354             capRelDefTo = null;
355         }
356         return capRelDefTo;
357     }
358
359     private RequirementCapabilityRelDef  restoreRequirementRelDef(ComponentInstance newComponentInstance, RelationMergeInfo mergeInfoFrom, String newComponentInstanceFromId) {
360         if (newComponentInstance != null) {
361             List<ComponentInstance> vfcInstances = getVfcInstances(newComponentInstance);
362             if(vfcInstances != null) {
363                 Map<String, ComponentInstance> vfciMap = toMap(vfcInstances, ComponentInstance::getName, (p1, p2) -> p1);
364                 return restoreRequirementRelation(mergeInfoFrom, newComponentInstanceFromId, vfciMap, null);
365             }
366             else {
367                 log.debug("#restoreRequirementCapabilityRelDef - It was not found VFC instances for component instance {}", newComponentInstance);
368             }
369         }
370         return null;
371     }
372
373     private RequirementCapabilityRelDef restoreCapabilityRelDef(ComponentInstance newComponentInstance, RelationMergeInfo mergeInfoTo, String newComponentInstanceToId) {
374         if (newComponentInstance != null) {
375             List<CapabilityOwner> capsOwners = getInstanceAtomicBuildingBlocks(newComponentInstance).getCapabilitiesOwners();
376             if(capsOwners != null) {
377                 Map<String, CapabilityOwner> vfciMap = toMap(capsOwners, CapabilityOwner::getName, (p1, p2) -> p1);
378                 return restoreCapabilityRelation(mergeInfoTo, newComponentInstanceToId, vfciMap, null);
379             }
380             else {
381                 log.debug("#restoreRequirementCapabilityRelDef - It was not found VFC instances for component instance {}", newComponentInstance);
382             }
383         }
384         return null;
385     }
386
387
388     private ComponentInstanceBuildingBlocks recursiveScanForAtomicBuildingBlocks(Component component) {
389         ComponentInstanceBuildingBlocks capsOwners = ComponentInstanceBuildingBlocks.of(component.getGroups(), null);
390         List<ComponentInstance> componentInstances = component.safeGetComponentInstances();
391         // Go recursively to collect atomic components only
392         ComponentInstanceBuildingBlocks propsOwnersRec = componentInstances.stream()
393                 .map(this::getInstanceAtomicBuildingBlocks)
394                 .reduce(ComponentInstanceBuildingBlocks::merge)
395                 .orElse(ComponentInstanceBuildingBlocks.empty());
396         return ComponentInstanceBuildingBlocks.merge(capsOwners, propsOwnersRec);
397     }
398
399
400     private Map<String, String> prepareMapForAtomicComponent(String newInstanceId, List<String> oldCapabilitiesOwnerIds) {
401         Map<String, String> resultMap;
402
403         int oldCapabilityOwnerIdsSize = oldCapabilitiesOwnerIds.size();
404         if (oldCapabilityOwnerIdsSize == 1) {
405             resultMap = new HashMap<>();
406             resultMap.put(oldCapabilitiesOwnerIds.get(0), newInstanceId);
407         }
408         else {
409             log.debug("#prepareMapForAtomicComponent - For atomic component the list of old capabilities owner Ids should contains one element while actual size is {},", oldCapabilityOwnerIdsSize);
410             resultMap = emptyMap();
411         }
412
413         return resultMap;
414     }
415
416     private Map<String, String> prepareMapForNonAtomicComponent(Component container, Component origInstanceNode,
417                                                                     String newInstanceId, List<String> oldCapabilitiesOwnerIds) {
418         ComponentInstance newInstance = container.getComponentInstanceById(newInstanceId).orElse(null);
419         if (newInstance == null) {
420             log.debug("#prepareMapForNonAtomicComponent - Failed to get component instance by newInstanceId: {}.", newInstanceId);
421             return emptyMap();
422         }
423         List<CapabilityOwner> prevCapOwners = recursiveScanForAtomicBuildingBlocks(origInstanceNode).getCapabilitiesOwners();
424         Component origNewCmpt = toscaOperationFacade.getToscaElement(newInstance.getActualComponentUid()).left().on(err -> exceptionUtils.rollBackAndThrow(err, newInstance.getActualComponentUid()));
425         return mapOldOwnerIdsToNewOnes(oldCapabilitiesOwnerIds, prevCapOwners, newInstance, origNewCmpt);
426     }
427
428     private Map<String, String> mapOldOwnerIdsToNewOnes(List<String> oldCapabilitiesOwnerIds,
429                                                         List<CapabilityOwner> prevCapOwners, ComponentInstance newInstance, Component origNewInstanceType) {
430         List<CapabilityOwner> newCapOwners = getInstanceAtomicBuildingBlocks(newInstance, origNewInstanceType).getCapabilitiesOwners();
431         return getCapabilitiesOwnerMapping(oldCapabilitiesOwnerIds, prevCapOwners, newCapOwners);
432     }
433
434     private Map<String, String> getCapabilitiesOwnerMapping(List<String> oldCapabilitiesOwnerIds, List<CapabilityOwner> prevCapOwners, List<CapabilityOwner> newCapOwners) {
435         Map<String, CapabilityOwner> capOwnersByName = toMap(newCapOwners, CapabilityOwner::getName, (p1, p2) -> p1);
436         return prevCapOwners
437                 .stream()
438                 .filter(oldCapOwner -> oldCapabilitiesOwnerIds.contains(oldCapOwner.getUniqueId()))
439                 .filter(oldCapOwner -> capOwnersByName.containsKey(oldCapOwner.getName()))
440                 .collect(Collectors.toMap(CapabilityOwner::getUniqueId, oldCapOwner -> capOwnersByName.get(oldCapOwner.getName()).getUniqueId(), (p1, p2) -> p1));
441     }
442
443
444     private RelationMergeInfo createCapabilityRelationMergeInfo(List<CapabilityOwner> vfcInstances, String ownerId, RequirementCapabilityRelDef relation) {
445         return vfcInstances.stream()
446                             .filter(inst -> StringUtils.equals(inst.getUniqueId(), ownerId))
447                             .map(capabilityOwner -> getCapabilityMergeInfo(capabilityOwner, relation))
448                             .findAny()
449                             .orElse(null);
450     }
451
452
453     private RelationMergeInfo createRequirementRelationMergeInfo(List<ComponentInstance> vfcInstances, String ownerId, RequirementCapabilityRelDef relation) {
454         return vfcInstances.stream()
455                 .filter(inst -> StringUtils.equals(inst.getUniqueId(), ownerId))
456                 .map(currVfcInst -> mapVfcInstanceRequirement(currVfcInst, relation))
457                 .filter(Objects::nonNull)
458                 .findAny()
459                 .orElse(null);
460     }
461
462     private RelationMergeInfo getCapabilityMergeInfo(CapabilityOwner capabilityOwner, RequirementCapabilityRelDef relDef) {
463         String capabilityUniqueId = relDef.resolveSingleRelationship().getRelation().getCapabilityUid();
464         String capOwnerName = capabilityOwner.getName();
465         CapabilityDefinition capabilityDef = retrieveCapabilityDefinition(capabilityUniqueId, capabilityOwner);
466         String capabilityType;
467         String capabilityName;
468         if (capabilityDef != null) {
469             capabilityType = capabilityDef.getType();
470             capabilityName = capabilityDef.getName();
471         } else {
472             log.debug("#getCapabilityMergeInfo - Failed to retrieve capability type for relation with name: {} and uniqueId {}", relDef.resolveSingleRelationship().getRelation().getCapability(), capabilityUniqueId);
473             capabilityType = null;
474             capabilityName = null;
475         }
476         return new RelationMergeInfo(capabilityType, capabilityName, capOwnerName, relDef);
477     }
478     
479     private RelationMergeInfo mapVfcInstanceRequirement(ComponentInstance vfcInstance, RequirementCapabilityRelDef relDef) {
480         String requirementUniqueId = relDef.resolveSingleRelationship().getRelation().getRequirementUid();
481         
482         String vfcInstanceName = vfcInstance.getName();
483         String vfcUid = vfcInstance.getComponentUid();
484         
485         Either<Resource, StorageOperationStatus> vfcResource = toscaOperationFacade.getToscaElement(vfcUid);
486         if(vfcResource.isLeft()) {
487             Resource vfc = vfcResource.left().value();
488             
489             RequirementDefinition requirementDef = retrieveRequirementDefinition(requirementUniqueId, vfc);
490             String requirementType;
491             String requirementName;
492             if (requirementDef != null) {
493                 requirementType = requirementDef.getCapability();
494                 requirementName = requirementDef.getName();
495             }
496             else {
497                 log.debug("#mapVfcInstanceRequirement - Failed to retrieve requirement type for relation with name: {} and uniqueId {}", relDef.resolveSingleRelationship().getRelation().getRequirement(), requirementUniqueId);
498                 requirementType = null;
499                 requirementName = null;                
500             }
501             
502             return new RelationMergeInfo(requirementType, requirementName, vfcInstanceName, relDef);
503         }
504         else {
505             log.debug("#mapVfcInstanceRequirement - Failed to load VFC by uid {}", vfcUid); 
506             return null;
507         }
508     }
509
510     private CapabilityDefinition retrieveCapabilityDefinition(String uniqueId, CapabilityOwner capabilityOwner) {
511         return capabilityOwner.getCapabilities().values().stream()
512                                                 .flatMap(List::stream)
513                                                 .filter(Objects::nonNull)
514                                                 .filter(def -> uniqueId.equals(def.getUniqueId()))
515                                                 .findFirst()
516                                                 .orElse(null);
517     }
518     
519     private RequirementDefinition retrieveRequirementDefinition(String uniqueId, Resource vfc) {
520         return vfc.getRequirements().values().stream()
521                 .flatMap(List::stream)
522                 .filter(Objects::nonNull)
523                 .filter(def -> uniqueId.equals(def.getUniqueId()))
524                 .findFirst()
525                 .orElse(null);
526     }
527     
528     private String retrieveCapabilityUid(String name, CapabilityOwner capabilityOwner) {
529         return capabilityOwner.getCapabilities().values()
530                                                 .stream()
531                                                 .flatMap(List::stream)
532                                                 .filter(Objects::nonNull)
533                                                 .filter(def -> name.equals(def.getName()))
534                                                 .findFirst()
535                                                 .map(CapabilityDefinition::getUniqueId)
536                                                 .orElse(null);
537     }
538
539     private String retrieveRequirementUid(String name, Component vfc) {
540         return vfc.getRequirements().values().stream()
541                                                 .flatMap(List::stream)
542                                                 .filter(Objects::nonNull)
543                                                 .filter(def -> name.equals(def.getName()))
544                                                 .findFirst()
545                                                 .map(RequirementDefinition::getUniqueId)
546                                                 .orElse(null);
547     }
548 }