From 410ce2713100ff2f9d183015cfca84ef7b33f849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Bausson?= Date: Mon, 10 Jul 2023 16:28:01 +0200 Subject: [PATCH] #2062 Port delegations are kept when DnDing port to any of target's ancerstors --- .../core/sirius/analysis/ABServices.java | 2 +- .../core/sirius/analysis/FaServices.java | 123 +++++++++++++----- 2 files changed, 95 insertions(+), 30 deletions(-) diff --git a/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/ABServices.java b/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/ABServices.java index 34fbebe370..17ab560787 100644 --- a/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/ABServices.java +++ b/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/ABServices.java @@ -319,7 +319,7 @@ private EObject _dndABComponent(NamedElement pcMoved, EObject newOwner, NamedEle // Remove all port outgoing allocations for (Port port : ComponentExt.getOwnedComponentPort(component)) { - FaServices.getFaServices().removeUselessPortRealizations(port, false, true, false, false); + FaServices.getFaServices().removeUselessPortAllocations(port, newContainer, false, true, false, false); } FaServices.getFaServices().removeUselessExchanges(component); diff --git a/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/FaServices.java b/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/FaServices.java index 64574c7dab..4f5f50456d 100644 --- a/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/FaServices.java +++ b/core/plugins/org.polarsys.capella.core.sirius.analysis/src/org/polarsys/capella/core/sirius/analysis/FaServices.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2020 THALES GLOBAL SERVICES. + * Copyright (c) 2006, 2023 THALES GLOBAL SERVICES. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -16,7 +16,6 @@ import java.util.AbstractMap; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -2367,19 +2366,19 @@ else if ((oldComponent != null) && (newContainer instanceof Role)) { // outGoing functiaonalExchages(component // Exchange Allocation) if (!oldContainer.equals(newComponent)) { - removeUseLessPortRealizationAndComponentExchangeAllocation(function, functions); + removeUseLessPortRealizationAndComponentExchangeAllocation(function, functions, newContainer); } return function; } private void removeUseLessPortRealizationAndComponentExchangeAllocation(AbstractFunction function, - Collection functions) { + Collection functions, NamedElement newContainer) { Collection functionalExchanges = new HashSet<>(); for (AbstractFunction fct : functions) { // Find all PortRealization and component exchanges to be deleted for (Port port : FunctionExt.getOwnedFunctionPorts(fct)) { - removeUselessPortRealizations(port, true, true, false, false); + removeUselessPortAllocations(port, newContainer, true, true, false, false); } } // consider incoming and outgoing functionalExchanges of target function @@ -2985,7 +2984,7 @@ public EObject dndABDeployment(NamedElement pcMoved, NamedElement oldContainer, // Remove all port outgoing allocations for (Port port : ComponentExt.getOwnedComponentPort(component)) { - removeUselessPortRealizations(port, false, true, false, false); + removeUselessPortAllocations(port, newContainer, false, true, false, false); } // move all deploying links @@ -3006,7 +3005,7 @@ public EObject dndABDeployment(NamedElement pcMoved, NamedElement oldContainer, // Remove all port outgoing allocations for (Port port : ComponentExt.getOwnedComponentPort(component)) { - removeUselessPortRealizations(port, false, true, false, false); + removeUselessPortAllocations(port, newContainer, false, true, false, false); } // move all deploying links @@ -3022,6 +3021,15 @@ public EObject dndABDeployment(NamedElement pcMoved, NamedElement oldContainer, return pcMoved; } + EObject removeUselessPortAllocations(Port port, NamedElement newContainer, boolean includeFunctionalRealization, boolean includeComponentRealization, + boolean topDelegation, boolean bottomDelegation) { + Collection elements = new HashSet<>(); + elements.addAll(retrievePortDelegations(port, topDelegation, bottomDelegation)); + elements.addAll(retrieveObsoletePortAllocations(port, newContainer, includeFunctionalRealization, includeComponentRealization, bottomDelegation, bottomDelegation)); + CapellaServices.getService().removeElements(elements); + return port; + } + /** * Perform a dnd of a port. * @@ -3030,7 +3038,14 @@ public EObject dndABDeployment(NamedElement pcMoved, NamedElement oldContainer, EObject removeUselessPortRealizations(Port port, boolean includeFunctionalRealization, boolean includeComponentRealization, boolean topDelegation, boolean bottomDelegation) { Collection elements = new HashSet<>(); + elements.addAll(retrievePortDelegations(port, topDelegation, bottomDelegation)); + elements.addAll(retrievePortAllocations(port, includeFunctionalRealization, includeComponentRealization)); + CapellaServices.getService().removeElements(elements); + return port; + } + private Collection retrievePortDelegations(Port port, boolean topDelegation, boolean bottomDelegation) { + Collection delegations = new HashSet<>(); if (port instanceof ComponentPort) { // Retrieve delegation to delete, according to parameters for (ComponentExchange exchange : PortExt.getDelegationComponentExchanges((ComponentPort) port)) { @@ -3046,13 +3061,69 @@ EObject removeUselessPortRealizations(Port port, boolean includeFunctionalRealiz } if (topDelegation && CsServices.getService().getContainersOfParts(containingPort).contains(delegatedPort)) { - elements.add(exchange); - } else if (bottomDelegation - && CsServices.getService().getContainersOfParts(delegatedPort).contains(containingPort)) { - elements.add(exchange); + delegations.add(exchange); + } else if (bottomDelegation && CsServices.getService().getContainersOfParts(delegatedPort).contains(containingPort)) { + delegations.add(exchange); } } } + return delegations; + } + + /** + * This method retrieve all the port's allocations and return those that should be deleted (as they do not make sense + * for the new element) + * + * @param movingPort + * the port that is being D&Ded + * @param newContainer + * the container the port was just Dropped on. + * @param includeFunctionalRealization + * @param includeComponentRealization + * @param topDelegation + * @param bottomDelegation + * @return + */ + private Collection retrieveObsoletePortAllocations(Port movingPort, NamedElement newContainer, boolean includeFunctionalRealization, + boolean includeComponentRealization, boolean topDelegation, boolean bottomDelegation) { + Collection elements = new HashSet(); + Collection allocations = retrievePortAllocations(movingPort, includeFunctionalRealization, includeComponentRealization); + Component instanciatedComponent = null; + if (newContainer instanceof Part) { + instanciatedComponent = PartExt.getComponentOfPart((Part) newContainer); + } + for (Allocation allocation : allocations) { + Port delegatedPort = (allocation.getSourceElement() == movingPort) ? (Port) allocation.getTargetElement() : (Port) allocation.getSourceElement(); + if (instanciatedComponent == null || !isEObjectInHierarchyOfContainer(delegatedPort.eContainer(), instanciatedComponent)) { + elements.add(allocation); + } + } + return elements; + } + + /** + * Test two objects to determine if the first one is a subElement of the other. Should eObject be an AbstractFunction, + * the test will be done on each of its FunctionalAllocation instead. + * + * @param eObject + * @param container + * @return + */ + private boolean isEObjectInHierarchyOfContainer(EObject eObject, NamedElement container) { + if (eObject == container) { + return true; + } else if (eObject instanceof AbstractFunction) { + if (((AbstractFunction) eObject).getComponentFunctionalAllocations().stream().anyMatch(cfa -> isEObjectInHierarchyOfContainer(cfa, container))) { + return true; + } + } else if (eObject instanceof ModelElement && eObject.eContainer() != null) { + return isEObjectInHierarchyOfContainer(eObject.eContainer(), container); + } + return false; + } + + private Collection retrievePortAllocations(Port port, boolean includeFunctionalRealization, boolean includeComponentRealization) { + Collection elements = new HashSet<>(); Collection allocations = new HashSet<>(); allocations.addAll(port.getIncomingPortAllocations()); @@ -3063,27 +3134,21 @@ EObject removeUselessPortRealizations(Port port, boolean includeFunctionalRealiz // Retrieve port allocation according to parameters for (Allocation realization : allocations) { if (isValidAllocation(realization)) { - if ((realization.getSourceElement() != null) && (realization.getTargetElement() != null)) { - if (includeFunctionalRealization && (realization.getTargetElement() instanceof FunctionPort)) { - elements.add(realization); - } + if (includeFunctionalRealization && (realization.getTargetElement() instanceof FunctionPort)) { + elements.add(realization); + } - if ((port instanceof FunctionPort) && includeComponentRealization - && (realization.getSourceElement() instanceof FunctionPort)) { - elements.add(realization); - } + if ((port instanceof FunctionPort) && includeComponentRealization && (realization.getSourceElement() instanceof FunctionPort)) { + elements.add(realization); + } - if (includeComponentRealization && ((realization.getTargetElement() instanceof ComponentPort) - || (realization.getTargetElement() instanceof PhysicalPort))) { - elements.add(realization); - } + if (includeComponentRealization && ((realization.getTargetElement() instanceof ComponentPort) || (realization.getTargetElement() instanceof PhysicalPort))) { + elements.add(realization); } } } - - CapellaServices.getService().removeElements(elements); - return port; + return elements; } /** @@ -3095,7 +3160,7 @@ EObject removeUselessPortRealizations(Port port, boolean includeFunctionalRealiz */ public EObject dndABFunctionPort(FunctionPort port, NamedElement oldContainer, NamedElement newContainer) { - removeUselessPortRealizations(port, true, true, false, false); + removeUselessPortAllocations(port, newContainer, true, true, false, false); // move the port in the new function container if (newContainer instanceof AbstractFunction) { @@ -3139,7 +3204,7 @@ public EObject dndABPhysicalPort(PhysicalPort port, Part oldContainer, Part newC if (!port.eContainer().equals(newContainer.getType())) { removeUselessExchanges(port); - removeUselessPortRealizations(port, true, true, false, false); + removeUselessPortAllocations(port, newContainer, true, true, false, false); ((Component) newContainer.getType()).getOwnedFeatures().add(port); updateExchanges(port, oldContainer, newContainer); @@ -3163,7 +3228,7 @@ public EObject dndABComponentPort(ComponentPort port, Part oldContainer, Part ne if (!port.eContainer().equals(newContainer.getType())) { removeUselessExchanges(port); - removeUselessPortRealizations(port, true, true, false, false); + removeUselessPortAllocations(port, newContainer, true, true, false, false); ((Component) newContainer.getType()).getOwnedFeatures().add(port); updateComponentExchanges(port, oldContainer, newContainer);