diff options
Diffstat (limited to 'catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceRelationMerge.java')
-rw-r--r-- | catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceRelationMerge.java | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceRelationMerge.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceRelationMerge.java new file mode 100644 index 0000000000..96f878abe0 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceRelationMerge.java @@ -0,0 +1,416 @@ +package org.openecomp.sdc.be.components.merge.instance; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.lang3.StringUtils; +import org.openecomp.sdc.be.components.merge.utils.MergeInstanceUtils; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.RelationshipInfo; +import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.att.aft.dme2.internal.google.common.annotations.VisibleForTesting; + +import fj.data.Either; + + +@org.springframework.stereotype.Component("ComponentInstanceRelashionMerge") +public class ComponentInstanceRelationMerge implements ComponentInstanceMergeInterface { + private static Logger log = LoggerFactory.getLogger(ComponentInstanceRelationMerge.class); + + @Autowired + private ComponentsUtils componentsUtils; + + @Autowired + private MergeInstanceUtils mergeInstanceUtils; + + @Autowired + private ToscaOperationFacade toscaOperationFacade; + + + @Override + public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance, Component originComponent) { + //All Relationships - container (service) holds info about all relations + //Filter by UniqueId in from/to + List<RequirementCapabilityRelDef> relationsFrom = getRelations(RequirementCapabilityRelDef::getFromNode, + containerComponent, + currentResourceInstance); + + List<RequirementCapabilityRelDef> relationsTo = getRelations(RequirementCapabilityRelDef::getToNode, + containerComponent, + currentResourceInstance); + + if (!relationsFrom.isEmpty() || !relationsTo.isEmpty()) { + List<ComponentInstance> vfcInstances = mergeInstanceUtils.getVfcInstances(currentResourceInstance, originComponent); + + if (vfcInstances != null) { + List<RelationMergeInfo> fromRelInfoList = convert(relationsFrom, rel -> mapRelationRequirement(rel, vfcInstances)); + List<RelationMergeInfo> toRelInfoList = convert(relationsTo, rel -> mapRelationCapability(rel, vfcInstances)); + + // Encapsulate all needed info in one container + VfRelationsMergeInfo vfRelationsMergeInfo = new VfRelationsMergeInfo(fromRelInfoList, toRelInfoList); + // Save it + dataHolder.setVfRelationsInfo(vfRelationsMergeInfo); + } + } + else { + log.debug("No relations relevant to currentResourceInstance {} found in container component", currentResourceInstance); + } + + } + + + @Override + public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) { + Wrapper<Either<Component, ResponseFormat>> resultWrapper = new Wrapper<>(); + + VfRelationsMergeInfo vfRelationsMergeInfo = getRelationsMergeInfo(dataHolder, updatedContainerComponent, resultWrapper); + + ComponentInstance newComponentInstance = null; + if(resultWrapper.isEmpty()) { + //Component Instance + newComponentInstance = loadComponentInstance(updatedContainerComponent, newInstanceId, resultWrapper); + } + + if(resultWrapper.isEmpty() && vfRelationsMergeInfo != null) { + // Load VFCI and filter them by name + List<ComponentInstance> vfcInstances = mergeInstanceUtils.getVfcInstances(newComponentInstance); + if(vfcInstances != null) { + Map<String, ComponentInstance> vfciMap = mergeInstanceUtils.convertToVfciNameMap(vfcInstances); + + // Process Relationships + List<RelationMergeInfo> toRelationsInfo = vfRelationsMergeInfo.getToRelationsInfo(); + Stream<RequirementCapabilityRelDef> toRelationsInfoStream = null; + if (toRelationsInfo != null) { + toRelationsInfoStream = toRelationsInfo.stream() + .map(oldCapInfo -> restoreCapabilityRelation(oldCapInfo, newInstanceId, vfciMap, updatedContainerComponent)) + .filter(Objects::nonNull); + } + + List<RelationMergeInfo> fromRelationsInfo = vfRelationsMergeInfo.getFromRelationsInfo(); + Stream<RequirementCapabilityRelDef> fromRelationsInfoStream = null; + if( fromRelationsInfo != null) { + //For Each old requirement relation info + fromRelationsInfoStream = fromRelationsInfo.stream() + .map(oldReqInfo -> restoreRequirementRelation(oldReqInfo, newInstanceId, vfciMap, updatedContainerComponent)) + .filter(Objects::nonNull); + } + + // Save relations in updated container (service) + List<RequirementCapabilityRelDef> updatedRelations = getUpdatedRelations(toRelationsInfoStream, fromRelationsInfoStream); + StorageOperationStatus saveResult = toscaOperationFacade.associateResourceInstances(updatedContainerComponent.getUniqueId(), updatedRelations); + if (saveResult == StorageOperationStatus.OK) { + resultWrapper.setInnerElement(Either.left(updatedContainerComponent)); + } + else { + log.debug("Failed to associate instances of resource {} status is {}", updatedContainerComponent.getUniqueId(), saveResult); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(saveResult), updatedContainerComponent.getUniqueId()); + resultWrapper.setInnerElement(Either.right(responseFormat)); + } + } + } + + return resultWrapper.getInnerElement(); + } + + @VisibleForTesting + public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) { + this.toscaOperationFacade = toscaOperationFacade; + } + + + @VisibleForTesting + public void setComponentsUtils(ComponentsUtils componentsUtils) { + this.componentsUtils = componentsUtils; + } + + @VisibleForTesting + public void setMergeInstanceUtils(MergeInstanceUtils mergeInstanceUtils) { + this.mergeInstanceUtils = mergeInstanceUtils; + } + + /** + * @param containerComponent + * @param instanceId + * @param resultWrapper + * @return + */ + private ComponentInstance loadComponentInstance(Component containerComponent, String instanceId, + Wrapper<Either<Component, ResponseFormat>> resultWrapper) { + ComponentInstance componentInstance = containerComponent.getComponentInstanceById(instanceId).orElse(null); + if (componentInstance == null) { + log.debug("Failed to get VF instance by new VF instance ID: {}", instanceId); + resultWrapper.setInnerElement(Either.left(containerComponent)); + } + + return componentInstance; + } + + + private List<RequirementCapabilityRelDef> getUpdatedRelations(Stream<RequirementCapabilityRelDef> toRelationsInfoStream, + Stream<RequirementCapabilityRelDef> fromRelationsInfoStream) { + Stream<RequirementCapabilityRelDef> updatedRelationsStream = Stream.empty(); + + if (toRelationsInfoStream != null) { + updatedRelationsStream = Stream.concat(updatedRelationsStream, toRelationsInfoStream); + } + + if (fromRelationsInfoStream != null) { + updatedRelationsStream = Stream.concat(updatedRelationsStream, fromRelationsInfoStream); + } + + return updatedRelationsStream.collect(Collectors.toList()); + } + + private List<RequirementCapabilityRelDef> getRelations(Function<RequirementCapabilityRelDef, String> getNodeFunc, + Component containerComponent, + ComponentInstance currentResourceInstance) { + + final List<RequirementCapabilityRelDef> componentInstancesRelations = containerComponent.getComponentInstancesRelations(); + final String vfInstanceId = currentResourceInstance.getUniqueId(); + + return componentInstancesRelations.stream() + .filter(rel -> StringUtils.equals(getNodeFunc.apply(rel), vfInstanceId)) + .collect(Collectors.toList()); + } + + private List<RelationMergeInfo> convert(List<RequirementCapabilityRelDef> relationsDef, + Function<RequirementCapabilityRelDef, RelationMergeInfo> mapFunc) { + return relationsDef.stream() + .map(mapFunc::apply) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private RelationMergeInfo mapRelationCapability(RequirementCapabilityRelDef relDef, List<ComponentInstance> vfcInstances) { + // Id of the VfcInstance that is the owner of the capability + String ownerId = relDef.resolveSingleRelationship().getRelation().getCapabilityOwnerId(); + return createRelationMergeInfo(vfcInstances, ownerId, currVfcInst -> mapVfcInstanceCapability(currVfcInst, relDef)); + } + + private RelationMergeInfo mapRelationRequirement(RequirementCapabilityRelDef relDef, List<ComponentInstance> vfcInstances) { + // Id of the VfcInstance that is the owner of the requirement + String ownerId = relDef.resolveSingleRelationship().getRelation().getRequirementOwnerId(); + return createRelationMergeInfo(vfcInstances, ownerId, currVfcInst -> mapVfcInstanceRequirement(currVfcInst, relDef)); + } + + private RelationMergeInfo createRelationMergeInfo(List<ComponentInstance> vfcInstances, String ownerId, Function<ComponentInstance, RelationMergeInfo> mapFunc) { + return vfcInstances.stream() + .filter(inst -> StringUtils.equals(inst.getUniqueId(), ownerId)) + .map(mapFunc::apply) + .filter(Objects::nonNull) + .findAny() + .orElse(null); + } + + + private RelationMergeInfo mapVfcInstanceCapability(ComponentInstance vfcInstance, RequirementCapabilityRelDef relDef) { + String capabilityUniqueId = relDef.resolveSingleRelationship().getRelation().getCapabilityUid(); + + + String vfcInstanceName = vfcInstance.getName(); + String vfcUid = vfcInstance.getComponentUid(); + + Either<Resource, StorageOperationStatus> vfcResource = toscaOperationFacade.getToscaElement(vfcUid); + if(vfcResource.isLeft()) { + Resource vfc = vfcResource.left().value(); + + CapabilityDefinition capabilityDef = retrieveCapabilityDefinition(capabilityUniqueId, vfc); + String capabilityType; + String capabilityName; + if (capabilityDef != null) { + capabilityType = capabilityDef.getType(); + capabilityName = capabilityDef.getName(); + } + else { + log.debug("Failed to retrieve capability type for relation with name: {} and uniqueId {}", relDef.resolveSingleRelationship().getRelation().getCapability(), capabilityUniqueId); + capabilityType = null; + capabilityName = null; + } + + return new RelationMergeInfo(capabilityType, capabilityName, vfcInstanceName, relDef); + } + else { + log.debug("Failed to load VFC by uid {}", vfcUid); + return null; + } + } + + private RelationMergeInfo mapVfcInstanceRequirement(ComponentInstance vfcInstance, RequirementCapabilityRelDef relDef) { + String requirementUniqueId = relDef.resolveSingleRelationship().getRelation().getRequirementUid(); + + String vfcInstanceName = vfcInstance.getName(); + String vfcUid = vfcInstance.getComponentUid(); + + Either<Resource, StorageOperationStatus> vfcResource = toscaOperationFacade.getToscaElement(vfcUid); + if(vfcResource.isLeft()) { + Resource vfc = vfcResource.left().value(); + + RequirementDefinition requirementDef = retrieveRequirementDefinition(requirementUniqueId, vfc); + String requirementType; + String requirementName; + if (requirementDef != null) { + requirementType = requirementDef.getCapability(); + requirementName = requirementDef.getName(); + } + else { + log.debug("Failed to retrieve requirement type for relation with name: {} and uniqueId {}", relDef.resolveSingleRelationship().getRelation().getRequirement(), requirementUniqueId); + requirementType = null; + requirementName = null; + } + + return new RelationMergeInfo(requirementType, requirementName, vfcInstanceName, relDef); + } + else { + log.debug("Failed to load VFC by uid {}", vfcUid); + return null; + } + } + + private CapabilityDefinition retrieveCapabilityDefinition(String uniqueId, Resource vfc) { + return vfc.getCapabilities().values().stream() + .flatMap(List::stream) + .filter(Objects::nonNull) + .filter(def -> uniqueId.equals(def.getUniqueId())) + .findFirst() + .orElse(null); + } + + private String retrieveCapabilityUid(String name, Component vfc) { + return vfc.getCapabilities().values().stream() + .flatMap(List::stream) + .filter(Objects::nonNull) + .filter(def -> name.equals(def.getName())) + .findFirst() + .map(CapabilityDefinition::getUniqueId) + .orElse(null); + } + + private RequirementDefinition retrieveRequirementDefinition(String uniqueId, Resource vfc) { + return vfc.getRequirements().values().stream() + .flatMap(List::stream) + .filter(Objects::nonNull) + .filter(def -> uniqueId.equals(def.getUniqueId())) + .findFirst() + .orElse(null); + } + + private String retrieveRequirementUid(String name, Component vfc) { + return vfc.getRequirements().values().stream() + .flatMap(List::stream) + .filter(Objects::nonNull) + .filter(def -> name.equals(def.getName())) + .findFirst() + .map(RequirementDefinition::getUniqueId) + .orElse(null); + } + + + + private VfRelationsMergeInfo getRelationsMergeInfo(DataForMergeHolder dataHolder, + Component updatedContainerComponent, + Wrapper<Either<Component, ResponseFormat>> resultWrapper) { + VfRelationsMergeInfo vfRelationsMergeInfo = dataHolder.getVfRelationsMergeInfo(); + if (vfRelationsMergeInfo == null) { + log.debug("There is no info about relations should be restored."); + resultWrapper.setInnerElement(Either.left(updatedContainerComponent)); + } + + return vfRelationsMergeInfo; + } + + + private RequirementCapabilityRelDef restoreCapabilityRelation(RelationMergeInfo oldCapInfo, + String newInstanceId, + Map<String, ComponentInstance> vfciMap, + Component updatedContainerComponent) { + String oldVfcInstanceName = oldCapInfo.getVfcInstanceName(); + + ComponentInstance newVfcInstance = vfciMap.get(oldVfcInstanceName); + if (newVfcInstance != null) { + // Append relation to updated container + RequirementCapabilityRelDef oldRelDef = oldCapInfo.getRelDef(); + oldRelDef.setToNode(newInstanceId); + + RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation(); + oldRelationshipInfo.setCapabilityOwnerId(newVfcInstance.getUniqueId()); + oldRelationshipInfo.getRelationship().setType(oldCapInfo.getCapReqType()); + + + String vfcUid = newVfcInstance.getComponentUid(); + Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(vfcUid); + + if(eitherComponent.isLeft()) { + String capabilityUid = retrieveCapabilityUid(oldCapInfo.getCapReqName() , eitherComponent.left().value()); + oldRelationshipInfo.setCapabilityUid(capabilityUid); + } + else { + log.debug("Unexpected error: resource was not loaded for VF ID: {}", vfcUid); + } + + updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef); + return oldRelDef; + } + else { + log.debug("Skip relation since it was not found VFC Instance with name {}", oldVfcInstanceName); + return null; + } + } + + + + private RequirementCapabilityRelDef restoreRequirementRelation(RelationMergeInfo oldReqInfo, + String newInstanceId, + Map<String, ComponentInstance> vfciMap, + Component updatedContainerComponent) { + String oldVfcInstanceName = oldReqInfo.getVfcInstanceName(); + + ComponentInstance newVfcInstance = vfciMap.get(oldReqInfo.getVfcInstanceName()); + if (newVfcInstance != null) { + // Append relation to updated container + RequirementCapabilityRelDef oldRelDef = oldReqInfo.getRelDef(); + oldRelDef.setFromNode(newInstanceId); + + RelationshipInfo oldRelationshipInfo = oldRelDef.resolveSingleRelationship().getRelation(); + oldRelationshipInfo.setRequirementOwnerId(newVfcInstance.getUniqueId()); + oldRelationshipInfo.getRelationship().setType(oldReqInfo.getCapReqType()); + + String vfcUid = newVfcInstance.getComponentUid(); + Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(vfcUid); + + if(eitherComponent.isLeft()) { + String requirementUid = retrieveRequirementUid(oldReqInfo.getCapReqName() , eitherComponent.left().value()); + oldRelationshipInfo.setRequirementUid(requirementUid); + } + else { + log.debug("Unexpected error: resource was not loaded for VF ID: {}", vfcUid); + } + + updatedContainerComponent.getComponentInstancesRelations().add(oldRelDef); + return oldRelDef; + } + else { + log.debug("Skip relation since it was not found VFC Instance with name {}", oldVfcInstanceName); + return null; + } + } + + +} |