diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 909638da6..91c0cdbde 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,24 @@ = Changelog +== v2026.9.0 (work in progress) + +=== Shapes + +=== Architectural decision records + +=== Breaking changes + +=== Dependency update + +=== Bug fixes + +=== Improvements + +=== New features + +- https://github.com/eclipse-syson/syson/issues/2316[#2316] [diagrams] Add support for list item inheritance in _perform actions_ compartments +s + == v2026.7.0 === Breaking changes diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVCompartmentItemInheritanceTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVCompartmentItemInheritanceTests.java index 4161bfef1..0417ef20a 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVCompartmentItemInheritanceTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVCompartmentItemInheritanceTests.java @@ -344,6 +344,55 @@ public void checkStateUsageExhibitStatesInheritanceWithRedefinition() { .run(); } + @DisplayName("GIVEN a base ActionDefinition with a perform action, WHEN another ActionDefinition is subclassing the base ActionDefinition, THEN the base ActionDefinition perform actions are inherited by the other ActionDefinition") + @Test + public void checkActionDefinitionPerformActionsInheritanceWithSubclassification() { + new ElementSpecializationInheritanceTestRunner() + .baseElementToInheritFromEClass(SysmlPackage.eINSTANCE.getActionDefinition()) + .baseElementToInheritFromNodeId(GeneralViewWithTopNodesTestProjectData.GraphicalIds.ACTION_DEFINITION_ID) + .elementToInheritCreationToolName("New Perform action") + .withEdgeExpected() + .withSelectedElementId("") + .elementToInheritExpectedListItemLabelText("ref ") + .compartmentName("perform actions") + .elementThatInheritFromBaseElementCreationToolName("New Action Definition") + .elementThatInheritFromBaseElementEClass(SysmlPackage.eINSTANCE.getActionDefinition()) + .specializationToolName("New Subclassification") + .run(); + } + + @DisplayName("GIVEN a StateDefinition with a do action, WHEN a StateUsage is typed by the StateDefinition, THEN the StateDefinition perform actions are inherited by the StateUsage") + @Test + public void checkStateDefinitionPerformActionsInheritanceWithFeatureTyping() { + new ElementSpecializationInheritanceTestRunner() + .baseElementToInheritFromEClass(SysmlPackage.eINSTANCE.getStateDefinition()) + .baseElementToInheritFromNodeId(GeneralViewWithTopNodesTestProjectData.GraphicalIds.STATE_DEFINITION_ID) + .elementToInheritCreationToolName("New Do Action") + .withSelectedElementId(GeneralViewWithTopNodesTestProjectData.SemanticIds.ACTION_USAGE_ID) + .elementToInheritExpectedListItemLabelText("ref do ::> action") + .compartmentName("perform actions") + .elementThatInheritFromBaseElementCreationToolName("New State") + .elementThatInheritFromBaseElementEClass(SysmlPackage.eINSTANCE.getStateUsage()) + .specializationToolName("New Feature Typing") + .run(); + } + + @DisplayName("GIVEN a StateUsage with an entry action, WHEN a PartUsage is subsetting by reference the StateUsage, THEN the StateUsage perform actions are inherited by the PartUsage") + @Test + public void checkStateUsagePerformActionsInheritanceWithReferenceSubsetting() { + new ElementSpecializationInheritanceTestRunner() + .baseElementToInheritFromEClass(SysmlPackage.eINSTANCE.getStateUsage()) + .baseElementToInheritFromNodeId(GeneralViewWithTopNodesTestProjectData.GraphicalIds.STATE_USAGE_ID) + .elementToInheritCreationToolName("New Entry Action") + .withSelectedElementId(GeneralViewWithTopNodesTestProjectData.SemanticIds.ACTION_USAGE_ID) + .elementToInheritExpectedListItemLabelText("ref entry ::> action") + .compartmentName("perform actions") + .elementThatInheritFromBaseElementCreationToolName("New Part") + .elementThatInheritFromBaseElementEClass(SysmlPackage.eINSTANCE.getPartUsage()) + .specializationToolName("New Reference Subsetting") + .run(); + } + /** * This test runner verifies that creating a specializing relationship create inherited elements. * diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/InheritedCompartmentItemFilterSwitch.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/InheritedCompartmentItemFilterSwitch.java index e0cfd3a00..89a828ff6 100644 --- a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/InheritedCompartmentItemFilterSwitch.java +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/InheritedCompartmentItemFilterSwitch.java @@ -19,6 +19,7 @@ import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; +import org.eclipse.syson.sysml.ActionUsage; import org.eclipse.syson.sysml.Behavior; import org.eclipse.syson.sysml.ConstraintUsage; import org.eclipse.syson.sysml.Definition; @@ -26,6 +27,7 @@ import org.eclipse.syson.sysml.Feature; import org.eclipse.syson.sysml.OwningMembership; import org.eclipse.syson.sysml.PartUsage; +import org.eclipse.syson.sysml.PerformActionUsage; import org.eclipse.syson.sysml.ReferenceUsage; import org.eclipse.syson.sysml.RequirementConstraintKind; import org.eclipse.syson.sysml.RequirementConstraintMembership; @@ -79,13 +81,11 @@ public Boolean caseExhibitStateUsage(ExhibitStateUsage object) { // Add this behavior parameter check for each caseXXXUsage. // In this case, we want to display inherited parameters (directed feature) but not all features with the same // type. - if (!shouldKeep && this.shouldConsiderParameter(object)) { + if (this.shouldConsiderParameter(object)) { shouldKeep = this.isInheritedParameter(object); - } - if (!shouldKeep && this.shouldConsiderExhibitState(object)) { + } else if (this.shouldConsiderExhibitState(object)) { shouldKeep = this.isInheritedState(object); - } - if (!shouldKeep) { + } else { shouldKeep = super.caseExhibitStateUsage(object); } return shouldKeep; @@ -115,6 +115,22 @@ public Boolean casePartUsage(PartUsage object) { return eType.equals(eClass) || (eType instanceof EClass eTypeEClass && eTypeEClass.isSuperTypeOf(eClass)); } + @Override + public Boolean casePerformActionUsage(PerformActionUsage object) { + Boolean shouldKeep = Boolean.FALSE; + // Add this behavior parameter check for each caseXXXUsage. + // In this case, we want to display inherited parameters (directed feature) but not all features with the same + // type. + if (this.shouldConsiderParameter(object)) { + shouldKeep = this.isInheritedParameter(object); + } else if (this.shouldConsiderPerformUsage(object)) { + shouldKeep = this.isInheritedAction(object); + } else { + shouldKeep = super.casePerformActionUsage(object); + } + return shouldKeep; + } + @Override public Boolean caseReferenceUsage(ReferenceUsage object) { // Add this behavior parameter check for each caseXXXUsage. @@ -162,4 +178,23 @@ private boolean isInheritedState(Feature feature) { }; return featureState.contains(feature); } + + private boolean shouldConsiderPerformUsage(Feature feature) { + if (!(feature instanceof PerformActionUsage)) { + return false; + } + + EClassifier eType = this.eReference.getEType(); + EClass eClass = feature.eClass(); + return eType.equals(eClass) || (eType instanceof EClass eTypeEClass && eTypeEClass.isSuperTypeOf(eClass)); + } + + private boolean isInheritedAction(Feature feature) { + List< ActionUsage> featureActions = switch (feature.getOwner()) { + case Definition definition -> definition.getOwnedAction(); + case Usage usage -> usage.getNestedAction(); + default -> List.of(); + }; + return featureActions.contains(feature); + } } diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java index a21b166b9..f6600f759 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java @@ -131,6 +131,7 @@ import org.eclipse.syson.standard.diagrams.view.nodes.ObjectiveDocumentationCompartmentItemNodeDescription; import org.eclipse.syson.standard.diagrams.view.nodes.PerformActionsCompartmentItemNodeDescriptionProvider; import org.eclipse.syson.standard.diagrams.view.nodes.PerformActionsCompartmentNodeDescriptionProvider; +import org.eclipse.syson.standard.diagrams.view.nodes.PerformActionsInheritedCompartmentItemNodeDescriptionProvider; import org.eclipse.syson.standard.diagrams.view.nodes.PortDefinitionOwnedItemBorderNodeDescriptionProvider; import org.eclipse.syson.standard.diagrams.view.nodes.PortDefinitionOwnedItemCompartmentItemNodeDescriptionProvider; import org.eclipse.syson.standard.diagrams.view.nodes.PortUsageBorderNodeDescriptionProvider; @@ -639,6 +640,7 @@ private List> createCompartmentsForListIte compartmentNodeDescriptionProviders.add(new CompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new CompartmentNodeDescriptionProvider(eClass, eReference, colorProvider)); compartmentNodeDescriptionProviders.add(new InheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); + compartmentNodeDescriptionProviders.add(new PerformActionsInheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); } else if ((SysmlPackage.eINSTANCE.getPartUsage().equals(eClass) && SysmlPackage.eINSTANCE.getUsage_NestedAction().equals(eReference)) @@ -646,6 +648,7 @@ private List> createCompartmentsForListIte compartmentNodeDescriptionProviders.add(new ActionItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new CompartmentNodeDescriptionProvider(eClass, eReference, colorProvider)); compartmentNodeDescriptionProviders.add(new InheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); + compartmentNodeDescriptionProviders.add(new PerformActionsInheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); } else if ((SysmlPackage.eINSTANCE.getPartUsage().equals(eClass) && SysmlPackage.eINSTANCE.getUsage_NestedState().equals(eReference)) @@ -661,6 +664,7 @@ private List> createCompartmentsForListIte compartmentNodeDescriptionProviders.add(new CompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new CompartmentNodeDescriptionProvider(eClass, eReference, colorProvider)); compartmentNodeDescriptionProviders.add(new InheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); + compartmentNodeDescriptionProviders.add(new PerformActionsInheritedCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentItemNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); compartmentNodeDescriptionProviders.add(new PerformActionsCompartmentNodeDescriptionProvider(eClass, eReference, colorProvider, this.getDescriptionNameGenerator())); } else if (SysmlPackage.eINSTANCE.getPortDefinition().equals(eClass) && SysmlPackage.eINSTANCE.getDefinition_OwnedItem().equals(eReference)) { diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/PerformActionsCompartmentNodeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/PerformActionsCompartmentNodeDescriptionProvider.java index 6c1f22ed5..0561de936 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/PerformActionsCompartmentNodeDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/PerformActionsCompartmentNodeDescriptionProvider.java @@ -64,6 +64,7 @@ protected List getDroppableNodes(IViewDiagramElementFinder cach public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) { cache.getNodeDescription(this.getDescriptionNameGenerator().getCompartmentName(this.eClass, this.eReference) + PERFORM_ACTIONS_COMPARTMENT_NAME).ifPresent(nd -> { cache.getNodeDescription(this.getDescriptionNameGenerator().getCompartmentItemName(this.eClass, this.eReference) + PERFORM_ACTIONS_COMPARTMENT_NAME).ifPresent(nd.getChildrenDescriptions()::add); + cache.getNodeDescription(this.getDescriptionNameGenerator().getInheritedCompartmentItemName(this.eClass, this.eReference) + PERFORM_ACTIONS_COMPARTMENT_NAME).ifPresent(nd.getChildrenDescriptions()::add); nd.setPalette(this.createCompartmentPalette(cache)); }); } diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/PerformActionsInheritedCompartmentItemNodeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/PerformActionsInheritedCompartmentItemNodeDescriptionProvider.java new file mode 100644 index 000000000..a86803642 --- /dev/null +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/PerformActionsInheritedCompartmentItemNodeDescriptionProvider.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2026 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.standard.diagrams.view.nodes; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.sirius.components.view.builder.providers.IColorProvider; +import org.eclipse.sirius.components.view.diagram.NodeDescription; +import org.eclipse.syson.diagram.common.view.nodes.InheritedCompartmentItemNodeDescriptionProvider; +import org.eclipse.syson.sysml.SysmlPackage; +import org.eclipse.syson.util.AQLConstants; +import org.eclipse.syson.util.IDescriptionNameGenerator; +import org.eclipse.syson.util.SysMLMetamodelHelper; + +/** + * The inherited perform action compartment list item node description provider. + * + * @author gcoutable + */ +public class PerformActionsInheritedCompartmentItemNodeDescriptionProvider extends InheritedCompartmentItemNodeDescriptionProvider { + + public PerformActionsInheritedCompartmentItemNodeDescriptionProvider(EClass eClass, EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) { + super(eClass, eReference, colorProvider, descriptionNameGenerator); + } + + @Override + public NodeDescription create() { + NodeDescription nd = super.create(); + var qualifiedName = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getPerformActionUsage()); + nd.setName(this.descriptionNameGenerator.getInheritedCompartmentItemName(this.eClass, this.eReference) + PerformActionsCompartmentNodeDescriptionProvider.PERFORM_ACTIONS_COMPARTMENT_NAME); + nd.setDomainType(qualifiedName); + nd.setPreconditionExpression(AQLConstants.AQL_SELF + ".oclIsTypeOf(" + qualifiedName + ")"); + return nd; + } +} diff --git a/doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc new file mode 100644 index 000000000..821339cd7 --- /dev/null +++ b/doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc @@ -0,0 +1,29 @@ += 2026.9.0 (work in progress) + +== Key highlights + +== New features + +* In diagrams: + +** Add support for list item inheritance in _perform actions_ compartments. + +* In textual import/export: + +== Bug fixes + +* In diagrams: + +* In textual import/export: + + +== Improvements + +* In diagrams: + +* In textual import/export: + + +== Technical details + +* For technical details on this {product} release, including breaking changes, please refer to the https://github.com/eclipse-syson/syson/blob/main/CHANGELOG.adoc[changelog]. diff --git a/doc/content/modules/user-manual/pages/release-notes/release-notes.adoc b/doc/content/modules/user-manual/pages/release-notes/release-notes.adoc index bdb6ad329..3096a03ca 100644 --- a/doc/content/modules/user-manual/pages/release-notes/release-notes.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/release-notes.adoc @@ -2,6 +2,7 @@ :sectnums!: +include::user-manual:release-notes/2026.9.0.adoc[leveloffset=+1] include::user-manual:release-notes/2026.7.0.adoc[leveloffset=+1] include::user-manual:release-notes/2026.5.0.adoc[leveloffset=+1] include::user-manual:release-notes/2026.3.0.adoc[leveloffset=+1] diff --git a/doc/docs-site/antora-playbook.yml b/doc/docs-site/antora-playbook.yml index 3ee1402d9..d8d7453d9 100644 --- a/doc/docs-site/antora-playbook.yml +++ b/doc/docs-site/antora-playbook.yml @@ -1,6 +1,6 @@ site: title: SysON Docs - start_page: v2026.5.0@syson::index.adoc + start_page: v2026.7.0@syson::index.adoc output: clean: true