1 package org.openecomp.sdc.be.components.merge.instance;
5 import java.util.Objects;
6 import java.util.function.Function;
7 import java.util.stream.Collectors;
8 import java.util.stream.Stream;
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;
29 import com.att.aft.dme2.internal.google.common.annotations.VisibleForTesting;
31 import fj.data.Either;
34 @org.springframework.stereotype.Component("ComponentInstanceRelashionMerge")
35 public class ComponentInstanceRelationMerge implements ComponentInstanceMergeInterface {
36 private static Logger log = LoggerFactory.getLogger(ComponentInstanceRelationMerge.class);
39 private ComponentsUtils componentsUtils;
42 private MergeInstanceUtils mergeInstanceUtils;
45 private ToscaOperationFacade toscaOperationFacade;
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,
54 currentResourceInstance);
56 List<RequirementCapabilityRelDef> relationsTo = getRelations(RequirementCapabilityRelDef::getToNode,
58 currentResourceInstance);
60 if (!relationsFrom.isEmpty() || !relationsTo.isEmpty()) {
61 List<ComponentInstance> vfcInstances = mergeInstanceUtils.getVfcInstances(currentResourceInstance, originComponent);
63 if (vfcInstances != null) {
64 List<RelationMergeInfo> fromRelInfoList = convert(relationsFrom, rel -> mapRelationRequirement(rel, vfcInstances));
65 List<RelationMergeInfo> toRelInfoList = convert(relationsTo, rel -> mapRelationCapability(rel, vfcInstances));
67 // Encapsulate all needed info in one container
68 VfRelationsMergeInfo vfRelationsMergeInfo = new VfRelationsMergeInfo(fromRelInfoList, toRelInfoList);
70 dataHolder.setVfRelationsInfo(vfRelationsMergeInfo);
74 log.debug("No relations relevant to currentResourceInstance {} found in container component", currentResourceInstance);
81 public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) {
82 Wrapper<Either<Component, ResponseFormat>> resultWrapper = new Wrapper<>();
84 VfRelationsMergeInfo vfRelationsMergeInfo = getRelationsMergeInfo(dataHolder, updatedContainerComponent, resultWrapper);
86 ComponentInstance newComponentInstance = null;
87 if(resultWrapper.isEmpty()) {
89 newComponentInstance = loadComponentInstance(updatedContainerComponent, newInstanceId, resultWrapper);
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);
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);
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);
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));
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));
130 return resultWrapper.getInnerElement();
134 public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) {
135 this.toscaOperationFacade = toscaOperationFacade;
140 public void setComponentsUtils(ComponentsUtils componentsUtils) {
141 this.componentsUtils = componentsUtils;
145 public void setMergeInstanceUtils(MergeInstanceUtils mergeInstanceUtils) {
146 this.mergeInstanceUtils = mergeInstanceUtils;
150 * @param containerComponent
152 * @param resultWrapper
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));
163 return componentInstance;
167 private List<RequirementCapabilityRelDef> getUpdatedRelations(Stream<RequirementCapabilityRelDef> toRelationsInfoStream,
168 Stream<RequirementCapabilityRelDef> fromRelationsInfoStream) {
169 Stream<RequirementCapabilityRelDef> updatedRelationsStream = Stream.empty();
171 if (toRelationsInfoStream != null) {
172 updatedRelationsStream = Stream.concat(updatedRelationsStream, toRelationsInfoStream);
175 if (fromRelationsInfoStream != null) {
176 updatedRelationsStream = Stream.concat(updatedRelationsStream, fromRelationsInfoStream);
179 return updatedRelationsStream.collect(Collectors.toList());
182 private List<RequirementCapabilityRelDef> getRelations(Function<RequirementCapabilityRelDef, String> getNodeFunc,
183 Component containerComponent,
184 ComponentInstance currentResourceInstance) {
186 final List<RequirementCapabilityRelDef> componentInstancesRelations = containerComponent.getComponentInstancesRelations();
187 final String vfInstanceId = currentResourceInstance.getUniqueId();
189 return componentInstancesRelations.stream()
190 .filter(rel -> StringUtils.equals(getNodeFunc.apply(rel), vfInstanceId))
191 .collect(Collectors.toList());
194 private List<RelationMergeInfo> convert(List<RequirementCapabilityRelDef> relationsDef,
195 Function<RequirementCapabilityRelDef, RelationMergeInfo> mapFunc) {
196 return relationsDef.stream()
198 .filter(Objects::nonNull)
199 .collect(Collectors.toList());
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));
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));
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))
218 .filter(Objects::nonNull)
224 private RelationMergeInfo mapVfcInstanceCapability(ComponentInstance vfcInstance, RequirementCapabilityRelDef relDef) {
225 String capabilityUniqueId = relDef.resolveSingleRelationship().getRelation().getCapabilityUid();
228 String vfcInstanceName = vfcInstance.getName();
229 String vfcUid = vfcInstance.getComponentUid();
231 Either<Resource, StorageOperationStatus> vfcResource = toscaOperationFacade.getToscaElement(vfcUid);
232 if(vfcResource.isLeft()) {
233 Resource vfc = vfcResource.left().value();
235 CapabilityDefinition capabilityDef = retrieveCapabilityDefinition(capabilityUniqueId, vfc);
236 String capabilityType;
237 String capabilityName;
238 if (capabilityDef != null) {
239 capabilityType = capabilityDef.getType();
240 capabilityName = capabilityDef.getName();
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;
248 return new RelationMergeInfo(capabilityType, capabilityName, vfcInstanceName, relDef);
251 log.debug("Failed to load VFC by uid {}", vfcUid);
256 private RelationMergeInfo mapVfcInstanceRequirement(ComponentInstance vfcInstance, RequirementCapabilityRelDef relDef) {
257 String requirementUniqueId = relDef.resolveSingleRelationship().getRelation().getRequirementUid();
259 String vfcInstanceName = vfcInstance.getName();
260 String vfcUid = vfcInstance.getComponentUid();
262 Either<Resource, StorageOperationStatus> vfcResource = toscaOperationFacade.getToscaElement(vfcUid);
263 if(vfcResource.isLeft()) {
264 Resource vfc = vfcResource.left().value();
266 RequirementDefinition requirementDef = retrieveRequirementDefinition(requirementUniqueId, vfc);
267 String requirementType;
268 String requirementName;
269 if (requirementDef != null) {
270 requirementType = requirementDef.getCapability();
271 requirementName = requirementDef.getName();
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;
279 return new RelationMergeInfo(requirementType, requirementName, vfcInstanceName, relDef);
282 log.debug("Failed to load VFC by uid {}", vfcUid);
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()))
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()))
302 .map(CapabilityDefinition::getUniqueId)
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()))
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()))
321 .map(RequirementDefinition::getUniqueId)
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));
336 return vfRelationsMergeInfo;
340 private RequirementCapabilityRelDef restoreCapabilityRelation(RelationMergeInfo oldCapInfo,
341 String newInstanceId,
342 Map<String, ComponentInstance> vfciMap,
343 Component updatedContainerComponent) {
344 String oldVfcInstanceName = oldCapInfo.getVfcInstanceName();
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);
352 RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation();
353 oldRelationshipInfo.setCapabilityOwnerId(newVfcInstance.getUniqueId());
354 oldRelationshipInfo.getRelationship().setType(oldCapInfo.getCapReqType());
357 String vfcUid = newVfcInstance.getComponentUid();
358 Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(vfcUid);
360 if(eitherComponent.isLeft()) {
361 String capabilityUid = retrieveCapabilityUid(oldCapInfo.getCapReqName() , eitherComponent.left().value());
362 oldRelationshipInfo.setCapabilityUid(capabilityUid);
365 log.debug("Unexpected error: resource was not loaded for VF ID: {}", vfcUid);
368 updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef);
372 log.debug("Skip relation since it was not found VFC Instance with name {}", oldVfcInstanceName);
379 private RequirementCapabilityRelDef restoreRequirementRelation(RelationMergeInfo oldReqInfo,
380 String newInstanceId,
381 Map<String, ComponentInstance> vfciMap,
382 Component updatedContainerComponent) {
383 String oldVfcInstanceName = oldReqInfo.getVfcInstanceName();
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);
391 RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation();
392 oldRelationshipInfo.setRequirementOwnerId(newVfcInstance.getUniqueId());
393 oldRelationshipInfo.getRelationship().setType(oldReqInfo.getCapReqType());
395 String vfcUid = newVfcInstance.getComponentUid();
396 Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(vfcUid);
398 if(eitherComponent.isLeft()) {
399 String requirementUid = retrieveRequirementUid(oldReqInfo.getCapReqName() , eitherComponent.left().value());
400 oldRelationshipInfo.setRequirementUid(requirementUid);
403 log.debug("Unexpected error: resource was not loaded for VF ID: {}", vfcUid);
406 updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef);
410 log.debug("Skip relation since it was not found VFC Instance with name {}", oldVfcInstanceName);