diff options
Diffstat (limited to 'catalog-be/src/main/java/org/openecomp/sdc/be/components/merge')
33 files changed, 1334 insertions, 209 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalInputsFilteringBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalInputsFilteringBusinessLogic.java index 9c140b36c7..e6dd6457cf 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalInputsFilteringBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalInputsFilteringBusinessLogic.java @@ -1,9 +1,6 @@ package org.openecomp.sdc.be.components.merge; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - +import fj.data.Either; import org.openecomp.sdc.be.components.impl.BaseBusinessLogic; import org.openecomp.sdc.be.components.impl.generic.GenericTypeBusinessLogic; import org.openecomp.sdc.be.dao.api.ActionStatus; @@ -12,7 +9,9 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.springframework.stereotype.Component; -import fj.data.Either; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; @Component public class GlobalInputsFilteringBusinessLogic extends BaseBusinessLogic { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalTypesMergeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalTypesMergeBusinessLogic.java index eb359e949e..4bd799805f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalTypesMergeBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/GlobalTypesMergeBusinessLogic.java @@ -1,7 +1,6 @@ package org.openecomp.sdc.be.components.merge; -import java.util.List; - +import fj.data.Either; import org.openecomp.sdc.be.components.merge.input.ComponentInputsMergeBL; import org.openecomp.sdc.be.components.merge.resource.MergeResourceBusinessLogic; import org.openecomp.sdc.be.dao.api.ActionStatus; @@ -11,7 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; -import fj.data.Either; +import java.util.List; @Component public class GlobalTypesMergeBusinessLogic implements MergeResourceBusinessLogic { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/RelationsComparator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/RelationsComparator.java index 6c20e501f9..058d4c2555 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/RelationsComparator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/RelationsComparator.java @@ -1,15 +1,15 @@ package org.openecomp.sdc.be.components.merge; -import java.util.List; -import java.util.Map; -import java.util.Optional; - 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.Resource; import org.springframework.stereotype.Component; +import java.util.List; +import java.util.Map; +import java.util.Optional; + @Component public class RelationsComparator { @@ -45,8 +45,8 @@ public class RelationsComparator { private boolean findRelation(Resource oldResource, List<RequirementCapabilityRelDef> oldRelations, Resource newResource, RequirementCapabilityRelDef newRelation) { for (RequirementCapabilityRelDef oldRelation : oldRelations) { - RelationshipInfo oldRelationship = oldRelation.getSingleRelationship().getRelation(); - RelationshipInfo newRelationship = newRelation.getSingleRelationship().getRelation(); + RelationshipInfo oldRelationship = oldRelation.resolveSingleRelationship().getRelation(); + RelationshipInfo newRelationship = newRelation.resolveSingleRelationship().getRelation(); if (oldRelationship != null && newRelationship != null && isRelationEqual(oldRelationship, newRelationship) && isRelationToNodeEquals(oldResource, oldRelation, newResource, newRelation)) { return true; } @@ -70,12 +70,12 @@ public class RelationsComparator { private boolean isRelationshipCapabilityEquals(RelationshipInfo oldRelationship, RelationshipInfo newRelationship) { if(oldRelationship.getCapabilityUid() !=null && newRelationship.getCapabilityUid() != null){ - return oldRelationship.getCapabilityUid().equals(newRelationship.getCapabilityUid()); + return oldRelationship.getCapabilityUid().equals(newRelationship.getCapabilityUid()); } else if(oldRelationship.getCapabilityUid() == null && newRelationship.getCapabilityUid() == null){ - return true; + return true; } - return false; + return false; } private boolean isRelationshipTypeEquals(RelationshipInfo oldRelationship, RelationshipInfo newRelationship) { @@ -84,12 +84,12 @@ public class RelationsComparator { private boolean isRelationshipReqNameEquals(RelationshipInfo oldRelationship, RelationshipInfo newRelationship) { if(oldRelationship.getRequirement() != null && newRelationship.getRequirement() != null){ - return oldRelationship.getRequirement().equals(newRelationship.getRequirement()); + return oldRelationship.getRequirement().equals(newRelationship.getRequirement()); } else if(oldRelationship.getRequirement() == null && newRelationship.getRequirement() == null){ - return true; + return true; } - return false; + return false; } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/TopologyComparator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/TopologyComparator.java index 8b48b0897a..0f68f9f409 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/TopologyComparator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/TopologyComparator.java @@ -1,8 +1,6 @@ package org.openecomp.sdc.be.components.merge; -import java.util.List; -import java.util.Map; - +import fj.data.Either; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.exception.SdcActionException; @@ -15,7 +13,8 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import fj.data.Either; +import java.util.List; +import java.util.Map; @org.springframework.stereotype.Component public class TopologyComparator { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/capability/CapabilityResolver.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/capability/CapabilityResolver.java new file mode 100644 index 0000000000..0a467ef876 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/capability/CapabilityResolver.java @@ -0,0 +1,29 @@ +package org.openecomp.sdc.be.components.merge.capability; + +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; + +import java.util.List; +import java.util.Map; + +public interface CapabilityResolver { + + /** + * + * @param container the instance container + * @param prevInstanceOrigNode the prev instance's original node type + * @param cmptInstanceId the current instance id + * @param prevCapabilities list of previous capabilities for which to find their corresponding new capabilities + * @return a mapping between the prev capability to its corresponding new capability (if exists) + */ + Map<CapabilityDefinition, CapabilityDefinition> resolvePrevCapToNewCapability(Component container, Component prevInstanceOrigNode, String cmptInstanceId, List<CapabilityDefinition> prevCapabilities); + + /** + * + * @param oldInstance the old instance of which its capabilities are to be mapped as the key + * @param currInstance the curr instance of which its capabilities are to be mapped as the value + * @return a mapping between the prev capability to its corresponding new capability (if exists) + */ + Map<CapabilityDefinition, CapabilityDefinition> resolvePrevCapIdToNewCapability(ComponentInstance oldInstance, ComponentInstance currInstance); +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/capability/SimpleCapabilityResolver.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/capability/SimpleCapabilityResolver.java new file mode 100644 index 0000000000..8400b32f9b --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/capability/SimpleCapabilityResolver.java @@ -0,0 +1,82 @@ +package org.openecomp.sdc.be.components.merge.capability; + +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.sdc.be.components.merge.utils.MergeInstanceUtils; +import org.openecomp.sdc.be.dao.utils.MapUtil; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; + +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +@org.springframework.stereotype.Component +public class SimpleCapabilityResolver implements CapabilityResolver { + + private MergeInstanceUtils mergeInstanceUtils; + + public SimpleCapabilityResolver(MergeInstanceUtils mergeInstanceUtils) { + this.mergeInstanceUtils = mergeInstanceUtils; + } + + @Override + public Map<CapabilityDefinition, CapabilityDefinition> resolvePrevCapToNewCapability(Component container, Component prevInstanceOrigNode, String cmptInstanceId, List<CapabilityDefinition> prevCapabilities) { + Map<String, List<CapabilityDefinition>> newCapabilitiesByType = resolveInstanceCapabilities(container, cmptInstanceId).getCapabilities(); + Map<String, String> oldCapOwnerToNewOwner = mapOldToNewCapabilitiesOwnerIds(container, prevInstanceOrigNode, cmptInstanceId, prevCapabilities); + return mapOldToNewCapabilities(prevCapabilities, newCapabilitiesByType, oldCapOwnerToNewOwner); + } + + @Override + public Map<CapabilityDefinition, CapabilityDefinition> resolvePrevCapIdToNewCapability(ComponentInstance oldInstance, ComponentInstance currInstance) { + Map<String, List<CapabilityDefinition>> newCapabilitiesByType = currInstance.getCapabilities(); + Map<String, String> oldCapOwnerToNewOwner = mergeInstanceUtils.mapOldToNewCapabilitiesOwnerIds(oldInstance, currInstance); + List<CapabilityDefinition> prevCapabilities = oldInstance.getCapabilities().values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + return mapOldToNewCapabilities(prevCapabilities, newCapabilitiesByType, oldCapOwnerToNewOwner); + } + + private Map<CapabilityDefinition, CapabilityDefinition> mapOldToNewCapabilities(List<CapabilityDefinition> prevCapabilities, Map<String, List<CapabilityDefinition>> newCapabilitiesByType, Map<String, String> oldCapOwnerToNewOwner) { + Map<CapabilityDefinition, CapabilityDefinition> oldToNewCapability = prevCapabilities + .stream() + .collect(HashMap::new, + (resultMap, prevCap) -> mapOldToNewCapability(newCapabilitiesByType, oldCapOwnerToNewOwner, resultMap, prevCap), + HashMap::putAll); + removeNotFoundNewCapabilities(oldToNewCapability); + return oldToNewCapability; + } + + private CapabilityDefinition mapOldToNewCapability(Map<String, List<CapabilityDefinition>> newCapabilitiesByType, Map<String, String> oldCapOwnerToNewOwner, Map<CapabilityDefinition, CapabilityDefinition> resultMap, CapabilityDefinition prevCap) { + return resultMap.put(prevCap, findCurrCapability(newCapabilitiesByType, prevCap, oldCapOwnerToNewOwner.get(prevCap.getOwnerId()))); + } + + private Map<String, String> mapOldToNewCapabilitiesOwnerIds(Component container, Component origInstanceNode, String cmptInstanceId, List<CapabilityDefinition> prevCapabilities) { + List<String> prevCapOwnerIds = prevCapabilities.stream().map(CapabilityDefinition::getOwnerId).distinct().collect(Collectors.toList()); + return mergeInstanceUtils.mapOldToNewCapabilitiesOwnerIds(container, origInstanceNode, cmptInstanceId, prevCapOwnerIds); + } + + private void removeNotFoundNewCapabilities(Map<CapabilityDefinition, CapabilityDefinition> oldToNewCapMap) { + oldToNewCapMap.values().removeIf(Objects::isNull); + } + + private ComponentInstance resolveInstanceCapabilities(Component capabilityOwnerContainer, String cmptInstanceId) { + return MapUtil.toMap(capabilityOwnerContainer.getComponentInstances(), ComponentInstance::getUniqueId).get(cmptInstanceId); + } + + + private CapabilityDefinition findCurrCapability(Map<String, List<CapabilityDefinition>> capabilitiesByType, CapabilityDefinition oldCap, String newCapOwnerId) { + List<CapabilityDefinition> newCapOfType = capabilitiesByType.get(oldCap.getType()); + if (newCapOwnerId == null || CollectionUtils.isEmpty(newCapOfType)) { + return null; + } + return newCapOfType.stream().filter(sameNameAndOwner(oldCap.getName(), newCapOwnerId)) + .findFirst().orElse(null); + + } + + private Predicate<CapabilityDefinition> sameNameAndOwner(String capName, String newCapOwnerId) { + return newCap -> newCap.getName().equals(capName) && newCap.getOwnerId().equals(newCapOwnerId); + } + + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/heat/HeatEnvArtifactsMergeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/heat/HeatEnvArtifactsMergeBusinessLogic.java index 1e1bc862cf..82deee598d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/heat/HeatEnvArtifactsMergeBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/heat/HeatEnvArtifactsMergeBusinessLogic.java @@ -1,15 +1,15 @@ package org.openecomp.sdc.be.components.merge.heat; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.model.ArtifactDefinition; import org.openecomp.sdc.be.model.HeatParameterDefinition; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + /** * Created by chaya on 9/14/2017. */ diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/ComponentInputsMergeBL.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/ComponentInputsMergeBL.java index b8ea5e35c4..be5e5367b8 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/ComponentInputsMergeBL.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/ComponentInputsMergeBL.java @@ -1,9 +1,7 @@ package org.openecomp.sdc.be.components.merge.input; -import java.util.Collections; -import java.util.List; -import java.util.Map; - +import fj.data.Either; +import org.openecomp.sdc.be.components.merge.instance.ComponentsMergeCommand; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.impl.ComponentsUtils; @@ -12,10 +10,13 @@ import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import fj.data.Either; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; @org.springframework.stereotype.Component -public class ComponentInputsMergeBL { +public class ComponentInputsMergeBL implements ComponentsMergeCommand { @javax.annotation.Resource private InputsValuesMergingBusinessLogic inputsValuesMergingBusinessLogic; @@ -26,6 +27,17 @@ public class ComponentInputsMergeBL { @javax.annotation.Resource private ComponentsUtils componentsUtils; + @Override + public ActionStatus mergeComponents(Component prevComponent, Component currentComponent) { + List<InputDefinition> inputsToMerge = currentComponent.getInputs() != null ? currentComponent.getInputs() : new ArrayList<>(); + return this.mergeAndRedeclareComponentInputs(prevComponent, currentComponent, inputsToMerge); + } + + @Override + public String description() { + return "merge component inputs"; + } + public ActionStatus mergeAndRedeclareComponentInputs(Component prevComponent, Component newComponent, List<InputDefinition> inputsToMerge) { mergeInputs(prevComponent, inputsToMerge); List<InputDefinition> previouslyDeclaredInputs = inputsValuesMergingBusinessLogic.getPreviouslyDeclaredInputsToMerge(prevComponent, newComponent); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/InputsValuesMergingBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/InputsValuesMergingBusinessLogic.java index e49d2b2c87..e0e7947226 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/InputsValuesMergingBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/input/InputsValuesMergingBusinessLogic.java @@ -1,12 +1,5 @@ package org.openecomp.sdc.be.components.merge.input; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - import org.apache.commons.lang.StringUtils; import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; @@ -14,6 +7,9 @@ import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.InputDefinition; +import java.util.*; +import java.util.stream.Collectors; + @org.springframework.stereotype.Component public class InputsValuesMergingBusinessLogic { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentCapabilitiesPropertiesMergeBL.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentCapabilitiesPropertiesMergeBL.java new file mode 100644 index 0000000000..e7117a2aeb --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentCapabilitiesPropertiesMergeBL.java @@ -0,0 +1,103 @@ +package org.openecomp.sdc.be.components.merge.instance; + +import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.sdc.be.components.merge.capability.CapabilityResolver; +import org.openecomp.sdc.be.components.merge.property.DataDefinitionsValuesMergingBusinessLogic; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.utils.MapUtil; +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.ComponentParametersView; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +@org.springframework.stereotype.Component +public class ComponentCapabilitiesPropertiesMergeBL implements ComponentsMergeCommand { + + private static final Logger LOGGER = LoggerFactory.getLogger(ComponentCapabilitiesPropertiesMergeBL.class); + + private DataDefinitionsValuesMergingBusinessLogic dataDefinitionsValuesMergingBusinessLogic; + private ToscaOperationFacade toscaOperationFacade; + private ComponentsUtils componentsUtils; + private CapabilityResolver capabilityResolver; + + public ComponentCapabilitiesPropertiesMergeBL(DataDefinitionsValuesMergingBusinessLogic dataDefinitionsValuesMergingBusinessLogic, ToscaOperationFacade toscaOperationFacade, ComponentsUtils componentsUtils, CapabilityResolver capabilityResolver) { + this.dataDefinitionsValuesMergingBusinessLogic = dataDefinitionsValuesMergingBusinessLogic; + this.toscaOperationFacade = toscaOperationFacade; + this.componentsUtils = componentsUtils; + this.capabilityResolver = capabilityResolver; + } + + @Override + public String description() { + return "merge component instances capabilities properties"; + } + + @Override + public ActionStatus mergeComponents(Component prevComponent, Component currentComponent) { + StorageOperationStatus mergeStatus = getCmptWithCapabilitiesProps(currentComponent.getUniqueId()) + .either(currCmptWithCap -> mergeCmptCalculatedCapabilitiesProperties(prevComponent, currCmptWithCap), + err -> err); + return componentsUtils.convertFromStorageResponse(mergeStatus); + } + + public ActionStatus mergeComponentInstanceCapabilities(Component currentComponent, Component origInstanceCmpt, String instanceId, List<CapabilityDefinition> prevInstanceCapabilities) { + if (CollectionUtils.isEmpty(prevInstanceCapabilities)) { + return ActionStatus.OK; + } + Map<CapabilityDefinition, CapabilityDefinition> oldToNewCap = capabilityResolver.resolvePrevCapToNewCapability(currentComponent, origInstanceCmpt, instanceId, prevInstanceCapabilities); + oldToNewCap.forEach(this::mergeCapabilityProperties); + StorageOperationStatus updateStatus = updateInstanceCapabilitiesProperties(currentComponent, instanceId); + return componentsUtils.convertFromStorageResponse(updateStatus); + } + + private StorageOperationStatus mergeCmptCalculatedCapabilitiesProperties(Component prevComponent, Component currentComponent) { + List<ComponentInstance> prevInstances = prevComponent.getComponentInstances(); + if (prevInstances == null) { + return StorageOperationStatus.OK; + } + prevInstances.forEach(prevInstance -> mergeInstanceCapabilities(prevInstance, currentComponent)); + return updateComponentCapabilitiesProperties(currentComponent); + } + + private void mergeInstanceCapabilities(ComponentInstance prevInstance, Component currComponent) { + ComponentInstance currInstance = MapUtil.toMap(currComponent.getComponentInstances(), ComponentInstance::getName).get(prevInstance.getName()); + Map<CapabilityDefinition, CapabilityDefinition> oldToNewCapabilities = capabilityResolver.resolvePrevCapIdToNewCapability(prevInstance, currInstance); + oldToNewCapabilities.forEach(this::mergeCapabilityProperties); + } + + private void mergeCapabilityProperties(CapabilityDefinition prevCapability, CapabilityDefinition currCapability) { + dataDefinitionsValuesMergingBusinessLogic.mergeInstanceDataDefinitions(prevCapability.getProperties(), currCapability.getProperties()); + } + + private StorageOperationStatus updateComponentCapabilitiesProperties(Component currComponent) { + return toscaOperationFacade.updateComponentCalculatedCapabilitiesProperties(currComponent); + } + + private StorageOperationStatus updateInstanceCapabilitiesProperties(Component currComponent, String instanceId) { + return toscaOperationFacade.updateComponentInstanceCapabilityProperties(currComponent, instanceId); + } + + private Either<Component, StorageOperationStatus> getCmptWithCapabilitiesProps(String cmptId) { + ComponentParametersView propertiesCapabilitiesFilter = new ComponentParametersView(true); + propertiesCapabilitiesFilter.setIgnoreCapabiltyProperties(false); + propertiesCapabilitiesFilter.setIgnoreComponentInstances(false); + propertiesCapabilitiesFilter.setIgnoreCapabilities(false); + return toscaOperationFacade.getToscaElement(cmptId, propertiesCapabilitiesFilter) + .right() + .map(err -> { + LOGGER.debug("failed to fetch cmpt {} with properties capabilities. status: {}", cmptId, err); + return err; + }); + + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceArtifactsMerge.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceArtifactsMerge.java index cac8c977e3..d16fa251e2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceArtifactsMerge.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceArtifactsMerge.java @@ -1,10 +1,6 @@ package org.openecomp.sdc.be.components.merge.instance; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - +import fj.data.Either; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic; import org.openecomp.sdc.be.model.ArtifactDefinition; import org.openecomp.sdc.be.model.Component; @@ -16,7 +12,10 @@ import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; -import fj.data.Either; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; /** * Created by chaya on 9/20/2017. @@ -81,7 +80,7 @@ public class ComponentInstanceArtifactsMerge implements ComponentInstanceMergeIn Either<Either<ArtifactDefinition, Operation>, ResponseFormat> uploadArtifactToService = artifactsBusinessLogic.updateResourceInstanceArtifactNoContent(newInstanceId, updatedContainerComponent, user, jsonForUpdateArtifact, artifactsBusinessLogic.new ArtifactOperationInfo( - false, false, ArtifactsBusinessLogic.ArtifactOperationEnum.Link), currentArtifactDefinition.getValue()); + false, false, ArtifactsBusinessLogic.ArtifactOperationEnum.LINK), currentArtifactDefinition.getValue()); if (uploadArtifactToService.isRight()) { return Either.right(uploadArtifactToService.right().value()); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceCapabiliteisPropertiesMerge.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceCapabiliteisPropertiesMerge.java new file mode 100644 index 0000000000..afad19baf2 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceCapabiliteisPropertiesMerge.java @@ -0,0 +1,47 @@ +package org.openecomp.sdc.be.components.merge.instance; + +import fj.data.Either; +import org.openecomp.sdc.be.dao.api.ActionStatus; +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.User; +import org.openecomp.sdc.exception.ResponseFormat; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static org.apache.commons.collections.MapUtils.isNotEmpty; + +@org.springframework.stereotype.Component +public class ComponentInstanceCapabiliteisPropertiesMerge implements ComponentInstanceMergeInterface { + + private ComponentCapabilitiesPropertiesMergeBL capabilitiesPropertiesMergeBL; + private ComponentsUtils componentsUtils; + + public ComponentInstanceCapabiliteisPropertiesMerge(ComponentCapabilitiesPropertiesMergeBL capabilitiesPropertiesMergeBL, ComponentsUtils componentsUtils) { + this.capabilitiesPropertiesMergeBL = capabilitiesPropertiesMergeBL; + this.componentsUtils = componentsUtils; + } + + @Override + public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance, Component originComponent) { + dataHolder.setOrigInstanceCapabilities(getAllInstanceCapabilities(currentResourceInstance)); + dataHolder.setOrigInstanceNode(originComponent); + } + + @Override + public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) { + Component origInstanceNode = dataHolder.getOrigInstanceNode(); + List<CapabilityDefinition> origInstanceCapabilities = dataHolder.getOrigInstanceCapabilities(); + ActionStatus mergeStatus = capabilitiesPropertiesMergeBL.mergeComponentInstanceCapabilities(updatedContainerComponent, origInstanceNode, newInstanceId, origInstanceCapabilities); + return Either.iif(!ActionStatus.OK.equals(mergeStatus), () -> componentsUtils.getResponseFormat(mergeStatus), () -> updatedContainerComponent); + } + + private List<CapabilityDefinition> getAllInstanceCapabilities(ComponentInstance currentResourceInstance) { + return isNotEmpty( currentResourceInstance.getCapabilities() ) ? currentResourceInstance.getCapabilities().values().stream().flatMap(Collection::stream).collect(Collectors.toList()) : new ArrayList<>() ; + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceForwardingPathMerge.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceForwardingPathMerge.java new file mode 100644 index 0000000000..20a5abc591 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceForwardingPathMerge.java @@ -0,0 +1,113 @@ +package org.openecomp.sdc.be.components.merge.instance; + +import fj.data.Either; +import org.javatuples.Pair; +import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ForwardingPathUtils; +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.Service; +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.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@org.springframework.stereotype.Component +public class ComponentInstanceForwardingPathMerge implements ComponentInstanceMergeInterface { + + private static Logger log = LoggerFactory.getLogger(ComponentInstanceForwardingPathMerge.class); + + @Autowired + private ServiceBusinessLogic serviceBusinessLogic; + + @Autowired + private ToscaOperationFacade toscaOperationFacade; + + @Autowired + private ComponentsUtils componentsUtils; + + @Override + public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, + ComponentInstance currentResourceInstance, Component originComponent) { + dataHolder.setOrigInstanceCapabilities(getAllInstanceCapabilities(currentResourceInstance)); + dataHolder.setOrigInstanceNode(originComponent); + dataHolder.setOrigComponentInstId(currentResourceInstance.getUniqueId()); + } + + @Override + public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, + Component updatedContainerComponent, String newInstanceId) { + if (!(updatedContainerComponent instanceof Service)) { + // no need to handle forwarding paths + return Either.left(updatedContainerComponent); + } + Service service = (Service) updatedContainerComponent; + ComponentInstance ci = service.getComponentInstanceById(newInstanceId).orElse(null); + if (ci == null){ + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, newInstanceId); + return Either.right(responseFormat); + } + Either<Component, StorageOperationStatus> resourceEither = toscaOperationFacade.getToscaFullElement(ci.getComponentUid()); + if (resourceEither.isRight() ) { + log.debug("Failed to fetch resource with id {} for instance {}",ci.getComponentUid() ,ci.getUniqueId()); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(resourceEither.right().value())); + return Either.right(responseFormat); + } + + Component fetchedComponent = resourceEither.left().value(); + + Pair<Map<String, ForwardingPathDataDefinition>, Map<String, ForwardingPathDataDefinition>> pair = new ForwardingPathUtils() + .updateForwardingPathOnVersionChange(service, dataHolder, fetchedComponent, newInstanceId); + Map<String, ForwardingPathDataDefinition> updated = pair.getValue0(); + Map<String, ForwardingPathDataDefinition> deleted = pair.getValue1(); + if (deleted != null && !deleted.isEmpty()) { + Either<Set<String>, ResponseFormat> deleteEither = serviceBusinessLogic + .deleteForwardingPaths(service.getUniqueId(), new HashSet<>(deleted.keySet()), user, false); + if (deleteEither.isRight()) { + if (log.isDebugEnabled()) { + log.debug("Failed to delete forwarding paths : {}", deleted.values().stream() + .map(ForwardingPathDataDefinition::getName).collect(Collectors.joining(", ", "( ", " )"))); + } + return Either.right(deleteEither.right().value()); + } + deleted.keySet().forEach(key -> service.getForwardingPaths().remove(key)); + } + if (updated != null && !updated.isEmpty()) { + Service updateFPService = new Service(); + updateFPService.setForwardingPaths(updated); + Either<Service, ResponseFormat> updateFPEither = serviceBusinessLogic + .updateForwardingPath(service.getUniqueId(), updateFPService, user, false); + if (updateFPEither.isRight()) { + if (log.isDebugEnabled()) { + log.debug("Failed to update forwarding paths : {}", updated.values().stream() + .map(ForwardingPathDataDefinition::getName).collect(Collectors.joining(", ", "( ", " )"))); + } + return Either.right(updateFPEither.right().value()); + } + updated.forEach((key, forwardingPathDataDefinition) -> service.getForwardingPaths().put(key,forwardingPathDataDefinition)); + } + return Either.left(updatedContainerComponent); + } + + + private List<CapabilityDefinition> getAllInstanceCapabilities(ComponentInstance currentResourceInstance) { + return currentResourceInstance.getCapabilities().values().stream().flatMap(Collection::stream) + .collect(Collectors.toList()); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceHeatEnvMerge.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceHeatEnvMerge.java index 1561cdc797..3938281ad2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceHeatEnvMerge.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceHeatEnvMerge.java @@ -1,8 +1,6 @@ package org.openecomp.sdc.be.components.merge.instance; -import java.util.List; -import java.util.Map; - +import fj.data.Either; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic; import org.openecomp.sdc.be.components.merge.heat.HeatEnvArtifactsMergeBusinessLogic; import org.openecomp.sdc.be.impl.ComponentsUtils; @@ -17,7 +15,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import fj.data.Either; +import java.util.List; +import java.util.Map; /** * Created by chaya on 9/20/2017. @@ -25,7 +24,7 @@ import fj.data.Either; @org.springframework.stereotype.Component("ComponentInstanceHeatEnvMerge") public class ComponentInstanceHeatEnvMerge implements ComponentInstanceMergeInterface { - private static Logger log = LoggerFactory.getLogger(ComponentInstanceHeatEnvMerge.class.getName()); + private static final Logger log = LoggerFactory.getLogger(ComponentInstanceHeatEnvMerge.class); @Autowired private ArtifactsBusinessLogic artifactsBusinessLogic; @@ -52,7 +51,7 @@ public class ComponentInstanceHeatEnvMerge implements ComponentInstanceMergeInte Map<String, Object> json = artifactsBusinessLogic.buildJsonForUpdateArtifact(artifactInfo, ArtifactGroupTypeEnum.DEPLOYMENT, null); Either<Either<ArtifactDefinition, Operation>, ResponseFormat> uploadArtifactToService = artifactsBusinessLogic.updateResourceInstanceArtifactNoContent(newInstanceId, updatedContainerComponent, user, json, - artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactsBusinessLogic.ArtifactOperationEnum.Update), null); + artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE), null); if (uploadArtifactToService.isRight()) { log.error("Failed to update artifact {} on resourceInstance {}", artifactInfo.getArtifactLabel(), newInstanceId); return Either.right(uploadArtifactToService.right().value()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ComponentInstanceInputsMergeBL.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInputsMergeBL.java index 4e49eef94c..2e289456e6 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ComponentInstanceInputsMergeBL.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInputsMergeBL.java @@ -1,9 +1,7 @@ -package org.openecomp.sdc.be.components.merge.property; - -import java.util.Collections; -import java.util.List; -import java.util.Map; +package org.openecomp.sdc.be.components.merge.instance; +import fj.data.Either; +import org.openecomp.sdc.be.components.merge.property.DataDefinitionsValuesMergingBusinessLogic; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.model.Component; @@ -13,10 +11,12 @@ import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import fj.data.Either; +import java.util.Collections; +import java.util.List; +import java.util.Map; @org.springframework.stereotype.Component -public class ComponentInstanceInputsMergeBL { +public class ComponentInstanceInputsMergeBL implements ComponentsMergeCommand { @javax.annotation.Resource private ToscaOperationFacade toscaOperationFacade; @@ -27,13 +27,19 @@ public class ComponentInstanceInputsMergeBL { @javax.annotation.Resource private DataDefinitionsValuesMergingBusinessLogic propertyValuesMergingBusinessLogic; - public ActionStatus mergeComponentInstancesInputs(Component oldComponent, Component newComponent) { - Map<String, List<ComponentInstanceInput>> componentInstancesInputs = newComponent.getComponentInstancesInputs(); + @Override + public ActionStatus mergeComponents(Component prevComponent, Component currentComponent) { + Map<String, List<ComponentInstanceInput>> componentInstancesInputs = currentComponent.getComponentInstancesInputs(); if (componentInstancesInputs == null) { return ActionStatus.OK; } - componentInstancesInputs.forEach((instanceId, instInputs) -> mergeOldInstanceInputsValues(oldComponent, newComponent, instanceId, instInputs)); - return updateComponentInstancesInputs(newComponent, componentInstancesInputs); + componentInstancesInputs.forEach((instanceId, instInputs) -> mergeOldInstanceInputsValues(prevComponent, currentComponent, instanceId, instInputs)); + return updateComponentInstancesInputs(currentComponent, componentInstancesInputs); + } + + @Override + public String description() { + return "merge component instance inputs"; } public ActionStatus mergeComponentInstanceInputs(List<ComponentInstanceInput> oldInstProps, List<InputDefinition> oldInputs, Component newComponent, String instanceId) { @@ -68,5 +74,4 @@ public class ComponentInstanceInputsMergeBL { propertyValuesMergingBusinessLogic.mergeInstanceDataDefinitions(oldInstInputs, oldInputs, instInputs, newComponent.getInputs()); } - } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeDataBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeDataBusinessLogic.java index 04af6b7fc0..d17469a287 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeDataBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeDataBusinessLogic.java @@ -1,7 +1,6 @@ package org.openecomp.sdc.be.components.merge.instance; -import java.util.List; - +import fj.data.Either; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.model.Component; @@ -15,14 +14,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import fj.data.Either; +import java.util.List; /** * Created by chaya on 9/12/2017. */ @org.springframework.stereotype.Component("componentInstanceMergeDataBusinessLogic") public class ComponentInstanceMergeDataBusinessLogic { - private static Logger log = LoggerFactory.getLogger(ComponentInstanceMergeDataBusinessLogic.class.getName()); + private static final Logger log = LoggerFactory.getLogger(ComponentInstanceMergeDataBusinessLogic.class); @Autowired private List<ComponentInstanceMergeInterface> componentInstancesMergeBLs; @@ -60,7 +59,7 @@ public class ComponentInstanceMergeDataBusinessLogic { */ public Either<Component, ResponseFormat> mergeComponentUserOrigData(User user, DataForMergeHolder dataHolder, org.openecomp.sdc.be.model.Component containerComponent, String newContainerComponentId, String newInstanceId) { - Either<Component, StorageOperationStatus> componentWithInstancesInputsAndProperties = getComponentWithInstancesInputsAndProperties(newContainerComponentId); + Either<Component, StorageOperationStatus> componentWithInstancesInputsAndProperties = getComponentWithInstancesMergeEntities(newContainerComponentId); if (componentWithInstancesInputsAndProperties.isRight()) { log.error("Component with id {} was not found", newContainerComponentId); StorageOperationStatus storageOperationStatus = componentWithInstancesInputsAndProperties.right().value(); @@ -79,12 +78,15 @@ public class ComponentInstanceMergeDataBusinessLogic { return Either.left(updatedContainerComponent); } - private Either<Component, StorageOperationStatus> getComponentWithInstancesInputsAndProperties(String containerComponentId) { + private Either<Component, StorageOperationStatus> getComponentWithInstancesMergeEntities(String containerComponentId) { ComponentParametersView filter = new ComponentParametersView(true); filter.setIgnoreComponentInstances(false); filter.setIgnoreComponentInstancesInputs(false); filter.setIgnoreComponentInstancesProperties(false); + filter.setIgnoreCapabilities(false); + filter.setIgnoreCapabiltyProperties(false); filter.setIgnoreArtifacts(false); + filter.setIgnoreForwardingPath(false); return toscaOperationFacade.getToscaElement(containerComponentId, filter); } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeInterface.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeInterface.java index 1d2849b94c..f4bcfdab5c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeInterface.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeInterface.java @@ -1,12 +1,11 @@ package org.openecomp.sdc.be.components.merge.instance; +import fj.data.Either; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.exception.ResponseFormat; -import fj.data.Either; - /** * Created by chaya on 9/20/2017. */ diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ComponentInstancePropertiesMergeBL.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstancePropertiesMergeBL.java index 43e3ec624a..99b1d389ed 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ComponentInstancePropertiesMergeBL.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstancePropertiesMergeBL.java @@ -1,22 +1,21 @@ -package org.openecomp.sdc.be.components.merge.property; - -import java.util.Collections; -import java.util.List; -import java.util.Map; +package org.openecomp.sdc.be.components.merge.instance; +import fj.data.Either; +import org.openecomp.sdc.be.components.merge.property.DataDefinitionsValuesMergingBusinessLogic; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.InputDefinition; -import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import fj.data.Either; +import java.util.Collections; +import java.util.List; +import java.util.Map; @org.springframework.stereotype.Component -public class ComponentInstancePropertiesMergeBL { +public class ComponentInstancePropertiesMergeBL implements ComponentsMergeCommand { @javax.annotation.Resource private ToscaOperationFacade toscaOperationFacade; @@ -27,13 +26,19 @@ public class ComponentInstancePropertiesMergeBL { @javax.annotation.Resource private DataDefinitionsValuesMergingBusinessLogic propertyValuesMergingBusinessLogic; - public ActionStatus mergeComponentInstancesProperties(Component oldComponent, Resource newResource) { - Map<String, List<ComponentInstanceProperty>> newInstProps = newResource.getComponentInstancesProperties(); + @Override + public ActionStatus mergeComponents(Component prevComponent, Component currentComponent) { + Map<String, List<ComponentInstanceProperty>> newInstProps = currentComponent.getComponentInstancesProperties(); if (newInstProps == null) { return ActionStatus.OK; } - newInstProps.forEach((instanceId, newProps) -> mergeOldInstancePropertiesValues(oldComponent, newResource, instanceId, newProps) ); - return updateComponentInstancesProperties(newResource, newInstProps); + newInstProps.forEach((instanceId, newProps) -> mergeOldInstancePropertiesValues(prevComponent, currentComponent, instanceId, newProps) ); + return updateComponentInstancesProperties(currentComponent, newInstProps); + } + + @Override + public String description() { + return "merge component instance properties"; } @@ -68,6 +73,4 @@ public class ComponentInstancePropertiesMergeBL { return ActionStatus.OK; } - - } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstancePropsAndInputsMerge.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstancePropsAndInputsMerge.java index 765ddb57f6..b63cc38690 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstancePropsAndInputsMerge.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstancePropsAndInputsMerge.java @@ -1,20 +1,10 @@ package org.openecomp.sdc.be.components.merge.instance; -import java.util.ArrayList; -import java.util.List; - +import fj.data.Either; import org.openecomp.sdc.be.components.merge.input.ComponentInputsMergeBL; -import org.openecomp.sdc.be.components.merge.property.ComponentInstanceInputsMergeBL; -import org.openecomp.sdc.be.components.merge.property.ComponentInstancePropertiesMergeBL; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.impl.ComponentsUtils; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.ComponentParametersView; -import org.openecomp.sdc.be.model.InputDefinition; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.exception.ResponseFormat; @@ -22,7 +12,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import fj.data.Either; +import java.util.ArrayList; +import java.util.List; /** * Created by chaya on 9/20/2017. @@ -30,7 +21,7 @@ import fj.data.Either; @org.springframework.stereotype.Component("ComponentInstancePropsAndInputsMerge") public class ComponentInstancePropsAndInputsMerge implements ComponentInstanceMergeInterface { - private static Logger log = LoggerFactory.getLogger(ComponentInstancePropsAndInputsMerge.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ComponentInstancePropsAndInputsMerge.class); @Autowired private ToscaOperationFacade toscaOperationFacade; @@ -81,19 +72,19 @@ public class ComponentInstancePropsAndInputsMerge implements ComponentInstanceMe ActionStatus actionStatus = componentInstancePropertiesMergeBL.mergeComponentInstanceProperties(originComponentInstanceProps, originComponentsInputs, updatedComponent, instanceId); if (actionStatus != ActionStatus.OK) { - log.error("Failed to update component {} with merged instance properties", updatedComponent.getUniqueId(), newComponentInstancesProps); + LOGGER.error("Failed to update component {} with merged instance properties", updatedComponent.getUniqueId(), newComponentInstancesProps); return Either.right(actionStatus); } return Either.left(newComponentInstancesProps); } private Either<List<ComponentInstanceInput>, ActionStatus> mergeComponentInstanceInputsIntoContainer(DataForMergeHolder dataHolder, Component updatedComponent, String instanceId) { - List<ComponentInstanceInput> originComponentInstanceInputs = dataHolder.getOrigComponentInstanceInputs(); + List<ComponentInstanceInput> originComponentInstanceInputs = dataHolder.getOrigComponentInstanceInputs(); List<InputDefinition> originComponentsInputs = dataHolder.getOrigComponentInputs(); List<ComponentInstanceInput> newComponentInstancesInputs = updatedComponent.safeGetComponentInstanceInput(instanceId); ActionStatus actionStatus = resourceInstanceInputsMergeBL.mergeComponentInstanceInputs(originComponentInstanceInputs, originComponentsInputs, updatedComponent, instanceId); if (actionStatus != ActionStatus.OK) { - log.error("Failed to update component {} with merged instance properties", updatedComponent.getUniqueId(), newComponentInstancesInputs); + LOGGER.error("Failed to update component {} with merged instance properties", updatedComponent.getUniqueId(), newComponentInstancesInputs); return Either.right(actionStatus); } return Either.left(newComponentInstancesInputs); @@ -106,14 +97,14 @@ public class ComponentInstancePropsAndInputsMerge implements ComponentInstanceMe // get instance inputs and properties after merge Either<Component, StorageOperationStatus> componentWithInstancesInputsAndProperties = getComponentWithInstancesInputsAndProperties(newContainerComponentId); if (componentWithInstancesInputsAndProperties.isRight()) { - log.error("Component %s was not found", newContainerComponentId); + LOGGER.error("Component %s was not found", newContainerComponentId); return Either.right(componentsUtils.convertFromStorageResponse(componentWithInstancesInputsAndProperties.right().value())); } Component updatedContainerComponent = componentWithInstancesInputsAndProperties.left().value(); ActionStatus redeclareStatus = resourceInputsMergeBL.redeclareComponentInputsForInstance(origComponentInputs, updatedContainerComponent, newInstanceId); if (redeclareStatus != ActionStatus.OK) { - log.error("Failed to update component {} with merged inputs {}", newContainerComponentId, inputsToAddToContainer); + LOGGER.error("Failed to update component {} with merged inputs {}", newContainerComponentId, inputsToAddToContainer); Either.right(redeclareStatus); } } 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; + } + } + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentsMergeCommand.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentsMergeCommand.java new file mode 100644 index 0000000000..5dcb1dda79 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentsMergeCommand.java @@ -0,0 +1,22 @@ +package org.openecomp.sdc.be.components.merge.instance; + +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.model.Component; + +public interface ComponentsMergeCommand { + + /** + * encapsulates the logic of merging component inner entities from the previous component into the currently updated component + * @param prevComponent the old component, whose entities need to be merged + * @param currentComponent the new component, whose entities need to be merged + * @return the status of the merge process + */ + ActionStatus mergeComponents(Component prevComponent, Component currentComponent); + + /** + * + * @return short description of the command for logging purposes + */ + String description(); + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/DataForMergeHolder.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/DataForMergeHolder.java index c5fb1d4a86..ac0959897d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/DataForMergeHolder.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/DataForMergeHolder.java @@ -6,8 +6,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; - import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.InputDefinition; @@ -23,6 +24,10 @@ public class DataForMergeHolder { private Map<String, ArtifactDefinition> origCompInstDeploymentArtifactsCreatedOnTheInstance; private Map<String, ArtifactDefinition> origCompInstInformationalArtifactsCreatedOnTheInstance; private List<ArtifactDefinition> origComponentInstanceHeatEnvArtifacts; + private VfRelationsMergeInfo vfRelationsMergeInfo; + private List<CapabilityDefinition> origInstanceCapabilities; + private Component origInstanceNode; + private String origComponentInstId; public DataForMergeHolder() { origComponentInstanceInputs = new ArrayList<>(); @@ -30,7 +35,7 @@ public class DataForMergeHolder { origComponentInputs = new ArrayList<>(); origCompInstDeploymentArtifactsCreatedOnTheInstance = new HashMap<>(); origCompInstDeploymentArtifactsCreatedOnTheInstance = new HashMap<>(); - + origInstanceCapabilities = new ArrayList<>(); } public List<ArtifactDefinition> getOrigComponentInstanceHeatEnvArtifacts() { @@ -109,6 +114,35 @@ public class DataForMergeHolder { origCompInstInformationalArtifactsCreatedOnTheInstance = origInformationalArtifacts; } + public void setVfRelationsInfo(VfRelationsMergeInfo vfRelationsMergeInfo) { + this.vfRelationsMergeInfo = vfRelationsMergeInfo; + } + + public VfRelationsMergeInfo getVfRelationsMergeInfo() { + return vfRelationsMergeInfo; + } + + public List<CapabilityDefinition> getOrigInstanceCapabilities() { + return origInstanceCapabilities; + } + public void setOrigInstanceCapabilities(List<CapabilityDefinition> origInstanceCapabilities) { + this.origInstanceCapabilities = origInstanceCapabilities; + } + public Component getOrigInstanceNode() { + return origInstanceNode; + } + + public void setOrigInstanceNode(Component origInstanceNode) { + this.origInstanceNode = origInstanceNode; + } + + public String getOrigComponentInstId() { + return origComponentInstId; + } + + public void setOrigComponentInstId(String origComponentInstId) { + this.origComponentInstId = origComponentInstId; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/RelationMergeInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/RelationMergeInfo.java new file mode 100644 index 0000000000..4ab802ad35 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/RelationMergeInfo.java @@ -0,0 +1,49 @@ +package org.openecomp.sdc.be.components.merge.instance; + +import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; + +public class RelationMergeInfo { + private String capReqType; + private String vfcInstanceName; + private RequirementCapabilityRelDef relDef; + private String capReqName; + + public RelationMergeInfo(String capReqType, String capReqName, String vfcInstanceName, RequirementCapabilityRelDef relDef) { + this.capReqType = capReqType; + this.capReqName = capReqName; + this.vfcInstanceName = vfcInstanceName; + this.relDef = relDef; + } + + public String getCapReqType() { + return capReqType; + } + + public void setCapReqType(String type) { + this.capReqType = type; + } + + public String getVfcInstanceName() { + return vfcInstanceName; + } + + public void setVfcInstanceName(String vfcInstanceName) { + this.vfcInstanceName = vfcInstanceName; + } + + public RequirementCapabilityRelDef getRelDef() { + return relDef; + } + + public void setRelDef(RequirementCapabilityRelDef relDef) { + this.relDef = relDef; + } + + public String getCapReqName() { + return capReqName; + } + + public void setCapReqName(String capReqName) { + this.capReqName = capReqName; + } +}
\ No newline at end of file diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/VfRelationsMergeInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/VfRelationsMergeInfo.java new file mode 100644 index 0000000000..e116b66408 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/VfRelationsMergeInfo.java @@ -0,0 +1,30 @@ +package org.openecomp.sdc.be.components.merge.instance; + +import java.util.List; + +public class VfRelationsMergeInfo { + private List<RelationMergeInfo> fromRelationsInfo; + private List<RelationMergeInfo> toRelationsInfo; + + public VfRelationsMergeInfo(List<RelationMergeInfo> fromRelationsInfo, List<RelationMergeInfo> toRelationsInfo) { + this.fromRelationsInfo = fromRelationsInfo; + this.toRelationsInfo = toRelationsInfo; + } + + public List<RelationMergeInfo> getFromRelationsInfo() { + return fromRelationsInfo; + } + + public void setFromRelationsInfo(List<RelationMergeInfo> fromRelationsInfo) { + this.fromRelationsInfo = fromRelationsInfo; + } + + public List<RelationMergeInfo> getToRelationsInfo() { + return toRelationsInfo; + } + + public void setToRelationsInfo(List<RelationMergeInfo> toRelationsInfo) { + this.toRelationsInfo = toRelationsInfo; + } + +}
\ No newline at end of file diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/DataDefinitionsValuesMergingBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/DataDefinitionsValuesMergingBusinessLogic.java index 96d3bce97e..139ac386a1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/DataDefinitionsValuesMergingBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/DataDefinitionsValuesMergingBusinessLogic.java @@ -1,11 +1,12 @@ package org.openecomp.sdc.be.components.merge.property; -import java.util.List; - import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.model.InputDefinition; import org.springframework.stereotype.Component; +import java.util.Collections; +import java.util.List; + @Component public class DataDefinitionsValuesMergingBusinessLogic { @@ -30,6 +31,11 @@ public class DataDefinitionsValuesMergingBusinessLogic { } + public <T extends PropertyDataDefinition> void mergeInstanceDataDefinitions(List<T> oldInstanceDataDefinition, List<T> updatedInstanceDataDefinition) { + List<InputDefinition> emptyInputsList = Collections.emptyList(); + mergeInstanceDataDefinitions(oldInstanceDataDefinition, emptyInputsList, updatedInstanceDataDefinition, emptyInputsList); + } + private void mergeInstanceDefinition(MergePropertyData mergeData) { if (isSameType(mergeData.getOldProp(), mergeData.getNewProp())) { propertyValueMergeBL.mergePropertyValue(mergeData.getOldProp(), mergeData.getNewProp(), mergeData.getGetInputNamesToMerge()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/MergePropertyData.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/MergePropertyData.java index 63a7a1b3a0..df65c1161f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/MergePropertyData.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/MergePropertyData.java @@ -1,10 +1,10 @@ package org.openecomp.sdc.be.components.merge.property; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; + import java.util.ArrayList; import java.util.List; -import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; - /** * A POJO which represents an instance property data definition (a {@link org.openecomp.sdc.be.model.ComponentInstanceProperty} or {@link org.openecomp.sdc.be.model.ComponentInstanceInput}) * that its value needs to be merged during an upgrade of a VSP. diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyDataValueMergeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyDataValueMergeBusinessLogic.java index 6b083596c7..318840d60a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyDataValueMergeBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyDataValueMergeBusinessLogic.java @@ -1,15 +1,7 @@ package org.openecomp.sdc.be.components.merge.property; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -import javax.annotation.Resource; - -import org.openecomp.sdc.be.components.impl.ImportUtils; +import com.google.gson.Gson; +import fj.data.Either; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; @@ -22,9 +14,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; -import com.google.gson.Gson; - -import fj.data.Either; +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; @Component public class PropertyDataValueMergeBusinessLogic { @@ -88,39 +80,6 @@ public class PropertyDataValueMergeBusinessLogic { return propertyConvertor.convertToToscaObject(propertyType, propValue, innerType, dataTypes); } - - @SuppressWarnings("unchecked") - private Object removeUnwantedGetInputValues(Object val, List<String> getInputNamesToMerge) { - if (val instanceof Map) { - return removeUnwantedGetInputValues((Map<String, Object>) val, getInputNamesToMerge); - } - if (val instanceof List) { - return removeUnwantedGetInputValues((List<Object>)val, getInputNamesToMerge); - } - return val; - } - - private List<Object> removeUnwantedGetInputValues(List<Object> listVal, List<String> getInputNamesToMerge) { - return listVal.stream().map(val -> removeUnwantedGetInputValues(val, getInputNamesToMerge)).collect(Collectors.toList()); - } - - private Map<String, Object> removeUnwantedGetInputValues(Map<String, Object> val, List<String> getInputNamesToMerge) { - return val.entrySet().stream().filter(entry -> !isGetInputEntry(entry) || isGetInputToMerge(getInputNamesToMerge, entry)) - .collect(Collectors.toMap(Map.Entry::getKey, entry -> removeUnwantedGetInputValues(entry.getValue(), getInputNamesToMerge))); - } - - private boolean isGetInputToMerge(List<String> getInputNamesToMerge, Map.Entry<String, Object> entry) { - return getInputNamesToMerge.contains(retrieveGetInputInputName(entry.getValue())); - } - - private String retrieveGetInputInputName(Object getInputValue) { - return getInputValue instanceof List ? (String)((List) getInputValue).get(0) : (String)getInputValue; - } - - private boolean isGetInputEntry(Map.Entry<String, Object> oldValEntry) { - return oldValEntry.getKey().equals(ImportUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); - } - private boolean isEmptyValue(Object val) { return val == null || val instanceof Map && ((Map) val).isEmpty() || diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyInstanceMergeDataBuilder.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyInstanceMergeDataBuilder.java index 09f26a39ee..df3030567d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyInstanceMergeDataBuilder.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyInstanceMergeDataBuilder.java @@ -1,15 +1,15 @@ package org.openecomp.sdc.be.components.merge.property; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.model.InputDefinition; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + public class PropertyInstanceMergeDataBuilder { private final static PropertyInstanceMergeDataBuilder INSTANCE = new PropertyInstanceMergeDataBuilder(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyValueMerger.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyValueMerger.java index 88601bb521..9fcb864fe9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyValueMerger.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyValueMerger.java @@ -1,13 +1,13 @@ package org.openecomp.sdc.be.components.merge.property; +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdc.be.components.impl.ImportUtils; + import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.apache.commons.lang.StringUtils; -import org.openecomp.sdc.be.components.impl.ImportUtils; - public abstract class PropertyValueMerger { abstract Object merge(Object oldVal, Object newVal, List<String> someStrings); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ScalarPropertyValueMerger.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ScalarPropertyValueMerger.java index 39381e7322..ce0ed0eed2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ScalarPropertyValueMerger.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/ScalarPropertyValueMerger.java @@ -1,9 +1,9 @@ package org.openecomp.sdc.be.components.merge.property; -import java.util.List; - import org.springframework.stereotype.Component; +import java.util.List; + @Component("scalar-prop-value-merger") public class ScalarPropertyValueMerger extends PropertyValueMerger { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/MergeResourceBLFactory.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/MergeResourceBLFactory.java index 9d11eb9aaf..cdfeded356 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/MergeResourceBLFactory.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/MergeResourceBLFactory.java @@ -1,14 +1,13 @@ package org.openecomp.sdc.be.components.merge.resource; +import fj.data.Either; import org.openecomp.sdc.be.components.merge.GlobalTypesMergeBusinessLogic; import org.openecomp.sdc.be.components.merge.TopologyComparator; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.model.Resource; import org.springframework.stereotype.Component; -import fj.data.Either; - @Component public class MergeResourceBLFactory { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/ResourceDataMergeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/ResourceDataMergeBusinessLogic.java index 251fb1a64e..0ffe693187 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/ResourceDataMergeBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/resource/ResourceDataMergeBusinessLogic.java @@ -1,62 +1,38 @@ package org.openecomp.sdc.be.components.merge.resource; -import java.util.ArrayList; -import java.util.List; - -import org.openecomp.sdc.be.components.merge.input.ComponentInputsMergeBL; -import org.openecomp.sdc.be.components.merge.property.ComponentInstanceInputsMergeBL; -import org.openecomp.sdc.be.components.merge.property.ComponentInstancePropertiesMergeBL; +import org.openecomp.sdc.be.components.merge.instance.ComponentsMergeCommand; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; +import java.util.List; + @Component public class ResourceDataMergeBusinessLogic implements MergeResourceBusinessLogic { - private final static Logger log = LoggerFactory.getLogger(ResourceDataMergeBusinessLogic.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ResourceDataMergeBusinessLogic.class); - @javax.annotation.Resource - private ComponentInputsMergeBL inputsValuesMergeBL; + private List<ComponentsMergeCommand> componentMergingCommands; - @javax.annotation.Resource - private ComponentInstancePropertiesMergeBL instancePropertiesValueMergeBL; - - @javax.annotation.Resource - private ComponentInstanceInputsMergeBL instanceInputsValueMergeBL; + public ResourceDataMergeBusinessLogic(List<ComponentsMergeCommand> componentMergingCommands) { + this.componentMergingCommands = componentMergingCommands; + } @Override public ActionStatus mergeResourceEntities(Resource oldResource, Resource newResource) { if (oldResource == null) { return ActionStatus.OK; } - - ActionStatus mergeInstInputsStatus = instancePropertiesValueMergeBL.mergeComponentInstancesProperties(oldResource, newResource); - if (mergeInstInputsStatus != ActionStatus.OK) { - log.error("failed to merge instance properties of resource {} status is {}", newResource.getUniqueId(), mergeInstInputsStatus); - return mergeInstInputsStatus; - } - - ActionStatus mergeInstPropsStatus = instanceInputsValueMergeBL.mergeComponentInstancesInputs(oldResource, newResource); - if (mergeInstPropsStatus != ActionStatus.OK) { - log.error("failed to merge instance inputs of resource {} status is {}", newResource.getUniqueId(), mergeInstPropsStatus); - return mergeInstPropsStatus; - } - - ActionStatus mergeInputsStatus = mergeInputs(oldResource, newResource); - if (mergeInputsStatus != ActionStatus.OK) { - log.error("failed to merge inputs of resource {} status is {}", newResource.getUniqueId(), mergeInputsStatus); - return mergeInputsStatus; + for (ComponentsMergeCommand componentMergeCommand : componentMergingCommands) { + ActionStatus mergeStatus = componentMergeCommand.mergeComponents(oldResource, newResource); + if (mergeStatus != ActionStatus.OK) { + LOGGER.error("failed on merge command {} of resource {} status is {}", componentMergeCommand.description(), newResource.getUniqueId(), mergeStatus); + return mergeStatus; + } } return ActionStatus.OK; } - private ActionStatus mergeInputs(Resource oldResource, Resource newResource) { - List<InputDefinition> inputsToMerge = newResource.getInputs() != null ? newResource.getInputs() : new ArrayList<>(); - return inputsValuesMergeBL.mergeAndRedeclareComponentInputs(oldResource, newResource, inputsToMerge); - } - - } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java new file mode 100644 index 0000000000..4ff7e06db5 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java @@ -0,0 +1,257 @@ +package org.openecomp.sdc.be.components.merge.utils; + +import fj.data.Either; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.annotations.VisibleForTesting; +import java.util.*; +import java.util.stream.Collectors; + +import static java.util.function.Function.identity; + +/** + * This class is Utils class but it should be bean + * @author dr2032 + * + */ +@org.springframework.stereotype.Component("MergeInstanceUtils") +public class MergeInstanceUtils { + private Logger log = LoggerFactory.getLogger(MergeInstanceUtils.class); + + @Autowired + private ToscaOperationFacade toscaOperationFacade; + + /** + * Maps capability owner IDs of old component instance to capability owner IDs of the new component instance + * @param container containing new component instance + * @param origInstanceNode old component (in case of PROXY it should be actual service) + * @param newInstanceId - ID of new instance of the component + * @param oldCapabilitiesOwnerIds + * @return + */ + public Map<String, String> mapOldToNewCapabilitiesOwnerIds(Component container, + Component origInstanceNode, + String newInstanceId, + List<String> oldCapabilitiesOwnerIds) { + + Map<String, String> resultMap; + + if (ModelConverter.isAtomicComponent(origInstanceNode) || isCVFC(origInstanceNode)) { + resultMap = prepareMapForAtomicComponent(newInstanceId, oldCapabilitiesOwnerIds); + } + else { + resultMap = prepareMapForNonAtomicComponent(container, origInstanceNode, newInstanceId, oldCapabilitiesOwnerIds); + } + + return resultMap; + } + + + private static boolean isCVFC(Component component) { + ComponentTypeEnum componentType = component.getComponentType(); + if (!componentType.equals(ComponentTypeEnum.RESOURCE)) { + return false; + } + + Resource resource = (Resource) component; + ResourceTypeEnum resourceType = resource.getResourceType(); + return resourceType == ResourceTypeEnum.CVFC; + } + + + /** + * Maps capability owner IDs of old component instance to capability owner IDs of the new component instance + * @param oldInstance + * @param newInstance + * @return + */ + public Map<String, String> mapOldToNewCapabilitiesOwnerIds(ComponentInstance oldInstance, ComponentInstance newInstance) { + List<ComponentInstance> oldVfcInstances = getVfcInstances(oldInstance); + List<ComponentInstance> newVfcInstances = getVfcInstances(newInstance); + + Map<String, ComponentInstance> newVfciNameMap = convertToVfciNameMap(newVfcInstances); + + return oldVfcInstances.stream() + .filter(oldVfci -> newVfciNameMap.containsKey(oldVfci.getName())) + .collect(Collectors.toMap(ComponentInstance::getUniqueId, oldVfci -> newVfciNameMap.get(oldVfci.getName()).getUniqueId())); + } + + + /** + * Method converts list of Component Instances to map of the instances where the key is their name + * @param componentInstances + * @return + */ + public Map<String, ComponentInstance> convertToVfciNameMap(List<ComponentInstance> componentInstances) { + return componentInstances != null ? + componentInstances.stream() + .collect(Collectors.toMap(ComponentInstance::getName, identity())): Collections.emptyMap(); + } + + + + /** + * Returns List of componentInstances by specified componentInstance + * If componentInstance is for atomic component the returned list will contain the specified componentInstance only. + * @param componentInstance + * @return + */ + public List<ComponentInstance> getVfcInstances(ComponentInstance componentInstance) { + if (componentInstance == null) { + return Collections.emptyList(); + } + + + List<ComponentInstance> vfcInstances; + + String componentId = componentInstance.getActualComponentUid(); + Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(componentId); + + if(eitherComponent.isLeft()) { + Component component = eitherComponent.left().value(); + vfcInstances = getVfcInstances(componentInstance, component); + } + else { + log.debug("Unexpected error: resource was not loaded for VF ID: {}", componentId); + vfcInstances = Collections.emptyList(); + } + + return vfcInstances; + } + + + /** + * Returns List of componentInstances by specified componentInstance and component + * If componentInstance is for atomic component the returned list will contain the specified componentInstance only. + * @param componentInstance + * @param eitherComponent + * @return + */ + public List<ComponentInstance> getVfcInstances(ComponentInstance componentInstance, Component component) { + if (componentInstance == null || component == null) { + return Collections.emptyList(); + } + + + List<ComponentInstance> vfcInstances; + + if (ModelConverter.isAtomicComponent(component) || isCVFC(component)) { + if (componentInstance.getIsProxy()) { + // Component is proxy and it doesn't contain required data + vfcInstances = getVfcInstances(componentInstance); + } + else { + vfcInstances = Arrays.asList(componentInstance); + } + } + else { + vfcInstances = recursiveScanForAtomicComponentInstances(component); + } + + return vfcInstances; + } + + + @VisibleForTesting + public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) { + this.toscaOperationFacade = toscaOperationFacade; + } + + + + /** + * @param component + * @return + */ + private List<ComponentInstance> recursiveScanForAtomicComponentInstances(Component component) { + List<ComponentInstance> vfcInstances; + + List<ComponentInstance> componentInstances = component.getComponentInstances(); + if (componentInstances != null) { + // Go recursively to collect atomic components only + vfcInstances = componentInstances.stream() + .map(this::getVfcInstances) + .flatMap(List::stream) + .collect(Collectors.toList()); + } + else { + vfcInstances = Collections.emptyList(); + } + + return vfcInstances; + } + + + + /** + * @param newInstanceId + * @param oldCapabilitiesOwnerIds + * @return + */ + private Map<String, String> prepareMapForAtomicComponent(String newInstanceId, List<String> oldCapabilitiesOwnerIds) { + Map<String, String> resultMap; + + int oldCapabilityOwnerIdsSize = oldCapabilitiesOwnerIds.size(); + if (oldCapabilityOwnerIdsSize == 1) { + resultMap = new HashMap<>(); + resultMap.put(oldCapabilitiesOwnerIds.get(0), newInstanceId); + } + else { + log.debug("For automic component the list of old capabilities owner Ids should contains one element while actual size is {},", oldCapabilityOwnerIdsSize); + resultMap = Collections.emptyMap(); + } + + return resultMap; + } + + /** + * @param container + * @param origInstanceNode + * @param newInstanceId + * @param oldCapabilitiesOwnerIds + * @return + */ + private Map<String, String> prepareMapForNonAtomicComponent(Component container, Component origInstanceNode, + String newInstanceId, List<String> oldCapabilitiesOwnerIds) { + Map<String, String> resultMap; + List<ComponentInstance> oldVfcInstances = recursiveScanForAtomicComponentInstances(origInstanceNode); + + ComponentInstance newInstance = container.getComponentInstanceById(newInstanceId).orElse(null); + if (newInstance == null) { + log.debug("Failed to get component instance by newInstanceId: {}.", newInstanceId); + resultMap = Collections.emptyMap(); + } + else { + resultMap = mapOldVfcIdsToNewOnes(oldCapabilitiesOwnerIds, oldVfcInstances, newInstance); + } + return resultMap; + } + + /** + * @param oldCapabilitiesOwnerIds + * @param oldVfcInstances + * @param newInstance + * @return + */ + private Map<String, String> mapOldVfcIdsToNewOnes(List<String> oldCapabilitiesOwnerIds, + List<ComponentInstance> oldVfcInstances, ComponentInstance newInstance) { + List<ComponentInstance> newVfcInstances = getVfcInstances(newInstance); + Map<String, ComponentInstance> newVfciNameMap = convertToVfciNameMap(newVfcInstances); + + return oldVfcInstances.stream() + .filter(oldVfc -> oldCapabilitiesOwnerIds.contains(oldVfc.getUniqueId())) + .filter(oldVfci -> newVfciNameMap.containsKey(oldVfci.getName())) + .collect(Collectors.toMap(ComponentInstance::getUniqueId, oldVfci -> newVfciNameMap.get(oldVfci.getName()).getUniqueId())); + } + +} |