diff --git a/.gitignore b/.gitignore index 22c6e2f1..e03cccfc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/bin/ **/*.class target/ +xtend-gen/ \ No newline at end of file diff --git a/bundles/org.palladiosimulator.editors.sirius.custom/src/org/palladiosimulator/editors/sirius/custom/util/PCMQueryUtils.java b/bundles/org.palladiosimulator.editors.sirius.custom/src/org/palladiosimulator/editors/sirius/custom/util/PCMQueryUtils.java new file mode 100644 index 00000000..2c9e6a1d --- /dev/null +++ b/bundles/org.palladiosimulator.editors.sirius.custom/src/org/palladiosimulator/editors/sirius/custom/util/PCMQueryUtils.java @@ -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 getTransitiveParentInterfaceClosureIncludingSelf( + OperationInterface self) { + Collection closure = new HashSet<>(); + Queue 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; + } + +} diff --git a/bundles/org.palladiosimulator.editors.sirius.seff.custom/src/org/palladiosimulator/editors/sirius/seff/custom/externaljavaactions/AddExternalCallAction.java b/bundles/org.palladiosimulator.editors.sirius.seff.custom/src/org/palladiosimulator/editors/sirius/seff/custom/externaljavaactions/AddExternalCallAction.java index 3620b638..d8e2f6e9 100644 --- a/bundles/org.palladiosimulator.editors.sirius.seff.custom/src/org/palladiosimulator/editors/sirius/seff/custom/externaljavaactions/AddExternalCallAction.java +++ b/bundles/org.palladiosimulator.editors.sirius.seff.custom/src/org/palladiosimulator/editors/sirius/seff/custom/externaljavaactions/AddExternalCallAction.java @@ -2,8 +2,11 @@ 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; @@ -11,89 +14,119 @@ 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 selections, Map parameters) { - ExternalCallAction extCall = (ExternalCallAction) parameters.get("instance"); - HashMap requiredRolesMap = new HashMap(); - 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 requiredRolesMap) { - - Collection filter = new ArrayList(); - - filter.add(Repository.class); - filter.add(OperationInterface.class); - filter.add(OperationSignature.class); - - Collection additionalChildReferences = new ArrayList(); - - 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 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 selections) { - return true; - } + + public interface SignatureSelector { + OperationSignature selectOperationSignature(ExternalCallAction extCall, + Collection requiredInterfaces); + } + + private final SignatureSelector signatureSelector; + + public AddExternalCallAction() { + this(AddExternalCallAction::selectOperationSignature); + } + + public AddExternalCallAction(SignatureSelector signatureSelector) { + this.signatureSelector = signatureSelector; + } + + @Override + public void execute(Collection selections, Map parameters) { + ExternalCallAction extCall = (ExternalCallAction) parameters.get("instance"); + if (extCall == null) { + return; + } + Map> requiredRolesMap = createRequiredRolesMap(extCall); + OperationSignature os = signatureSelector.selectOperationSignature(extCall, requiredRolesMap.keySet()); + if (os != null) { + extCall.setCalledService_ExternalService(os); + Collection 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> createRequiredRolesMap( + ExternalCallAction eca) { + Map> result = new HashMap>(); + + ResourceDemandingBehaviour rd = eca.getResourceDemandingBehaviour_AbstractAction(); + ServiceEffectSpecification seff = SEFFUtil.getEnclosingSEFF(rd); + BasicComponent parent = seff.getBasicComponent_ServiceEffectSpecification(); + Collection 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 operationInterfaces = PCMQueryUtils.getTransitiveParentInterfaceClosureIncludingSelf( + operationInterface); + for (OperationInterface i : operationInterfaces) { + Collection requiredRoles = result.computeIfAbsent(i, + key -> new LinkedHashSet()); + requiredRoles.add(operationRequiredRole); + } + } + + return result; + } + + protected static OperationSignature selectOperationSignature(ExternalCallAction extCall, + Collection requiredInterfaces) { + Collection filter = new ArrayList(); + filter.add(Repository.class); + filter.add(OperationInterface.class); + filter.add(OperationSignature.class); + + Collection additionalChildReferences = new ArrayList(); + 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 selections) { + return true; + } } diff --git a/bundles/org.palladiosimulator.editors.sirius.usage.custom/src/org/palladiosimulator/editors/sirius/usage/custom/externaljavaactions/EntryLevelSystemCallDialog.java b/bundles/org.palladiosimulator.editors.sirius.usage.custom/src/org/palladiosimulator/editors/sirius/usage/custom/externaljavaactions/EntryLevelSystemCallDialog.java index 3f02fe6b..20202857 100644 --- a/bundles/org.palladiosimulator.editors.sirius.usage.custom/src/org/palladiosimulator/editors/sirius/usage/custom/externaljavaactions/EntryLevelSystemCallDialog.java +++ b/bundles/org.palladiosimulator.editors.sirius.usage.custom/src/org/palladiosimulator/editors/sirius/usage/custom/externaljavaactions/EntryLevelSystemCallDialog.java @@ -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; @@ -46,12 +47,14 @@ private OperationSignature getOperationSignature(EntryLevelSystemCall element) { filter.add(OperationInterface.class); filter.add(OperationSignature.class); - Collection additionalChildReferences = new ArrayList(); PalladioSelectEObjectDialog dialog = new PalladioSelectEObjectDialog(SHELL, filter, additionalChildReferences, element.eResource().getResourceSet()); - + Collection calledInterfaces = PCMQueryUtils + .getTransitiveParentInterfaceClosureIncludingSelf(element.getProvidedRole_EntryLevelSystemCall() + .getProvidedInterface__OperationProvidedRole()); + dialog.setProvidedService(OperationSignature.class); @@ -59,9 +62,9 @@ private OperationSignature getOperationSignature(EntryLevelSystemCall element) { 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(); @@ -87,7 +90,6 @@ private OperationProvidedRole getOperationProvidedRole(EntryLevelSystemCall elem return (OperationProvidedRole) dialog.getResult(); } - @Override public boolean canExecute(final Collection arg0) { return true; diff --git a/releng/org.palladiosimulator.editors.sirius.targetplatform/tp.target b/releng/org.palladiosimulator.editors.sirius.targetplatform/tp.target index 8c5c0807..a78ad7e0 100644 --- a/releng/org.palladiosimulator.editors.sirius.targetplatform/tp.target +++ b/releng/org.palladiosimulator.editors.sirius.targetplatform/tp.target @@ -6,6 +6,10 @@ + + + + diff --git a/tests/org.palladiosimulator.editors.sirius.custom.tests/.classpath b/tests/org.palladiosimulator.editors.sirius.custom.tests/.classpath new file mode 100644 index 00000000..bb6f7aed --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.custom.tests/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/org.palladiosimulator.editors.sirius.custom.tests/.project b/tests/org.palladiosimulator.editors.sirius.custom.tests/.project new file mode 100644 index 00000000..ced72922 --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.custom.tests/.project @@ -0,0 +1,34 @@ + + + org.palladiosimulator.editors.sirius.custom.tests + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/tests/org.palladiosimulator.editors.sirius.custom.tests/.settings/org.eclipse.jdt.core.prefs b/tests/org.palladiosimulator.editors.sirius.custom.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..c9545f06 --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.custom.tests/.settings/org.eclipse.jdt.core.prefs @@ -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 diff --git a/tests/org.palladiosimulator.editors.sirius.custom.tests/META-INF/MANIFEST.MF b/tests/org.palladiosimulator.editors.sirius.custom.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5368dd1f --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.custom.tests/META-INF/MANIFEST.MF @@ -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 diff --git a/tests/org.palladiosimulator.editors.sirius.custom.tests/build.properties b/tests/org.palladiosimulator.editors.sirius.custom.tests/build.properties new file mode 100644 index 00000000..d8e2f0e9 --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.custom.tests/build.properties @@ -0,0 +1,5 @@ +source.. = src/,\ + xtend-gen/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/tests/org.palladiosimulator.editors.sirius.custom.tests/src/org/palladiosimulator/editors/sirius/custom/util/PCMQueryUtilsTest.xtend b/tests/org.palladiosimulator.editors.sirius.custom.tests/src/org/palladiosimulator/editors/sirius/custom/util/PCMQueryUtilsTest.xtend new file mode 100644 index 00000000..84c64f36 --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.custom.tests/src/org/palladiosimulator/editors/sirius/custom/util/PCMQueryUtilsTest.xtend @@ -0,0 +1,94 @@ +package org.palladiosimulator.editors.sirius.custom.util + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.palladiosimulator.pcm.repository.OperationInterface +import org.palladiosimulator.pcm.repository.Repository +import org.palladiosimulator.pcm.repository.RepositoryFactory + +import static org.junit.Assert.assertEquals +import java.util.HashSet + +class PCMQueryUtilsTest { + + val static extension RepositoryFactory REPO_FACTORY = RepositoryFactory.eINSTANCE + var Repository repo + + @BeforeEach + def void setup() { + this.repo = createTestRepo() + } + + @Test + def void testNoInheritance() { + val expected = #{repo.getByName("Parent Parent Parent")} + val actual = PCMQueryUtils.getTransitiveParentInterfaceClosureIncludingSelf(repo.getByName("Parent Parent Parent")) + assertEquals(expected, actual) + } + + @Test + def void testSingleInheritance() { + val expected = #{repo.getByName("Parent Parent"), repo.getByName("Parent Parent Parent")} + val actual = PCMQueryUtils.getTransitiveParentInterfaceClosureIncludingSelf(repo.getByName("Parent Parent")) + assertEquals(expected, actual) + } + + @Test + def void testDiamondInheritance() { + val expected = new HashSet(repo.interfaces__Repository) + val actual = PCMQueryUtils.getTransitiveParentInterfaceClosureIncludingSelf(repo.getByName("Current")) + assertEquals(expected, actual) + } + + protected def getByName(Repository repo, String name) { + repo.interfaces__Repository.filter(OperationInterface).findFirst[entityName == name] + } + + protected static def createTestRepo() { + createRepository => [ + + val parentParentParentInterface = createOperationInterface => [ + entityName = "Parent Parent Parent" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentParentParent" + ] + ] + val parentParentInterface = createOperationInterface => [ + entityName = "Parent Parent" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentParent" + ] + parentInterfaces__Interface += parentParentParentInterface + ] + val parentInterfaceLeft = createOperationInterface => [ + entityName = "Parent Left" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentLeft" + ] + parentInterfaces__Interface += parentParentInterface + parentInterfaces__Interface += parentParentParentInterface + ] + val parentInterfaceRight = createOperationInterface => [ + entityName = "Parent Right" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentRight" + ] + parentInterfaces__Interface += parentParentInterface + ] + val currentInterface = createOperationInterface => [ + entityName = "Current" + signatures__OperationInterface += createOperationSignature => [ + entityName = "current" + ] + parentInterfaces__Interface += parentInterfaceLeft + parentInterfaces__Interface += parentInterfaceRight + ] + interfaces__Repository += parentParentParentInterface + interfaces__Repository += parentParentInterface + interfaces__Repository += parentInterfaceLeft + interfaces__Repository += parentInterfaceRight + interfaces__Repository += currentInterface + + ] + } +} diff --git a/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.classpath b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.classpath new file mode 100644 index 00000000..bb6f7aed --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.project b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.project new file mode 100644 index 00000000..0350dfa2 --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.project @@ -0,0 +1,34 @@ + + + org.palladiosimulator.editors.sirius.seff.custom.tests + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.settings/org.eclipse.jdt.core.prefs b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..c9545f06 --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/.settings/org.eclipse.jdt.core.prefs @@ -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 diff --git a/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/META-INF/MANIFEST.MF b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000..64076f7d --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/META-INF/MANIFEST.MF @@ -0,0 +1,15 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Sirius SEFF Custom Code Tests +Bundle-SymbolicName: org.palladiosimulator.editors.sirius.seff.custom.tests +Bundle-Version: 5.1.0.qualifier +Fragment-Host: org.palladiosimulator.editors.sirius.seff.custom;bundle-version="5.0.0" +Automatic-Module-Name: org.palladiosimulator.editors.sirius.seff.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, + org.apache.commons.lang3;bundle-version="2.1.0" diff --git a/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/build.properties b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/build.properties new file mode 100644 index 00000000..d8e2f0e9 --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/build.properties @@ -0,0 +1,5 @@ +source.. = src/,\ + xtend-gen/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/src/org/palladiosimulator/editors/sirius/seff/custom/tests/AddExternalCallActionTest.xtend b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/src/org/palladiosimulator/editors/sirius/seff/custom/tests/AddExternalCallActionTest.xtend new file mode 100644 index 00000000..e83718db --- /dev/null +++ b/tests/org.palladiosimulator.editors.sirius.seff.custom.tests/src/org/palladiosimulator/editors/sirius/seff/custom/tests/AddExternalCallActionTest.xtend @@ -0,0 +1,227 @@ +package org.palladiosimulator.editors.sirius.seff.custom.tests + +import java.util.function.Consumer +import java.util.function.Function +import org.apache.commons.lang3.mutable.MutableObject +import org.junit.jupiter.api.Test +import org.palladiosimulator.editors.sirius.seff.custom.externaljavaactions.AddExternalCallAction +import org.palladiosimulator.pcm.repository.BasicComponent +import org.palladiosimulator.pcm.repository.OperationInterface +import org.palladiosimulator.pcm.repository.OperationRequiredRole +import org.palladiosimulator.pcm.repository.Repository +import org.palladiosimulator.pcm.repository.RepositoryFactory +import org.palladiosimulator.pcm.seff.ExternalCallAction +import org.palladiosimulator.pcm.seff.SeffFactory + +import static org.junit.Assert.assertEquals +import static org.junit.Assert.assertNull +import static org.junit.Assert.assertTrue + +class AddExternalCallActionTest { + + static val extension RepositoryFactory REPO_FACTORY = RepositoryFactory.eINSTANCE + static val extension SeffFactory SEFF_FACTORY = SeffFactory.eINSTANCE + + @Test + def void testCanExecuteAlwaysReturnsTrue() { + assertTrue(new AddExternalCallAction().canExecute(null)) + } + + @Test + def void testInvalidExternalCallAction() { + runTest( + [repo|], + [repo|null], + [repo|null], + [repo|null], + [repo|#[]] + ) + } + + @Test + def void testWithSimpleInterface() { + val ecaWrapper = new MutableObject + val interfaceWrapper = new MutableObject + val roleWrapper = new MutableObject + runTest( + [repo| + ecaWrapper.value = repo.eAllContents.filter(ExternalCallAction).findFirst[true] + interfaceWrapper.value = repo.interfaces__Repository.filter(OperationInterface).findFirst[entityName == "Parent Parent Parent"] + roleWrapper.value = (repo.components__Repository.get(0) as BasicComponent).requiredRoles_InterfaceRequiringEntity.get(0) as OperationRequiredRole + roleWrapper.value.requiredInterface__OperationRequiredRole = interfaceWrapper.value + ], + [repo|ecaWrapper.value], + [repo|interfaceWrapper.value], + [repo|roleWrapper.value], + [repo|#[interfaceWrapper.value]] + ) + } + + @Test + def void testWithComplexInheritanceHierarchy() { + val ecaWrapper = new MutableObject + val interfaceWrapper = new MutableObject + val roleWrapper = new MutableObject + runTest( + [repo| + ecaWrapper.value = repo.eAllContents.filter(ExternalCallAction).findFirst[true] + interfaceWrapper.value = repo.interfaces__Repository.filter(OperationInterface).findFirst[entityName == "Current"] + roleWrapper.value = (repo.components__Repository.get(0) as BasicComponent).requiredRoles_InterfaceRequiringEntity.get(0) as OperationRequiredRole + ], + [repo|ecaWrapper.value], + [repo|interfaceWrapper.value], + [repo|roleWrapper.value], + [repo|repo.interfaces__Repository.filter(OperationInterface)] + ) + } + + @Test + def void testWithNoSelectedSignature() { + val ecaWrapper = new MutableObject + runTest( + [repo| + ecaWrapper.value = repo.eAllContents.filter(ExternalCallAction).findFirst[true] + ], + [repo|ecaWrapper.value], + [repo|null], + [repo|null], + [repo|repo.interfaces__Repository.filter(OperationInterface)] + ) + assertNull(ecaWrapper.value.calledService_ExternalService) + assertNull(ecaWrapper.value.role_ExternalService) + } + + @Test + def void testWithNoAvailableRequiredRole() { + val ecaWrapper = new MutableObject + val interfaceWrapper = new MutableObject + runTest( + [repo| + ecaWrapper.value = repo.eAllContents.filter(ExternalCallAction).findFirst[true] + interfaceWrapper.value = repo.interfaces__Repository.filter(OperationInterface).findFirst[entityName == "Current"] + val requiredRole = (repo.components__Repository.get(0) as BasicComponent).requiredRoles_InterfaceRequiringEntity.get(0) as OperationRequiredRole + requiredRole.requiredInterface__OperationRequiredRole = repo.interfaces__Repository.filter(OperationInterface).findFirst[entityName == "Parent Parent Parent"] + ], + [repo|ecaWrapper.value], + [repo|interfaceWrapper.value], + [repo|null], + [repo|repo.interfaces__Repository.filter(OperationInterface).filter[entityName == "Parent Parent Parent"]] + ) + } + + @Test + def void testWithMultiplePotentialRoles() { + // TODO test might have to be changed as part of EDITORS-215 + val ecaWrapper = new MutableObject + val interfaceWrapper = new MutableObject + val roleWrapper = new MutableObject // we always expect the first role to be selected + runTest( + [repo| + ecaWrapper.value = repo.eAllContents.filter(ExternalCallAction).findFirst[true] + interfaceWrapper.value = repo.interfaces__Repository.filter(OperationInterface).findFirst[entityName == "Parent Parent Parent"] + roleWrapper.value = (repo.components__Repository.get(0) as BasicComponent).requiredRoles_InterfaceRequiringEntity.get(0) as OperationRequiredRole + roleWrapper.value.requiredInterface__OperationRequiredRole = interfaceWrapper.value + val component = roleWrapper.value.requiringEntity_RequiredRole + component.requiredRoles_InterfaceRequiringEntity += createOperationRequiredRole => [ + requiredInterface__OperationRequiredRole = interfaceWrapper.value + ] + ], + [repo|ecaWrapper.value], + [repo|interfaceWrapper.value], + [repo|roleWrapper.value], + [repo|#[interfaceWrapper.value]] + ) + } + + protected def runTest(Consumer repoModifier, Function ecaProvider, + Function expectedInterfaceProvider, + Function expectedRoleProvider, + Function> expectedInterfacesProvider) { + + val repo = createDefaultRepository + repoModifier.accept(repo) + val externalCallAction = ecaProvider.apply(repo) + val expectedInterface = expectedInterfaceProvider.apply(repo) + val expectedInterfaces = expectedInterfacesProvider.apply(repo).toSet + val expectedRole = expectedRoleProvider.apply(repo) + val expectedSignature = expectedInterface?.signatures__OperationInterface?.iterator?.next + + val subject = new AddExternalCallAction([eca, interfaces | + assertEquals(externalCallAction, eca) + assertEquals(expectedInterfaces, interfaces) + expectedSignature + ]) + subject.execute(#[], #{"instance" -> externalCallAction}) + if (externalCallAction !== null) { + assertEquals(expectedSignature, externalCallAction.calledService_ExternalService) + assertEquals(expectedRole, externalCallAction.role_ExternalService) + } + } + + protected def Repository createDefaultRepository() { + createRepository => [ + + val parentParentParentInterface = createOperationInterface => [ + entityName = "Parent Parent Parent" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentParentParent" + ] + ] + val parentParentInterface = createOperationInterface => [ + entityName = "Parent Parent" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentParent" + ] + parentInterfaces__Interface += parentParentParentInterface + ] + val parentInterfaceLeft = createOperationInterface => [ + entityName = "Parent Left" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentLeft" + ] + parentInterfaces__Interface += parentParentInterface + parentInterfaces__Interface += parentParentParentInterface + ] + val parentInterfaceRight = createOperationInterface => [ + entityName = "Parent Right" + signatures__OperationInterface += createOperationSignature => [ + entityName = "parentRight" + ] + parentInterfaces__Interface += parentParentInterface + ] + val currentInterface = createOperationInterface => [ + entityName = "Current" + signatures__OperationInterface += createOperationSignature => [ + entityName = "current" + ] + parentInterfaces__Interface += parentInterfaceLeft + parentInterfaces__Interface += parentInterfaceRight + ] + interfaces__Repository += parentParentParentInterface + interfaces__Repository += parentParentInterface + interfaces__Repository += parentInterfaceLeft + interfaces__Repository += parentInterfaceRight + interfaces__Repository += currentInterface + + components__Repository += createBasicComponent => [ + entityName = "Component" + requiredRoles_InterfaceRequiringEntity += createOperationRequiredRole => [ + requiredInterface__OperationRequiredRole = currentInterface + ] + serviceEffectSpecifications__BasicComponent += createResourceDemandingSEFF => [ + describedService__SEFF = currentInterface.signatures__OperationInterface.iterator.next + val startAction = createStartAction + val ecAction = createExternalCallAction + ecAction.predecessor_AbstractAction = startAction + val stopAction = createStopAction + stopAction.predecessor_AbstractAction = ecAction + steps_Behaviour += startAction + steps_Behaviour += ecAction + steps_Behaviour += stopAction + ] + ] + + ] + } + +}