re base code
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / merge / instance / ComponentInstanceRelationMerge.java
1 package org.openecomp.sdc.be.components.merge.instance;
2
3 import fj.data.Either;
4 import org.apache.commons.lang3.StringUtils;
5 import org.openecomp.sdc.be.components.merge.utils.CapabilityOwner;
6 import org.openecomp.sdc.be.components.merge.utils.ComponentInstanceBuildingBlocks;
7 import org.openecomp.sdc.be.components.merge.utils.MergeInstanceUtils;
8 import org.openecomp.sdc.be.dao.utils.MapUtil;
9 import org.openecomp.sdc.be.impl.ComponentsUtils;
10 import org.openecomp.sdc.be.model.Component;
11 import org.openecomp.sdc.be.model.ComponentInstance;
12 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
13 import org.openecomp.sdc.be.model.User;
14 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
15 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
16 import org.openecomp.sdc.common.datastructure.Wrapper;
17 import org.openecomp.sdc.common.log.wrappers.Logger;
18 import org.openecomp.sdc.exception.ResponseFormat;
19
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Objects;
24 import java.util.function.Function;
25 import java.util.stream.Collectors;
26 import java.util.stream.Stream;
27
28
29 @org.springframework.stereotype.Component("ComponentInstanceRelashionMerge")
30 public class ComponentInstanceRelationMerge implements ComponentInstanceMergeInterface {
31     private static final Logger log = Logger.getLogger(ComponentInstanceRelationMerge.class);
32     
33     private final ComponentsUtils componentsUtils;
34     private final MergeInstanceUtils mergeInstanceUtils;
35     private final ToscaOperationFacade toscaOperationFacade;
36
37     public ComponentInstanceRelationMerge(ComponentsUtils componentsUtils, MergeInstanceUtils mergeInstanceUtils, ToscaOperationFacade toscaOperationFacade) {
38         this.componentsUtils = componentsUtils;
39         this.mergeInstanceUtils = mergeInstanceUtils;
40         this.toscaOperationFacade = toscaOperationFacade;
41     }
42     
43
44     @Override
45     public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance, Component originComponent) {
46         //All Relationships - container (service) holds info about all relations
47         //Filter by UniqueId in from/to
48         List<RequirementCapabilityRelDef> relationsFrom = getRelations(RequirementCapabilityRelDef::getFromNode,
49                                                                       containerComponent,
50                                                                       currentResourceInstance);
51
52         List<RequirementCapabilityRelDef> relationsTo = getRelations(RequirementCapabilityRelDef::getToNode,
53                                                                     containerComponent,
54                                                                     currentResourceInstance);
55
56         if (!relationsFrom.isEmpty() || !relationsTo.isEmpty()) {
57             ComponentInstanceBuildingBlocks instBuildingBlocks = mergeInstanceUtils.getInstanceAtomicBuildingBlocks(currentResourceInstance, originComponent);
58
59             if  (instBuildingBlocks != null) {
60                 List<RelationMergeInfo> fromRelInfoList = convert(relationsFrom, rel -> mergeInstanceUtils.mapRelationRequirement(rel, instBuildingBlocks.getVfcInstances()));
61                 List<RelationMergeInfo> toRelInfoList = convert(relationsTo, rel -> mergeInstanceUtils.mapRelationCapability(rel, instBuildingBlocks.getCapabilitiesOwners()));
62
63                 // Encapsulate all needed info in one container
64                 ContainerRelationsMergeInfo containerRelationsMergeInfo = new ContainerRelationsMergeInfo(fromRelInfoList, toRelInfoList);
65                 // Save it
66                 dataHolder.setVfRelationsInfo(containerRelationsMergeInfo);
67             }
68         }
69         else {
70             log.debug("No relations relevant to currentResourceInstance {} found in container component", currentResourceInstance);
71         }
72
73     }
74
75
76     @Override
77     public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) {
78         Wrapper<Either<Component, ResponseFormat>> resultWrapper = new Wrapper<>();
79
80         ContainerRelationsMergeInfo containerRelationsMergeInfo = getRelationsMergeInfo(dataHolder, updatedContainerComponent, resultWrapper);
81
82         ComponentInstance newComponentInstance = null;
83         if(resultWrapper.isEmpty()) {
84             //Component Instance
85             newComponentInstance = loadComponentInstance(updatedContainerComponent, newInstanceId, resultWrapper);
86         }
87
88         if(resultWrapper.isEmpty() && containerRelationsMergeInfo != null) {
89             // Load VFCI and filter them by name
90             ComponentInstanceBuildingBlocks instanceBuildBlocks = mergeInstanceUtils.getInstanceAtomicBuildingBlocks(newComponentInstance);
91             if(instanceBuildBlocks != null) {
92                 // Process Relationships
93                 Stream<RequirementCapabilityRelDef> toRelationsInfoStream = getCapabilitiesRelationInfoStream(updatedContainerComponent, newInstanceId, containerRelationsMergeInfo, instanceBuildBlocks);
94                 Stream<RequirementCapabilityRelDef> fromRelationsInfoStream = getRequirementRelationsInfoStream(updatedContainerComponent, newInstanceId, containerRelationsMergeInfo, instanceBuildBlocks);
95                 List<RequirementCapabilityRelDef> updatedRelations = getUpdatedRelations(toRelationsInfoStream, fromRelationsInfoStream);
96                 StorageOperationStatus saveResult = toscaOperationFacade.associateResourceInstances(updatedContainerComponent.getUniqueId(), updatedRelations);
97                 if (saveResult == StorageOperationStatus.OK) {
98                     resultWrapper.setInnerElement(Either.left(updatedContainerComponent));
99                 }
100                 else {
101                     log.debug("Failed to associate instances of resource {} status is {}", updatedContainerComponent.getUniqueId(), saveResult);
102                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(saveResult), updatedContainerComponent.getUniqueId());
103                     resultWrapper.setInnerElement(Either.right(responseFormat));
104                 }
105             }
106         }
107         return resultWrapper.getInnerElement();
108     }
109
110     private Stream<RequirementCapabilityRelDef> getRequirementRelationsInfoStream(Component updatedContainerComponent, String newInstanceId, ContainerRelationsMergeInfo containerRelationsMergeInfo, ComponentInstanceBuildingBlocks instanceBuildBlocks) {
111         Map<String, ComponentInstance> vfciMap = MapUtil.toMap(instanceBuildBlocks.getVfcInstances(), ComponentInstance::getName, (p1, p2) -> p1);
112         List<RelationMergeInfo> fromRelationsInfo = containerRelationsMergeInfo.getFromRelationsInfo();
113         Stream<RequirementCapabilityRelDef> fromRelationsInfoStream = null;
114         if( fromRelationsInfo != null) {
115             fromRelationsInfoStream = fromRelationsInfo.stream()
116                                         .map(oldReqInfo -> mergeInstanceUtils.restoreRequirementRelation(oldReqInfo, newInstanceId, vfciMap, updatedContainerComponent))
117                                         .filter(Objects::nonNull);
118         }
119         return fromRelationsInfoStream;
120     }
121
122     private Stream<RequirementCapabilityRelDef> getCapabilitiesRelationInfoStream(Component updatedContainerComponent, String newInstanceId, ContainerRelationsMergeInfo containerRelationsMergeInfo, ComponentInstanceBuildingBlocks instanceBuildBlocks) {
123         Map<String, CapabilityOwner> capOwnersByName = MapUtil.toMap(instanceBuildBlocks.getCapabilitiesOwners(), CapabilityOwner::getName, (p1, p2) -> p1);
124         List<RelationMergeInfo> toRelationsInfo = containerRelationsMergeInfo.getToRelationsInfo();
125         Stream<RequirementCapabilityRelDef> toRelationsInfoStream = null;
126         if (toRelationsInfo != null) {
127             toRelationsInfoStream = toRelationsInfo.stream()
128                                     .map(oldCapInfo -> mergeInstanceUtils.restoreCapabilityRelation(oldCapInfo, newInstanceId, capOwnersByName, updatedContainerComponent))
129                                     .filter(Objects::nonNull);
130         }
131         return toRelationsInfoStream;
132     }
133
134     /**
135      * @param containerComponent
136      * @param instanceId
137      * @param resultWrapper
138      * @return
139      */
140     private ComponentInstance loadComponentInstance(Component containerComponent, String instanceId,
141             Wrapper<Either<Component, ResponseFormat>> resultWrapper) {
142         ComponentInstance componentInstance = containerComponent.getComponentInstanceById(instanceId).orElse(null);
143         if (componentInstance == null) {
144             log.debug("Failed to get VF instance by new VF instance ID: {}", instanceId);
145             resultWrapper.setInnerElement(Either.left(containerComponent));
146         }
147
148         return componentInstance;
149     }
150
151
152     private List<RequirementCapabilityRelDef> getUpdatedRelations(Stream<RequirementCapabilityRelDef> toRelationsInfoStream, 
153                                                                   Stream<RequirementCapabilityRelDef> fromRelationsInfoStream) {
154         Stream<RequirementCapabilityRelDef> updatedRelationsStream = Stream.empty();
155
156         if (toRelationsInfoStream != null) {
157             updatedRelationsStream = Stream.concat(updatedRelationsStream, toRelationsInfoStream);
158         }
159
160         if (fromRelationsInfoStream != null) {
161             updatedRelationsStream = Stream.concat(updatedRelationsStream, fromRelationsInfoStream);
162         }
163
164         return updatedRelationsStream.collect(Collectors.toList());
165     }
166
167     private List<RequirementCapabilityRelDef> getRelations(Function<RequirementCapabilityRelDef, String> getNodeFunc,
168                                                            Component containerComponent,
169                                                            ComponentInstance currentResourceInstance) {
170
171         final List<RequirementCapabilityRelDef> componentInstancesRelations = containerComponent.getComponentInstancesRelations();
172         if (componentInstancesRelations == null) {
173             return Collections.emptyList();
174         }
175         
176         final String vfInstanceId = currentResourceInstance.getUniqueId();
177
178         return componentInstancesRelations.stream()
179                                             .filter(rel -> StringUtils.equals(getNodeFunc.apply(rel), vfInstanceId))
180                                             .collect(Collectors.toList());
181     }
182
183     private List<RelationMergeInfo> convert(List<RequirementCapabilityRelDef> relationsDef, 
184                                             Function<RequirementCapabilityRelDef, RelationMergeInfo> mapFunc) {
185         return relationsDef.stream()
186                             .map(mapFunc)
187                             .filter(Objects::nonNull)
188                             .collect(Collectors.toList());
189     }
190     
191     private ContainerRelationsMergeInfo getRelationsMergeInfo(DataForMergeHolder dataHolder,
192                                                               Component updatedContainerComponent,
193                                                               Wrapper<Either<Component, ResponseFormat>> resultWrapper) {
194         ContainerRelationsMergeInfo containerRelationsMergeInfo = dataHolder.getContainerRelationsMergeInfo();
195         if (containerRelationsMergeInfo == null) {
196             log.debug("There is no info about relations should be restored.");
197             resultWrapper.setInnerElement(Either.left(updatedContainerComponent));
198         }
199
200         return containerRelationsMergeInfo;
201     }
202 }