Skip to content

Commit

Permalink
EDITORS-294 Allow selecting inherited signatures in calls.
Browse files Browse the repository at this point in the history
  • Loading branch information
seiferma committed Dec 7, 2021
1 parent b26b127 commit 32af3fc
Show file tree
Hide file tree
Showing 17 changed files with 632 additions and 80 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**/bin/
**/*.class
target/
xtend-gen/
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.palladiosimulator.editors.sirius.custom.util;

import java.util.ArrayDeque;
import java.util.Collection;
import java.util.HashSet;
import java.util.Queue;

import org.palladiosimulator.pcm.repository.OperationInterface;

public final class PCMQueryUtils {

private PCMQueryUtils() {
// intentionally empty
}

public static Collection<OperationInterface> getTransitiveParentInterfaceClosureIncludingSelf(
OperationInterface self) {
Collection<OperationInterface> closure = new HashSet<>();
Queue<OperationInterface> queue = new ArrayDeque<>();
queue.add(self);
while (!queue.isEmpty()) {
OperationInterface current = queue.poll();
closure.add(current);
current.getParentInterfaces__Interface()
.stream()
.filter(OperationInterface.class::isInstance)
.map(OperationInterface.class::cast)
.filter(i -> !closure.contains(i))
.forEach(queue::add);
}
return closure;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,98 +2,131 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.sirius.tools.api.ui.IExternalJavaAction;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.palladiosimulator.editors.commons.dialogs.selection.PalladioSelectEObjectDialog;
import org.palladiosimulator.editors.sirius.custom.util.PCMQueryUtils;
import org.palladiosimulator.pcm.repository.BasicComponent;
import org.palladiosimulator.pcm.repository.OperationInterface;
import org.palladiosimulator.pcm.repository.OperationRequiredRole;
import org.palladiosimulator.pcm.repository.OperationSignature;
import org.palladiosimulator.pcm.repository.Repository;
import org.palladiosimulator.pcm.repository.RequiredRole;
import org.palladiosimulator.pcm.seff.ExternalCallAction;
import org.palladiosimulator.pcm.seff.ResourceDemandingBehaviour;
import org.palladiosimulator.pcm.seff.ServiceEffectSpecification;

public class AddExternalCallAction implements IExternalJavaAction {


public static final Shell SHELL = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();


@Override
public void execute(Collection<? extends EObject> selections, Map<String, Object> parameters) {
ExternalCallAction extCall = (ExternalCallAction) parameters.get("instance");
HashMap<OperationInterface, OperationRequiredRole> requiredRolesMap = new HashMap<OperationInterface, OperationRequiredRole>();
OperationSignature os = getOperationSignature(extCall, requiredRolesMap);
if (os != null) {
extCall.setCalledService_ExternalService(os);
extCall.setRole_ExternalService(requiredRolesMap.get(os.getInterface__OperationSignature()));
}

}

private OperationSignature getOperationSignature(ExternalCallAction extCall, HashMap<OperationInterface, OperationRequiredRole> requiredRolesMap) {

Collection<Object> filter = new ArrayList<Object>();

filter.add(Repository.class);
filter.add(OperationInterface.class);
filter.add(OperationSignature.class);

Collection<EReference> additionalChildReferences = new ArrayList<EReference>();

PalladioSelectEObjectDialog dialog = new PalladioSelectEObjectDialog(SHELL, filter, additionalChildReferences,
extCall.eResource().getResourceSet());


dialog.setProvidedService(OperationSignature.class);

for (Object o : dialog.getTreeViewer().getExpandedElements()) {
if (!(o instanceof OperationInterface)) //if the current object is not an OperationInterface, skip.
continue;

ResourceDemandingBehaviour rd = extCall.getResourceDemandingBehaviour_AbstractAction();

ServiceEffectSpecification seff = SEFFUtil.getEnclosingSEFF(rd);
BasicComponent parent = seff.getBasicComponent_ServiceEffectSpecification();

//if o is not referenced by any OperationRequiredRole, remove it from the tree viewer
OperationRequiredRole requiredRole = getOperationRequiredRole(parent.getRequiredRoles_InterfaceRequiringEntity(), (OperationInterface) o);
if (requiredRole != null)
requiredRolesMap.put((OperationInterface) o, requiredRole);
else
dialog.getTreeViewer().remove(o);


}

dialog.open();

return (OperationSignature) dialog.getResult();
}

private OperationRequiredRole getOperationRequiredRole(Collection<RequiredRole> requiredRoles, OperationInterface operationInterface) {
for (RequiredRole r : requiredRoles) {
if (!(r instanceof OperationRequiredRole))
continue;

if (((OperationRequiredRole) r).getRequiredInterface__OperationRequiredRole() == operationInterface)
return (OperationRequiredRole) r;
}
return null;
}


@Override
public boolean canExecute(Collection<? extends EObject> selections) {
return true;
}

public interface SignatureSelector {
OperationSignature selectOperationSignature(ExternalCallAction extCall,
Collection<OperationInterface> requiredInterfaces);
}

private final SignatureSelector signatureSelector;

public AddExternalCallAction() {
this(AddExternalCallAction::selectOperationSignature);
}

public AddExternalCallAction(SignatureSelector signatureSelector) {
this.signatureSelector = signatureSelector;
}

@Override
public void execute(Collection<? extends EObject> selections, Map<String, Object> parameters) {
ExternalCallAction extCall = (ExternalCallAction) parameters.get("instance");
if (extCall == null) {
return;
}
Map<OperationInterface, Collection<OperationRequiredRole>> requiredRolesMap = createRequiredRolesMap(extCall);
OperationSignature os = signatureSelector.selectOperationSignature(extCall, requiredRolesMap.keySet());
if (os != null) {
extCall.setCalledService_ExternalService(os);
Collection<OperationRequiredRole> potentialRoles = requiredRolesMap
.getOrDefault(os.getInterface__OperationSignature(), Collections.emptyList());
// TODO add selection logic for potentialRoles.size() > 1 as part of EDITORS-215
OperationRequiredRole firstrole = potentialRoles.isEmpty() ? null
: potentialRoles.iterator()
.next();
extCall.setRole_ExternalService(firstrole);
}

}

protected Map<OperationInterface, Collection<OperationRequiredRole>> createRequiredRolesMap(
ExternalCallAction eca) {
Map<OperationInterface, Collection<OperationRequiredRole>> result = new HashMap<OperationInterface, Collection<OperationRequiredRole>>();

ResourceDemandingBehaviour rd = eca.getResourceDemandingBehaviour_AbstractAction();
ServiceEffectSpecification seff = SEFFUtil.getEnclosingSEFF(rd);
BasicComponent parent = seff.getBasicComponent_ServiceEffectSpecification();
Collection<OperationRequiredRole> operationRequiredRoles = parent.getRequiredRoles_InterfaceRequiringEntity()
.stream()
.filter(OperationRequiredRole.class::isInstance)
.map(OperationRequiredRole.class::cast)
.collect(Collectors.toList());

// add required role and required interfaces to map
for (OperationRequiredRole operationRequiredRole : operationRequiredRoles) {
OperationInterface operationInterface = operationRequiredRole.getRequiredInterface__OperationRequiredRole();
Collection<OperationInterface> operationInterfaces = PCMQueryUtils.getTransitiveParentInterfaceClosureIncludingSelf(
operationInterface);
for (OperationInterface i : operationInterfaces) {
Collection<OperationRequiredRole> requiredRoles = result.computeIfAbsent(i,
key -> new LinkedHashSet<OperationRequiredRole>());
requiredRoles.add(operationRequiredRole);
}
}

return result;
}

protected static OperationSignature selectOperationSignature(ExternalCallAction extCall,
Collection<OperationInterface> requiredInterfaces) {
Collection<Object> filter = new ArrayList<Object>();
filter.add(Repository.class);
filter.add(OperationInterface.class);
filter.add(OperationSignature.class);

Collection<EReference> additionalChildReferences = new ArrayList<EReference>();
Shell shell = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow()
.getShell();
PalladioSelectEObjectDialog dialog = new PalladioSelectEObjectDialog(shell, filter, additionalChildReferences,
extCall.eResource()
.getResourceSet());

dialog.setProvidedService(OperationSignature.class);

for (Object o : dialog.getTreeViewer()
.getExpandedElements()) {
if (!(o instanceof OperationInterface)) { // if the current object is not an
// OperationInterface, skip.
continue;
}
if (!requiredInterfaces.contains(o)) {
dialog.getTreeViewer()
.remove(o);
}
}

dialog.open();

return (OperationSignature) dialog.getResult();
}

@Override
public boolean canExecute(Collection<? extends EObject> selections) {
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.palladiosimulator.editors.commons.dialogs.selection.PalladioSelectEObjectDialog;
import org.palladiosimulator.editors.sirius.custom.util.PCMQueryUtils;
import org.palladiosimulator.pcm.repository.OperationInterface;
import org.palladiosimulator.pcm.repository.OperationProvidedRole;
import org.palladiosimulator.pcm.repository.OperationSignature;
Expand Down Expand Up @@ -46,22 +47,24 @@ private OperationSignature getOperationSignature(EntryLevelSystemCall element) {
filter.add(OperationInterface.class);
filter.add(OperationSignature.class);


Collection<EReference> additionalChildReferences = new ArrayList<EReference>();

PalladioSelectEObjectDialog dialog = new PalladioSelectEObjectDialog(SHELL, filter, additionalChildReferences,
element.eResource().getResourceSet());

Collection<OperationInterface> calledInterfaces = PCMQueryUtils
.getTransitiveParentInterfaceClosureIncludingSelf(element.getProvidedRole_EntryLevelSystemCall()
.getProvidedInterface__OperationProvidedRole());

dialog.setProvidedService(OperationSignature.class);


for (Object o : dialog.getTreeViewer().getExpandedElements()) {
if (!(o instanceof OperationInterface))
continue;
OperationInterface oi = (OperationInterface) o;
if (!element.getProvidedRole_EntryLevelSystemCall().getProvidedInterface__OperationProvidedRole().equals(oi))
dialog.getTreeViewer().remove(o);

if (!calledInterfaces.contains(oi)) {
dialog.getTreeViewer().remove(o);
}
}

dialog.open();
Expand All @@ -87,7 +90,6 @@ private OperationProvidedRole getOperationProvidedRole(EntryLevelSystemCall elem
return (OperationProvidedRole) dialog.getResult();
}


@Override
public boolean canExecute(final Collection<? extends EObject> arg0) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
<unit id="org.eclipse.sirius.runtime.ide.eef.feature.group" version="0.0.0"/>
<repository location="http://download.eclipse.org/releases/2021-09/202109151000/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="false" type="InstallableUnit">
<unit id="org.apache.commons.lang3" version="0.0.0"/>
<repository location="http://download.eclipse.org/tools/orbit/downloads/2021-09/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="false" type="InstallableUnit" filter="release">
<unit id="org.palladiosimulator.pcm.feature.feature.group" version="0.0.0"/>
<repository location="https://updatesite.palladio-simulator.com/palladio-core-pcm/releases/latest/"/>
Expand Down
16 changes: 16 additions & 0 deletions tests/org.palladiosimulator.editors.sirius.custom.tests/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="xtend-gen">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
34 changes: 34 additions & 0 deletions tests/org.palladiosimulator.editors.sirius.custom.tests/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.palladiosimulator.editors.sirius.custom.tests</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>
</projectDescription>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Sirius Editors Custom Code Tests
Bundle-SymbolicName: org.palladiosimulator.editors.sirius.custom.tests
Bundle-Version: 5.1.0.qualifier
Fragment-Host: org.palladiosimulator.editors.sirius.custom;bundle-version="5.0.0"
Automatic-Module-Name: org.palladiosimulator.editors.sirius.custom.tests
Bundle-RequiredExecutionEnvironment: JavaSE-11
Import-Package: org.junit;version="4.12.0",
org.junit.jupiter.api;version="5.7.0"
Require-Bundle: com.google.guava,
org.eclipse.xtext.xbase.lib,
org.eclipse.xtend.lib,
org.eclipse.xtend.lib.macro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source.. = src/,\
xtend-gen/
output.. = bin/
bin.includes = META-INF/,\
.
Loading

0 comments on commit 32af3fc

Please sign in to comment.