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