Skip to content

Commit

Permalink
eclipse-capella#2062 Port delegations are kept when DnDing port to an…
Browse files Browse the repository at this point in the history
…y of target's ancerstors
  • Loading branch information
ebausson-obeo committed Aug 25, 2023
1 parent 753d3d4 commit d876113
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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<AbstractFunction> functions) {
Collection<AbstractFunction> functions, NamedElement newContainer) {
Collection<FunctionalExchange> 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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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<EObject> 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.
*
Expand All @@ -3030,7 +3038,14 @@ public EObject dndABDeployment(NamedElement pcMoved, NamedElement oldContainer,
EObject removeUselessPortRealizations(Port port, boolean includeFunctionalRealization,
boolean includeComponentRealization, boolean topDelegation, boolean bottomDelegation) {
Collection<EObject> elements = new HashSet<>();
elements.addAll(retrievePortDelegations(port, topDelegation, bottomDelegation));
elements.addAll(retrievePortAllocations(port, includeFunctionalRealization, includeComponentRealization));
CapellaServices.getService().removeElements(elements);
return port;
}

private Collection<EObject> retrievePortDelegations(Port port, boolean topDelegation, boolean bottomDelegation) {
Collection<EObject> delegations = new HashSet<>();
if (port instanceof ComponentPort) {
// Retrieve delegation to delete, according to parameters
for (ComponentExchange exchange : PortExt.getDelegationComponentExchanges((ComponentPort) port)) {
Expand All @@ -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<Allocation> retrieveObsoletePortAllocations(Port movingPort, NamedElement newContainer, boolean includeFunctionalRealization,
boolean includeComponentRealization, boolean topDelegation, boolean bottomDelegation) {
Collection<Allocation> elements = new HashSet<Allocation>();
Collection<Allocation> 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<Allocation> retrievePortAllocations(Port port, boolean includeFunctionalRealization, boolean includeComponentRealization) {
Collection<Allocation> elements = new HashSet<>();

Collection<Allocation> allocations = new HashSet<>();
allocations.addAll(port.getIncomingPortAllocations());
Expand All @@ -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;
}

/**
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit d876113

Please sign in to comment.