Skip to content

Commit 25adc5d

Browse files
pcdavidAxelRICHARD
authored andcommitted
[2054] Fix the invocation of "New Start/Done Action" from inside a package named "Actions"
Bug: #2054 Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
1 parent a2b3e62 commit 25adc5d

File tree

4 files changed

+172
-3
lines changed

4 files changed

+172
-3
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ It now follows the same rule than all other graphical node: if a compartment tha
9595
- https://github.com/eclipse-syson/syson/issues/1990[#1990] [diagrams] Fix the `EnumerationDefinition` graphical node compartment name to follow the SysMLv2 specification.
9696
- https://github.com/eclipse-syson/syson/issues/2049[#2049] [diagrams] Fix the direct edit and the display of `ends` graphical node elements inside the _ends_ compartment.
9797
Now the _end_ keyword is not displayed anymore in the label of these graphical nodes, and the direct edit only allows to edit the name of the end instead of the full label which was confusing for users.
98-
98+
- https://github.com/eclipse-syson/syson/issues/2054[#2054] [diagrams] Fix an error when invoking the tools _New Start Action_ or _New Done Action_ from inside a package named `Actions`.
9999

100100
=== Improvements
101101

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 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 static org.assertj.core.api.Assertions.assertThat;
16+
import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat;
17+
18+
import java.time.Duration;
19+
import java.util.Optional;
20+
import java.util.UUID;
21+
import java.util.concurrent.atomic.AtomicReference;
22+
import java.util.function.Consumer;
23+
import java.util.stream.Stream;
24+
25+
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
26+
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
27+
import org.eclipse.sirius.components.core.api.IObjectSearchService;
28+
import org.eclipse.sirius.components.diagrams.Diagram;
29+
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionInput;
30+
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionSuccessPayload;
31+
import org.eclipse.sirius.components.graphql.tests.api.IExecuteEditingContextFunctionRunner;
32+
import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider;
33+
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
34+
import org.eclipse.syson.AbstractIntegrationTests;
35+
import org.eclipse.syson.GivenSysONServer;
36+
import org.eclipse.syson.application.controllers.diagrams.checkers.CheckDiagramElementCount;
37+
import org.eclipse.syson.application.controllers.diagrams.testers.ToolTester;
38+
import org.eclipse.syson.application.controllers.utils.TestNameGenerator;
39+
import org.eclipse.syson.application.data.GeneralViewWithTopNodesTestProjectData;
40+
import org.eclipse.syson.services.diagrams.DiagramComparator;
41+
import org.eclipse.syson.services.diagrams.DiagramDescriptionIdProvider;
42+
import org.eclipse.syson.services.diagrams.api.IGivenDiagramDescription;
43+
import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription;
44+
import org.eclipse.syson.standard.diagrams.view.SDVDescriptionNameGenerator;
45+
import org.eclipse.syson.sysml.Package;
46+
import org.eclipse.syson.sysml.SysmlPackage;
47+
import org.eclipse.syson.util.IDescriptionNameGenerator;
48+
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
49+
import org.junit.jupiter.api.BeforeEach;
50+
import org.junit.jupiter.api.DisplayName;
51+
import org.junit.jupiter.params.ParameterizedTest;
52+
import org.junit.jupiter.params.provider.Arguments;
53+
import org.junit.jupiter.params.provider.MethodSource;
54+
import org.springframework.beans.factory.annotation.Autowired;
55+
import org.springframework.boot.test.context.SpringBootTest;
56+
import org.springframework.transaction.annotation.Transactional;
57+
58+
import reactor.core.publisher.Flux;
59+
import reactor.test.StepVerifier;
60+
61+
/**
62+
* Tests the New Start Action and New Done Action tools.
63+
*
64+
* @author pcdavid
65+
*/
66+
@Transactional
67+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
68+
public class GVNewStartDoneActionsTests extends AbstractIntegrationTests {
69+
70+
private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator();
71+
72+
@Autowired
73+
private IGivenInitialServerState givenInitialServerState;
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 ToolTester nodeCreationTester;
86+
87+
@Autowired
88+
private DiagramComparator diagramComparator;
89+
90+
@Autowired
91+
private IExecuteEditingContextFunctionRunner executeEditingContextFunctionRunner;
92+
93+
@Autowired
94+
private IObjectSearchService objectSearchService;
95+
96+
private Flux<DiagramRefreshedEventPayload> givenSubscriptionToDiagram() {
97+
var diagramEventInput = new DiagramEventInput(UUID.randomUUID(),
98+
GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
99+
GeneralViewWithTopNodesTestProjectData.GraphicalIds.DIAGRAM_ID);
100+
return this.givenDiagramSubscription.subscribe(diagramEventInput);
101+
}
102+
103+
@BeforeEach
104+
public void setUp() {
105+
this.givenInitialServerState.initialize();
106+
}
107+
108+
private static Stream<Arguments> toolParameters() {
109+
return Stream.of(Arguments.of("New Start Action"), Arguments.of("New Done Action")).map(TestNameGenerator::namedArguments);
110+
}
111+
112+
@DisplayName("GIVEN a SysML Project with an ActionDefinition inside a package named Actions, WHEN invoking $toolName, THEN the action is added in the action flow compartment")
113+
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
114+
@ParameterizedTest
115+
@MethodSource("toolParameters")
116+
public void checkNewStartAction(String toolName) {
117+
var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
118+
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
119+
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);
120+
String creationToolId = diagramDescriptionIdProvider.getNodeToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getActionDefinition()), toolName);
121+
AtomicReference<Diagram> diagram = new AtomicReference<>();
122+
123+
var flux = this.givenSubscriptionToDiagram();
124+
125+
Consumer<Object> initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram::set);
126+
127+
Runnable renamePackageAction = () -> {
128+
var input = new ExecuteEditingContextFunctionInput(UUID.randomUUID(), GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
129+
(editingContext, executeEditingContextFunctionInput) -> {
130+
Optional<Object> optPackage = this.objectSearchService.getObject(editingContext, GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID);
131+
assertThat(optPackage).isPresent().get().isInstanceOf(Package.class);
132+
var parentPacakge = (Package) optPackage.get();
133+
parentPacakge.setDeclaredName("Actions");
134+
return new ExecuteEditingContextFunctionSuccessPayload(executeEditingContextFunctionInput.id(), true);
135+
});
136+
var payload = this.executeEditingContextFunctionRunner.execute(input).block();
137+
assertThat(payload).isInstanceOf(ExecuteEditingContextFunctionSuccessPayload.class);
138+
};
139+
140+
Runnable invokeCreationTool = () -> this.nodeCreationTester.invokeTool(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, diagram, "ActionDefinition", creationToolId);
141+
142+
Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
143+
new CheckDiagramElementCount(this.diagramComparator)
144+
.hasNewNodeCount(1)
145+
.check(diagram.get(), newDiagram);
146+
});
147+
148+
StepVerifier.create(flux)
149+
.consumeNextWith(initialDiagramContentConsumer)
150+
.then(renamePackageAction)
151+
.then(invokeCreationTool)
152+
.consumeNextWith(diagramCheck)
153+
.thenCancel()
154+
.verify(Duration.ofSeconds(10));
155+
}
156+
157+
}

backend/services/syson-services/src/main/java/org/eclipse/syson/services/UtilService.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.Collection;
1717
import java.util.List;
1818
import java.util.Objects;
19+
import java.util.Optional;
1920

2021
import org.antlr.v4.runtime.atn.Transition;
2122
import org.eclipse.emf.common.notify.Adapter;
@@ -601,7 +602,7 @@ public void removeTransitionFeaturesOfSpecificKind(TransitionUsage transition, T
601602
* @return the standard start ActionUsage defined in the <code>Actions</code> library.
602603
*/
603604
public ActionUsage retrieveStandardStartAction(Element eObject) {
604-
return this.findByName(eObject, "Actions::Action::start");
605+
return this.findByNameAndTypeInStandardLibraries(eObject, ActionUsage.class, "Actions::Action::start");
605606
}
606607

607608
/**
@@ -613,7 +614,17 @@ public ActionUsage retrieveStandardStartAction(Element eObject) {
613614
* @return the standard done ActionUsage defined in the <code>Actions</code> library.
614615
*/
615616
public ActionUsage retrieveStandardDoneAction(Element eObject) {
616-
return this.findByName(eObject, "Actions::Action::done");
617+
return this.findByNameAndTypeInStandardLibraries(eObject, ActionUsage.class, "Actions::Action::done");
618+
}
619+
620+
private <T extends Element> T findByNameAndTypeInStandardLibraries(Element context, Class<T> klass, String qualifiedName) {
621+
return context.eResource().getResourceSet().getResources().stream()
622+
.flatMap(resource -> this.getLibraries(resource, true).stream())
623+
.flatMap(stdlibPackage -> Optional.ofNullable(this.findByName(stdlibPackage, qualifiedName)).stream())
624+
.filter(klass::isInstance)
625+
.map(klass::cast)
626+
.findFirst()
627+
.orElse(null);
617628
}
618629

619630
/**

doc/content/modules/user-manual/pages/release-notes/2026.3.0.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ It now follows the same rule than all other graphical node: if a compartment tha
3232
** Fix the `EnumerationDefinition` graphical node compartment name from `enumerations` to `enums`, to follow the SysMLv2 specification.
3333
** Fix the direct edit and the display of `ends` graphical node elements inside the _ends_ compartment.
3434
Now the _end_ keyword is not displayed anymore in the label of these graphical nodes, and the direct edit only allows to edit the name of the `end` element instead of the full label which was confusing for users.
35+
** Fix an error when invoking the tools _New Start Action_ or _New Done Action_ from inside a package named `Actions`.
3536

3637
* In textual import/export:
3738

0 commit comments

Comments
 (0)