Skip to content

Commit ed1867a

Browse files
florianbarbinAxelRICHARD
authored andcommitted
[1210] Add the parameters compartment on ActionDefinition in GV Diagram
Bug: #1210 Signed-off-by: Florian Barbin <florian.barbin@obeo.fr>
1 parent 90aef32 commit ed1867a

12 files changed

Lines changed: 292 additions & 12 deletions

File tree

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ When end-users click on _New Object_ on a semantic element, and select a `ViewUs
3030
- https://github.com/eclipse-syson/syson/issues/1252[#1252] [exort] Implement textual export of `TriggerInvocationExpression`.
3131
- https://github.com/eclipse-syson/syson/issues/1233[#1233] [general-view] Add a creation tool of State sub actions with referenced action inside State elements
3232
- https://github.com/eclipse-syson/syson/issues/1255[#1255] [general-view] Improve label of `TransitionUsage` to display the "AcceptParameterPart".
33+
- https://github.com/eclipse-syson/syson/issues/1210[#1210] general-view] Add the `parameters` compartment on `ActionDefinition` in the _General View_ diagram.
3334

3435
=== New features
3536

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.application.controllers.diagrams.general.view;
14+
15+
import java.time.Duration;
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.UUID;
19+
import java.util.concurrent.atomic.AtomicReference;
20+
21+
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
22+
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
23+
import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariable;
24+
import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariableType;
25+
import org.eclipse.sirius.components.diagrams.Diagram;
26+
import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider;
27+
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
28+
import org.eclipse.syson.AbstractIntegrationTests;
29+
import org.eclipse.syson.SysONTestsProperties;
30+
import org.eclipse.syson.application.controllers.diagrams.checkers.CheckDiagramElementCount;
31+
import org.eclipse.syson.application.controllers.diagrams.checkers.DiagramCheckerService;
32+
import org.eclipse.syson.application.controllers.diagrams.checkers.IDiagramChecker;
33+
import org.eclipse.syson.application.controllers.diagrams.testers.NodeCreationTester;
34+
import org.eclipse.syson.application.data.GeneralViewWithTopNodesTestProjectData;
35+
import org.eclipse.syson.application.data.SysONRepresentationDescriptionIdentifiers;
36+
import org.eclipse.syson.diagram.general.view.GVDescriptionNameGenerator;
37+
import org.eclipse.syson.services.diagrams.DiagramComparator;
38+
import org.eclipse.syson.services.diagrams.DiagramDescriptionIdProvider;
39+
import org.eclipse.syson.services.diagrams.api.IGivenDiagramDescription;
40+
import org.eclipse.syson.services.diagrams.api.IGivenDiagramReference;
41+
import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription;
42+
import org.eclipse.syson.sysml.ActionDefinition;
43+
import org.eclipse.syson.sysml.SysmlPackage;
44+
import org.eclipse.syson.util.IDescriptionNameGenerator;
45+
import org.junit.jupiter.api.AfterEach;
46+
import org.junit.jupiter.api.BeforeEach;
47+
import org.junit.jupiter.api.DisplayName;
48+
import org.junit.jupiter.api.Test;
49+
import org.springframework.beans.factory.annotation.Autowired;
50+
import org.springframework.boot.test.context.SpringBootTest;
51+
import org.springframework.test.context.jdbc.Sql;
52+
import org.springframework.test.context.jdbc.SqlConfig;
53+
import org.springframework.transaction.annotation.Transactional;
54+
55+
import reactor.test.StepVerifier;
56+
57+
/**
58+
* Tests the {@link ActionDefinition} inherited features behavior with parameters compartment.
59+
*
60+
* @author fbarbin
61+
*/
62+
@Transactional
63+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { SysONTestsProperties.NO_DEFAULT_LIBRARIES_PROPERTY })
64+
public class GVActionDefinitionParameterTests extends AbstractIntegrationTests {
65+
66+
67+
private final IDescriptionNameGenerator descriptionNameGenerator = new GVDescriptionNameGenerator();
68+
69+
@Autowired
70+
private IGivenInitialServerState givenInitialServerState;
71+
72+
@Autowired
73+
private IGivenDiagramReference givenDiagram;
74+
75+
@Autowired
76+
private IGivenDiagramDescription givenDiagramDescription;
77+
78+
@Autowired
79+
private IGivenDiagramSubscription givenDiagramSubscription;
80+
81+
@Autowired
82+
private IDiagramIdProvider diagramIdProvider;
83+
84+
@Autowired
85+
private NodeCreationTester nodeCreationTester;
86+
87+
@Autowired
88+
private DiagramComparator diagramComparator;
89+
90+
private DiagramDescriptionIdProvider diagramDescriptionIdProvider;
91+
92+
private DiagramCheckerService diagramCheckerService;
93+
94+
private StepVerifier.Step<DiagramRefreshedEventPayload> verifier;
95+
96+
private AtomicReference<Diagram> diagram;
97+
98+
@BeforeEach
99+
public void setUp() {
100+
this.givenInitialServerState.initialize();
101+
var diagramEventInput = new DiagramEventInput(UUID.randomUUID(),
102+
GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
103+
GeneralViewWithTopNodesTestProjectData.GraphicalIds.DIAGRAM_ID);
104+
var flux = this.givenDiagramSubscription.subscribe(diagramEventInput);
105+
this.verifier = StepVerifier.create(flux);
106+
this.diagram = this.givenDiagram.getDiagram(this.verifier);
107+
var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
108+
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
109+
this.diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);
110+
this.diagramCheckerService = new DiagramCheckerService(this.diagramComparator, this.descriptionNameGenerator);
111+
}
112+
113+
@AfterEach
114+
public void tearDown() {
115+
if (this.verifier != null) {
116+
this.verifier.thenCancel()
117+
.verify(Duration.ofSeconds(10));
118+
}
119+
}
120+
121+
@DisplayName("Given a SysML Project with an ActionDefinition that generalizes a UseCaseDefinition, when creating a subject in the UseCaseDefinition, then it should not be displayed in the ActionDefinition parameters compartment")
122+
@Sql(scripts = { GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
123+
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
124+
@Test
125+
public void checkActionDefinitionInParameter() {
126+
this.checkItemParameterOnActionDefinition("In");
127+
}
128+
129+
private void checkItemParameterOnActionDefinition(String kind) {
130+
List<ToolVariable> variables = new ArrayList<>();
131+
variables.add(new ToolVariable("selectedObject", GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID, ToolVariableType.OBJECT_ID));
132+
133+
String creationToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getUseCaseDefinition()), "New Subject");
134+
this.verifier.then(() -> this.nodeCreationTester.createNode(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, this.diagram, "UseCaseDefinition", creationToolId, variables));
135+
136+
IDiagramChecker diagramChecker = (initialDiagram, newDiagram) -> {
137+
new CheckDiagramElementCount(this.diagramComparator)
138+
.hasNewBorderNodeCount(0)
139+
.hasNewNodeCount(1) // Only one subject in the UseCaseDefinition subjects compartment.
140+
.hasNewEdgeCount(0)
141+
.check(initialDiagram, newDiagram);
142+
143+
};
144+
145+
this.diagramCheckerService.checkDiagram(diagramChecker, this.diagram, this.verifier);
146+
}
147+
}

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVEdgeItemUsageTests.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ private void checkItemParameterOnActionDefinition(String kind) {
231231
IDiagramChecker diagramChecker = (initialDiagram, newDiagram) -> {
232232
new CheckDiagramElementCount(this.diagramComparator)
233233
.hasNewBorderNodeCount(1) // One bordered node
234-
.hasNewNodeCount(5) // One border + one root node for Tree Composition (with 3 compartments)
234+
.hasNewNodeCount(6) // One border + one root node for Tree Composition (with 3 compartments) +
235+
// parameters in the parameters compartment
235236
.hasNewEdgeCount(1) // Composite Edge
236237
.check(initialDiagram, newDiagram);
237238
List<Node> newNodes = this.diagramComparator.newNodes(initialDiagram, newDiagram);
@@ -248,9 +249,9 @@ private void checkItemParameterOnActionDefinition(String kind) {
248249
List<Node> otherNewNodes = newNodes.stream().filter(n -> n != rootItem && !rootItem.getChildNodes().contains(n)).toList();
249250

250251
// Check for nested item list node
251-
assertThat(otherNewNodes).hasSize(1)
252+
assertThat(otherNewNodes).hasSize(2)
253+
.filteredOn(Node::isBorderNode)
252254
.first(DiagramInstanceOfAssertFactories.NODE)
253-
.isBorderNode()
254255
.hasType("node:image")
255256
.hasTargetObjectLabel(ITEM1)
256257
.hasTargetObjectKind("siriusComponents://semantic?domain=sysml&entity=ItemUsage");

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVSubNodeStructureCreationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ private static Stream<Arguments> packageChildNodeParameters() {
189189
Arguments.of(SysmlPackage.eINSTANCE.getPortDefinition(), ownedMember, 4),
190190
Arguments.of(SysmlPackage.eINSTANCE.getAcceptActionUsage(), ownedMember, 1),
191191
Arguments.of(SysmlPackage.eINSTANCE.getActionUsage(), ownedMember, 4),
192-
Arguments.of(SysmlPackage.eINSTANCE.getActionDefinition(), ownedMember, 3),
192+
Arguments.of(SysmlPackage.eINSTANCE.getActionDefinition(), ownedMember, 4),
193193
Arguments.of(SysmlPackage.eINSTANCE.getAssignmentActionUsage(), ownedMember, 0),
194194
Arguments.of(SysmlPackage.eINSTANCE.getConcernUsage(), ownedMember, 7),
195195
Arguments.of(SysmlPackage.eINSTANCE.getConcernDefinition(), ownedMember, 8),

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVTopNodeCreationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private static Stream<Arguments> topNodeParameters() {
164164
Arguments.of(SysmlPackage.eINSTANCE.getPortDefinition(), 4),
165165
Arguments.of(SysmlPackage.eINSTANCE.getAcceptActionUsage(), 1),
166166
Arguments.of(SysmlPackage.eINSTANCE.getActionUsage(), 4),
167-
Arguments.of(SysmlPackage.eINSTANCE.getActionDefinition(), 3),
167+
Arguments.of(SysmlPackage.eINSTANCE.getActionDefinition(), 4),
168168
Arguments.of(SysmlPackage.eINSTANCE.getAssignmentActionUsage(), 0),
169169
Arguments.of(SysmlPackage.eINSTANCE.getConcernUsage(), 7),
170170
Arguments.of(SysmlPackage.eINSTANCE.getConcernDefinition(), 8),

backend/application/syson-application/src/test/resources/scripts/database-content/GeneralView-WithTopNodes.sql

Lines changed: 5 additions & 6 deletions
Large diffs are not rendered by default.

backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/InheritedCompartmentItemFilterSwitch.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024 Obeo.
2+
* Copyright (c) 2024, 2025 Obeo.
33
* This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -18,7 +18,9 @@
1818
import org.eclipse.emf.ecore.EClassifier;
1919
import org.eclipse.emf.ecore.EObject;
2020
import org.eclipse.emf.ecore.EReference;
21+
import org.eclipse.syson.sysml.Behavior;
2122
import org.eclipse.syson.sysml.ConstraintUsage;
23+
import org.eclipse.syson.sysml.Element;
2224
import org.eclipse.syson.sysml.Feature;
2325
import org.eclipse.syson.sysml.OwningMembership;
2426
import org.eclipse.syson.sysml.PartUsage;
@@ -48,6 +50,12 @@ public Boolean defaultCase(EObject object) {
4850

4951
@Override
5052
public Boolean caseFeature(Feature object) {
53+
// Add this behavior parameter check for each caseXXXUsage.
54+
// In this case, we want to display inherited parameters (directed feature) but not all features with the same
55+
// type.
56+
if (this.isBehaviorParameter()) {
57+
return this.isInheritedBehaviorParameter(object);
58+
}
5159
return this.eReference.getEType().equals(object.eClass());
5260
}
5361

@@ -72,15 +80,35 @@ public Boolean caseConstraintUsage(ConstraintUsage object) {
7280

7381
@Override
7482
public Boolean casePartUsage(PartUsage object) {
83+
// Add this behavior parameter check for each caseXXXUsage.
84+
// In this case, we want to display inherited parameters (directed feature) but not all features with the same
85+
// type.
86+
if (this.isBehaviorParameter()) {
87+
return this.isInheritedBehaviorParameter(object);
88+
}
7589
EClassifier eType = this.eReference.getEType();
7690
EClass eClass = object.eClass();
7791
return eType.equals(eClass) || (eType instanceof EClass eTypeEClass && eTypeEClass.isSuperTypeOf(eClass));
7892
}
7993

8094
@Override
8195
public Boolean caseReferenceUsage(ReferenceUsage object) {
96+
// Add this behavior parameter check for each caseXXXUsage.
97+
// In this case, we want to display inherited parameters (directed feature) but not all features with the same
98+
// type.
99+
if (this.isBehaviorParameter()) {
100+
return this.isInheritedBehaviorParameter(object);
101+
}
82102
EClassifier eType = this.eReference.getEType();
83103
EClass eClass = object.eClass();
84104
return eType.equals(eClass) || (eType instanceof EClass eTypeEClass && eTypeEClass.isSuperTypeOf(eClass));
85105
}
106+
107+
private boolean isBehaviorParameter() {
108+
return SysmlPackage.eINSTANCE.getBehavior_Parameter().equals(this.eReference);
109+
}
110+
111+
private boolean isInheritedBehaviorParameter(Element object) {
112+
return object.getOwner() instanceof Behavior behavior && behavior.getParameter().contains(object);
113+
}
86114
}

backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/GeneralViewDiagramDescriptionProvider.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import org.eclipse.syson.diagram.general.view.edges.TransitionEdgeDescriptionProvider;
7575
import org.eclipse.syson.diagram.general.view.edges.UsageNestedActionUsageEdgeDescriptionProvider;
7676
import org.eclipse.syson.diagram.general.view.edges.UsageNestedUsageEdgeDescriptionProvider;
77+
import org.eclipse.syson.diagram.general.view.nodes.ActionDefinitionParametersCompartmentNodeDescriptionProvider;
7778
import org.eclipse.syson.diagram.general.view.nodes.ActionItemNodeDescriptionProvider;
7879
import org.eclipse.syson.diagram.general.view.nodes.ActionsCompartmentNodeDescriptionProvider;
7980
import org.eclipse.syson.diagram.general.view.nodes.ActorNodeDescriptionProvider;
@@ -322,6 +323,7 @@ public RepresentationDescription create(IColorProvider colorProvider) {
322323
this.linkCaseObjectiveRequirementCompartment(cache);
323324
this.linkAllocationDefinitionEndsCompartment(cache);
324325
this.linkStatesCompartment(cache);
326+
this.linkActionDefinitionCompartments(cache);
325327

326328
var palette = this.createDiagramPalette(cache);
327329
diagramDescription.setPalette(palette);
@@ -396,6 +398,10 @@ private List<IDiagramElementDescriptionProvider<?>> createAllCompartmentNodeDesc
396398
// ActionDefinition
397399
compartmentNodeDescriptionProviders.addAll(this.createCompartmentsForOwnedAction(colorProvider));
398400

401+
// Compartment "parameters" (DirectedFeature) is defined for:
402+
// ActionDefinition
403+
compartmentNodeDescriptionProviders.addAll(this.createCompartmentsForActionDefinition(colorProvider));
404+
399405
// Compartment "actions" (NestedAction) is defined for:
400406
// ActionUsage, PartUsage, PerformActionUsage
401407
compartmentNodeDescriptionProviders.addAll(this.createCompartmentsForNestedAction(colorProvider));
@@ -495,6 +501,16 @@ private List<IDiagramElementDescriptionProvider<?>> createCompartmentsForOwnedAc
495501
return compartmentNodeDescriptionProviders;
496502
}
497503

504+
private List<IDiagramElementDescriptionProvider<?>> createCompartmentsForActionDefinition(IColorProvider colorProvider) {
505+
final List<IDiagramElementDescriptionProvider<?>> compartmentNodeDescriptionProviders = new ArrayList<>();
506+
compartmentNodeDescriptionProviders.add(new ActionDefinitionParametersCompartmentNodeDescriptionProvider(colorProvider, this.getDescriptionNameGenerator()));
507+
compartmentNodeDescriptionProviders.add(new CompartmentItemNodeDescriptionProvider(SysmlPackage.eINSTANCE.getActionDefinition(), SysmlPackage.eINSTANCE.getBehavior_Parameter(), colorProvider,
508+
this.getDescriptionNameGenerator()));
509+
compartmentNodeDescriptionProviders.add(new InheritedCompartmentItemNodeDescriptionProvider(SysmlPackage.eINSTANCE.getActionDefinition(), SysmlPackage.eINSTANCE.getBehavior_Parameter(),
510+
colorProvider, this.getDescriptionNameGenerator()));
511+
return compartmentNodeDescriptionProviders;
512+
}
513+
498514
private List<IDiagramElementDescriptionProvider<?>> createCompartmentsForConnectionEnd(IColorProvider colorProvider) {
499515
final List<IDiagramElementDescriptionProvider<?>> compartmentNodeDescriptionProviders = new ArrayList<>();
500516

@@ -930,6 +946,24 @@ private void linkStatesCompartment(IViewDiagramElementFinder cache) {
930946
);
931947
}
932948

949+
private void linkActionDefinitionCompartments(IViewDiagramElementFinder cache) {
950+
NodeDescription actionDefinitionNodeDescription = cache.getNodeDescription(this.getDescriptionNameGenerator().getNodeName(SysmlPackage.eINSTANCE.getActionDefinition())).get();
951+
String documentationCompartmentName = this.getDescriptionNameGenerator().getCompartmentName(SysmlPackage.eINSTANCE.getActionDefinition(), SysmlPackage.eINSTANCE.getElement_Documentation());
952+
953+
// We want to add the Parameters container just after the documentation. If the documentation is not found, we
954+
// will add it at the first index.
955+
Integer documentationContainerIndex = actionDefinitionNodeDescription.getReusedChildNodeDescriptions().stream()
956+
.filter(nodeDescription -> documentationCompartmentName.equals(nodeDescription.getName()))
957+
.findFirst()
958+
.map(documentationContainerDescription -> actionDefinitionNodeDescription.getReusedChildNodeDescriptions().indexOf(documentationContainerDescription))
959+
.orElse(-1);
960+
cache.getNodeDescription(
961+
this.getDescriptionNameGenerator().getCompartmentName(SysmlPackage.eINSTANCE.getActionDefinition(), SysmlPackage.eINSTANCE.getBehavior_Parameter()))
962+
.ifPresent(parameterContainerNodeDescription -> {
963+
actionDefinitionNodeDescription.getReusedChildNodeDescriptions().add(documentationContainerIndex + 1, parameterContainerNodeDescription);
964+
});
965+
}
966+
933967
private DiagramPalette createDiagramPalette(IViewDiagramElementFinder cache) {
934968
return this.diagramBuilderHelper.newDiagramPalette()
935969
.dropNodeTool(this.createDropFromDiagramTool(cache))

0 commit comments

Comments
 (0)