Sync Integ to Master
[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 java.util.List;
4 import java.util.Map;
5 import java.util.Objects;
6 import java.util.function.Function;
7 import java.util.stream.Collectors;
8 import java.util.stream.Stream;
9
10 import org.apache.commons.lang3.StringUtils;
11 import org.openecomp.sdc.be.components.merge.utils.MergeInstanceUtils;
12 import org.openecomp.sdc.be.impl.ComponentsUtils;
13 import org.openecomp.sdc.be.model.CapabilityDefinition;
14 import org.openecomp.sdc.be.model.Component;
15 import org.openecomp.sdc.be.model.ComponentInstance;
16 import org.openecomp.sdc.be.model.RelationshipInfo;
17 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
18 import org.openecomp.sdc.be.model.RequirementDefinition;
19 import org.openecomp.sdc.be.model.Resource;
20 import org.openecomp.sdc.be.model.User;
21 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
22 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
23 import org.openecomp.sdc.common.datastructure.Wrapper;
24 import org.openecomp.sdc.exception.ResponseFormat;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.springframework.beans.factory.annotation.Autowired;
28
29 import com.att.aft.dme2.internal.google.common.annotations.VisibleForTesting;
30
31 import fj.data.Either;
32
33
34 @org.springframework.stereotype.Component("ComponentInstanceRelashionMerge")
35 public class ComponentInstanceRelationMerge implements ComponentInstanceMergeInterface {
36     private static Logger log = LoggerFactory.getLogger(ComponentInstanceRelationMerge.class);
37     
38     @Autowired
39     private ComponentsUtils componentsUtils;
40     
41     @Autowired
42     private MergeInstanceUtils mergeInstanceUtils;
43
44     @Autowired
45     private ToscaOperationFacade toscaOperationFacade;
46
47
48     @Override
49     public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance, Component originComponent) {
50         //All Relationships - container (service) holds info about all relations
51         //Filter by UniqueId in from/to
52         List<RequirementCapabilityRelDef> relationsFrom = getRelations(RequirementCapabilityRelDef::getFromNode,
53                                                                       containerComponent,
54                                                                       currentResourceInstance);
55
56         List<RequirementCapabilityRelDef> relationsTo = getRelations(RequirementCapabilityRelDef::getToNode,
57                                                                     containerComponent,
58                                                                     currentResourceInstance);
59
60         if (!relationsFrom.isEmpty() || !relationsTo.isEmpty()) {
61             List<ComponentInstance> vfcInstances = mergeInstanceUtils.getVfcInstances(currentResourceInstance, originComponent);
62
63             if  (vfcInstances != null) {
64                 List<RelationMergeInfo> fromRelInfoList = convert(relationsFrom, rel -> mapRelationRequirement(rel, vfcInstances));
65                 List<RelationMergeInfo> toRelInfoList = convert(relationsTo, rel -> mapRelationCapability(rel, vfcInstances));
66
67                 // Encapsulate all needed info in one container
68                 VfRelationsMergeInfo vfRelationsMergeInfo = new VfRelationsMergeInfo(fromRelInfoList, toRelInfoList);
69                 // Save it
70                 dataHolder.setVfRelationsInfo(vfRelationsMergeInfo);
71             }
72         }
73         else {
74             log.debug("No relations relevant to currentResourceInstance {} found in container component", currentResourceInstance);
75         }
76
77     }
78
79
80     @Override
81     public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) {
82         Wrapper<Either<Component, ResponseFormat>> resultWrapper = new Wrapper<>();
83
84         VfRelationsMergeInfo vfRelationsMergeInfo = getRelationsMergeInfo(dataHolder, updatedContainerComponent, resultWrapper);
85
86         ComponentInstance newComponentInstance = null;
87         if(resultWrapper.isEmpty()) {
88             //Component Instance
89             newComponentInstance = loadComponentInstance(updatedContainerComponent, newInstanceId, resultWrapper);
90         }
91
92         if(resultWrapper.isEmpty() && vfRelationsMergeInfo != null) {
93             // Load VFCI and filter them by name
94             List<ComponentInstance> vfcInstances = mergeInstanceUtils.getVfcInstances(newComponentInstance);
95             if(vfcInstances != null) {
96                 Map<String, ComponentInstance> vfciMap = mergeInstanceUtils.convertToVfciNameMap(vfcInstances);
97
98                 // Process Relationships
99                 List<RelationMergeInfo> toRelationsInfo = vfRelationsMergeInfo.getToRelationsInfo();
100                 Stream<RequirementCapabilityRelDef> toRelationsInfoStream = null;
101                 if (toRelationsInfo != null) {
102                     toRelationsInfoStream = toRelationsInfo.stream()
103                                             .map(oldCapInfo -> restoreCapabilityRelation(oldCapInfo, newInstanceId, vfciMap, updatedContainerComponent))
104                                             .filter(Objects::nonNull);
105                 }
106
107                 List<RelationMergeInfo> fromRelationsInfo = vfRelationsMergeInfo.getFromRelationsInfo();
108                 Stream<RequirementCapabilityRelDef> fromRelationsInfoStream = null;
109                 if( fromRelationsInfo != null) {
110                     //For Each old requirement relation info
111                     fromRelationsInfoStream = fromRelationsInfo.stream()
112                                                 .map(oldReqInfo -> restoreRequirementRelation(oldReqInfo, newInstanceId, vfciMap, updatedContainerComponent))
113                                                 .filter(Objects::nonNull);
114                 }
115
116                 // Save relations in updated container (service)
117                 List<RequirementCapabilityRelDef> updatedRelations = getUpdatedRelations(toRelationsInfoStream, fromRelationsInfoStream);
118                 StorageOperationStatus saveResult = toscaOperationFacade.associateResourceInstances(updatedContainerComponent.getUniqueId(), updatedRelations);
119                 if (saveResult == StorageOperationStatus.OK) {
120                     resultWrapper.setInnerElement(Either.left(updatedContainerComponent));
121                 }
122                 else {
123                     log.debug("Failed to associate instances of resource {} status is {}", updatedContainerComponent.getUniqueId(), saveResult);
124                     ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(saveResult), updatedContainerComponent.getUniqueId());
125                     resultWrapper.setInnerElement(Either.right(responseFormat));
126                 }
127             }
128         }
129
130         return resultWrapper.getInnerElement();
131     }
132     
133     @VisibleForTesting
134     public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) {
135         this.toscaOperationFacade = toscaOperationFacade;
136     }
137     
138     
139     @VisibleForTesting
140     public void setComponentsUtils(ComponentsUtils componentsUtils) {
141         this.componentsUtils = componentsUtils;
142     }
143     
144     @VisibleForTesting
145     public void setMergeInstanceUtils(MergeInstanceUtils mergeInstanceUtils) {
146         this.mergeInstanceUtils = mergeInstanceUtils;
147     }
148
149     /**
150      * @param containerComponent
151      * @param instanceId
152      * @param resultWrapper
153      * @return
154      */
155     private ComponentInstance loadComponentInstance(Component containerComponent, String instanceId,
156             Wrapper<Either<Component, ResponseFormat>> resultWrapper) {
157         ComponentInstance componentInstance = containerComponent.getComponentInstanceById(instanceId).orElse(null);
158         if (componentInstance == null) {
159             log.debug("Failed to get VF instance by new VF instance ID: {}", instanceId);
160             resultWrapper.setInnerElement(Either.left(containerComponent));
161         }
162
163         return componentInstance;
164     }
165
166
167     private List<RequirementCapabilityRelDef> getUpdatedRelations(Stream<RequirementCapabilityRelDef> toRelationsInfoStream, 
168                                                                   Stream<RequirementCapabilityRelDef> fromRelationsInfoStream) {
169         Stream<RequirementCapabilityRelDef> updatedRelationsStream = Stream.empty();
170
171         if (toRelationsInfoStream != null) {
172             updatedRelationsStream = Stream.concat(updatedRelationsStream, toRelationsInfoStream);
173         }
174
175         if (fromRelationsInfoStream != null) {
176             updatedRelationsStream = Stream.concat(updatedRelationsStream, fromRelationsInfoStream);
177         }
178
179         return updatedRelationsStream.collect(Collectors.toList());
180     }
181
182     private List<RequirementCapabilityRelDef> getRelations(Function<RequirementCapabilityRelDef, String> getNodeFunc,
183                                                            Component containerComponent,
184                                                            ComponentInstance currentResourceInstance) {
185
186         final List<RequirementCapabilityRelDef> componentInstancesRelations = containerComponent.getComponentInstancesRelations();
187         final String vfInstanceId = currentResourceInstance.getUniqueId();
188
189         return componentInstancesRelations.stream()
190                                             .filter(rel -> StringUtils.equals(getNodeFunc.apply(rel), vfInstanceId))
191                                             .collect(Collectors.toList());
192     }
193
194     private List<RelationMergeInfo> convert(List<RequirementCapabilityRelDef> relationsDef, 
195                                             Function<RequirementCapabilityRelDef, RelationMergeInfo> mapFunc) {
196         return relationsDef.stream()
197                             .map(mapFunc::apply)
198                             .filter(Objects::nonNull)
199                             .collect(Collectors.toList());
200     }
201     
202     private RelationMergeInfo mapRelationCapability(RequirementCapabilityRelDef relDef, List<ComponentInstance> vfcInstances) {
203         // Id of the VfcInstance that is the owner of the capability
204         String ownerId = relDef.resolveSingleRelationship().getRelation().getCapabilityOwnerId();
205         return createRelationMergeInfo(vfcInstances, ownerId, currVfcInst -> mapVfcInstanceCapability(currVfcInst, relDef));
206     }
207     
208     private RelationMergeInfo mapRelationRequirement(RequirementCapabilityRelDef relDef, List<ComponentInstance> vfcInstances) {
209         // Id of the VfcInstance that is the owner of the requirement
210         String ownerId = relDef.resolveSingleRelationship().getRelation().getRequirementOwnerId();
211         return createRelationMergeInfo(vfcInstances, ownerId, currVfcInst -> mapVfcInstanceRequirement(currVfcInst, relDef));
212     }
213     
214     private RelationMergeInfo createRelationMergeInfo(List<ComponentInstance> vfcInstances, String ownerId, Function<ComponentInstance, RelationMergeInfo> mapFunc) {
215         return vfcInstances.stream()
216                             .filter(inst -> StringUtils.equals(inst.getUniqueId(), ownerId))
217                             .map(mapFunc::apply)
218                             .filter(Objects::nonNull)
219                             .findAny()
220                             .orElse(null);
221     }
222     
223     
224     private RelationMergeInfo mapVfcInstanceCapability(ComponentInstance vfcInstance, RequirementCapabilityRelDef relDef) {
225         String capabilityUniqueId = relDef.resolveSingleRelationship().getRelation().getCapabilityUid();
226
227
228         String vfcInstanceName = vfcInstance.getName();
229         String vfcUid = vfcInstance.getComponentUid();
230
231         Either<Resource, StorageOperationStatus> vfcResource = toscaOperationFacade.getToscaElement(vfcUid);
232         if(vfcResource.isLeft()) {
233             Resource vfc = vfcResource.left().value();
234
235             CapabilityDefinition capabilityDef = retrieveCapabilityDefinition(capabilityUniqueId, vfc);
236             String capabilityType;
237             String capabilityName;
238             if (capabilityDef != null) {
239                 capabilityType = capabilityDef.getType();
240                 capabilityName = capabilityDef.getName();
241             }
242             else {
243                 log.debug("Failed to retrieve capability type for relation with name: {} and uniqueId {}", relDef.resolveSingleRelationship().getRelation().getCapability(), capabilityUniqueId);
244                 capabilityType = null;
245                 capabilityName = null;
246             }
247
248             return new RelationMergeInfo(capabilityType, capabilityName, vfcInstanceName, relDef);
249         }
250         else {
251             log.debug("Failed to load VFC by uid {}", vfcUid);
252             return null;
253         }
254     }
255     
256     private RelationMergeInfo mapVfcInstanceRequirement(ComponentInstance vfcInstance, RequirementCapabilityRelDef relDef) {
257         String requirementUniqueId = relDef.resolveSingleRelationship().getRelation().getRequirementUid();
258
259         String vfcInstanceName = vfcInstance.getName();
260         String vfcUid = vfcInstance.getComponentUid();
261
262         Either<Resource, StorageOperationStatus> vfcResource = toscaOperationFacade.getToscaElement(vfcUid);
263         if(vfcResource.isLeft()) {
264             Resource vfc = vfcResource.left().value();
265
266             RequirementDefinition requirementDef = retrieveRequirementDefinition(requirementUniqueId, vfc);
267             String requirementType;
268             String requirementName;
269             if (requirementDef != null) {
270                 requirementType = requirementDef.getCapability();
271                 requirementName = requirementDef.getName();
272             }
273             else {
274                 log.debug("Failed to retrieve requirement type for relation with name: {} and uniqueId {}", relDef.resolveSingleRelationship().getRelation().getRequirement(), requirementUniqueId);
275                 requirementType = null;
276                 requirementName = null;
277             }
278
279             return new RelationMergeInfo(requirementType, requirementName, vfcInstanceName, relDef);
280         }
281         else {
282             log.debug("Failed to load VFC by uid {}", vfcUid);
283             return null;
284         }
285     }
286
287     private CapabilityDefinition retrieveCapabilityDefinition(String uniqueId, Resource vfc) {
288         return vfc.getCapabilities().values().stream()
289                                                 .flatMap(List::stream)
290                                                 .filter(Objects::nonNull)
291                                                 .filter(def -> uniqueId.equals(def.getUniqueId()))
292                                                 .findFirst()
293                                                 .orElse(null);
294     }
295     
296     private String retrieveCapabilityUid(String name, Component vfc) {
297         return vfc.getCapabilities().values().stream()
298                                                 .flatMap(List::stream)
299                                                 .filter(Objects::nonNull)
300                                                 .filter(def -> name.equals(def.getName()))
301                                                 .findFirst()
302                                                 .map(CapabilityDefinition::getUniqueId)
303                                                 .orElse(null);
304     }
305
306     private RequirementDefinition retrieveRequirementDefinition(String uniqueId, Resource vfc) {
307         return vfc.getRequirements().values().stream()
308                                                 .flatMap(List::stream)
309                                                 .filter(Objects::nonNull)
310                                                 .filter(def -> uniqueId.equals(def.getUniqueId()))
311                                                 .findFirst()
312                                                 .orElse(null);
313     }
314
315     private String retrieveRequirementUid(String name, Component vfc) {
316         return vfc.getRequirements().values().stream()
317                                                 .flatMap(List::stream)
318                                                 .filter(Objects::nonNull)
319                                                 .filter(def -> name.equals(def.getName()))
320                                                 .findFirst()
321                                                 .map(RequirementDefinition::getUniqueId)
322                                                 .orElse(null);
323     }
324
325
326
327     private VfRelationsMergeInfo getRelationsMergeInfo(DataForMergeHolder dataHolder,
328                                                         Component updatedContainerComponent,
329                                                         Wrapper<Either<Component, ResponseFormat>> resultWrapper) {
330         VfRelationsMergeInfo vfRelationsMergeInfo = dataHolder.getVfRelationsMergeInfo();
331         if (vfRelationsMergeInfo == null) {
332             log.debug("There is no info about relations should be restored.");
333             resultWrapper.setInnerElement(Either.left(updatedContainerComponent));
334         }
335
336         return vfRelationsMergeInfo;
337     }
338
339
340     private RequirementCapabilityRelDef restoreCapabilityRelation(RelationMergeInfo oldCapInfo,
341                                                                   String newInstanceId,
342                                                                   Map<String, ComponentInstance> vfciMap,
343                                                                   Component updatedContainerComponent) {
344         String oldVfcInstanceName = oldCapInfo.getVfcInstanceName();
345
346         ComponentInstance newVfcInstance = vfciMap.get(oldVfcInstanceName);
347         if (newVfcInstance != null) {
348             // Append relation to updated container
349             RequirementCapabilityRelDef oldRelDef = oldCapInfo.getRelDef();
350             oldRelDef.setToNode(newInstanceId);
351
352             RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation();
353             oldRelationshipInfo.setCapabilityOwnerId(newVfcInstance.getUniqueId());
354             oldRelationshipInfo.getRelationship().setType(oldCapInfo.getCapReqType());
355
356
357             String vfcUid = newVfcInstance.getComponentUid();
358             Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(vfcUid);
359
360             if(eitherComponent.isLeft()) {
361                 String capabilityUid = retrieveCapabilityUid(oldCapInfo.getCapReqName() , eitherComponent.left().value());
362                 oldRelationshipInfo.setCapabilityUid(capabilityUid);
363             }
364             else {
365                 log.debug("Unexpected error: resource was not loaded for VF ID: {}", vfcUid);
366             }
367
368             updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef);
369             return oldRelDef;
370         }
371         else {
372             log.debug("Skip relation since it was not found VFC Instance with name {}", oldVfcInstanceName);
373             return null;
374         }
375     }
376
377
378
379     private RequirementCapabilityRelDef restoreRequirementRelation(RelationMergeInfo oldReqInfo,
380                                                                     String newInstanceId,
381                                                                    Map<String, ComponentInstance> vfciMap,
382                                                                    Component updatedContainerComponent) {
383         String oldVfcInstanceName = oldReqInfo.getVfcInstanceName();
384
385         ComponentInstance newVfcInstance = vfciMap.get(oldReqInfo.getVfcInstanceName());
386         if (newVfcInstance != null) {
387             // Append relation to updated container
388             RequirementCapabilityRelDef oldRelDef = oldReqInfo.getRelDef();
389             oldRelDef.setFromNode(newInstanceId);
390
391             RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation();
392             oldRelationshipInfo.setRequirementOwnerId(newVfcInstance.getUniqueId());
393             oldRelationshipInfo.getRelationship().setType(oldReqInfo.getCapReqType());
394
395             String vfcUid = newVfcInstance.getComponentUid();
396             Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(vfcUid);
397
398             if(eitherComponent.isLeft()) {
399                 String requirementUid = retrieveRequirementUid(oldReqInfo.getCapReqName() , eitherComponent.left().value());
400                 oldRelationshipInfo.setRequirementUid(requirementUid);
401             }
402             else {
403                 log.debug("Unexpected error: resource was not loaded for VF ID: {}", vfcUid);
404             }
405
406             updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef);
407             return oldRelDef;
408         }
409         else {
410             log.debug("Skip relation since it was not found VFC Instance with name {}", oldVfcInstanceName);
411             return null;
412         }
413     }
414
415     
416 }