1 package org.openecomp.sdc.be.components.merge.instance;
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;
20 import java.util.Collections;
21 import java.util.List;
23 import java.util.Objects;
24 import java.util.function.Function;
25 import java.util.stream.Collectors;
26 import java.util.stream.Stream;
29 @org.springframework.stereotype.Component("ComponentInstanceRelashionMerge")
30 public class ComponentInstanceRelationMerge implements ComponentInstanceMergeInterface {
31 private static final Logger log = Logger.getLogger(ComponentInstanceRelationMerge.class);
33 private final ComponentsUtils componentsUtils;
34 private final MergeInstanceUtils mergeInstanceUtils;
35 private final ToscaOperationFacade toscaOperationFacade;
37 public ComponentInstanceRelationMerge(ComponentsUtils componentsUtils, MergeInstanceUtils mergeInstanceUtils, ToscaOperationFacade toscaOperationFacade) {
38 this.componentsUtils = componentsUtils;
39 this.mergeInstanceUtils = mergeInstanceUtils;
40 this.toscaOperationFacade = toscaOperationFacade;
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,
50 currentResourceInstance);
52 List<RequirementCapabilityRelDef> relationsTo = getRelations(RequirementCapabilityRelDef::getToNode,
54 currentResourceInstance);
56 if (!relationsFrom.isEmpty() || !relationsTo.isEmpty()) {
57 ComponentInstanceBuildingBlocks instBuildingBlocks = mergeInstanceUtils.getInstanceAtomicBuildingBlocks(currentResourceInstance, originComponent);
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()));
63 // Encapsulate all needed info in one container
64 ContainerRelationsMergeInfo containerRelationsMergeInfo = new ContainerRelationsMergeInfo(fromRelInfoList, toRelInfoList);
66 dataHolder.setVfRelationsInfo(containerRelationsMergeInfo);
70 log.debug("No relations relevant to currentResourceInstance {} found in container component", currentResourceInstance);
77 public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) {
78 Wrapper<Either<Component, ResponseFormat>> resultWrapper = new Wrapper<>();
80 ContainerRelationsMergeInfo containerRelationsMergeInfo = getRelationsMergeInfo(dataHolder, updatedContainerComponent, resultWrapper);
82 ComponentInstance newComponentInstance = null;
83 if(resultWrapper.isEmpty()) {
85 newComponentInstance = loadComponentInstance(updatedContainerComponent, newInstanceId, resultWrapper);
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));
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));
107 return resultWrapper.getInnerElement();
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);
119 return fromRelationsInfoStream;
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);
131 return toRelationsInfoStream;
135 * @param containerComponent
137 * @param resultWrapper
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));
148 return componentInstance;
152 private List<RequirementCapabilityRelDef> getUpdatedRelations(Stream<RequirementCapabilityRelDef> toRelationsInfoStream,
153 Stream<RequirementCapabilityRelDef> fromRelationsInfoStream) {
154 Stream<RequirementCapabilityRelDef> updatedRelationsStream = Stream.empty();
156 if (toRelationsInfoStream != null) {
157 updatedRelationsStream = Stream.concat(updatedRelationsStream, toRelationsInfoStream);
160 if (fromRelationsInfoStream != null) {
161 updatedRelationsStream = Stream.concat(updatedRelationsStream, fromRelationsInfoStream);
164 return updatedRelationsStream.collect(Collectors.toList());
167 private List<RequirementCapabilityRelDef> getRelations(Function<RequirementCapabilityRelDef, String> getNodeFunc,
168 Component containerComponent,
169 ComponentInstance currentResourceInstance) {
171 final List<RequirementCapabilityRelDef> componentInstancesRelations = containerComponent.getComponentInstancesRelations();
172 if (componentInstancesRelations == null) {
173 return Collections.emptyList();
176 final String vfInstanceId = currentResourceInstance.getUniqueId();
178 return componentInstancesRelations.stream()
179 .filter(rel -> StringUtils.equals(getNodeFunc.apply(rel), vfInstanceId))
180 .collect(Collectors.toList());
183 private List<RelationMergeInfo> convert(List<RequirementCapabilityRelDef> relationsDef,
184 Function<RequirementCapabilityRelDef, RelationMergeInfo> mapFunc) {
185 return relationsDef.stream()
187 .filter(Objects::nonNull)
188 .collect(Collectors.toList());
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));
200 return containerRelationsMergeInfo;