Skip to content

Commit 458bcc5

Browse files
committed
[2111] Improve stakeholder creation tool using the latest selection dialog changes
Bug: #2111 Signed-off-by: Guillaume Coutable <guillaume.coutable@obeo.fr>
1 parent 75b6856 commit 458bcc5

7 files changed

Lines changed: 157 additions & 41 deletions

File tree

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ As a result, the following GraphQL mutations have been removed `exposeRequiremen
3030

3131
=== Improvements
3232

33+
- https://github.com/eclipse-syson/syson/issues/2111[#2111] [diagrams] Leverage the latest change of the selection dialog to allow creating a stakeholder without specialization.
3334

3435
=== New features
3536

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

Lines changed: 108 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
package org.eclipse.syson.application.controllers.diagrams.general.view;
1414

1515
import static org.assertj.core.api.Assertions.assertThat;
16+
import static org.assertj.core.api.InstanceOfAssertFactories.type;
1617
import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat;
1718
import static org.junit.jupiter.api.Assertions.assertEquals;
1819

@@ -56,6 +57,7 @@
5657
import org.eclipse.syson.standard.diagrams.view.SDVDescriptionNameGenerator;
5758
import org.eclipse.syson.sysml.Element;
5859
import org.eclipse.syson.sysml.PartUsage;
60+
import org.eclipse.syson.sysml.Specialization;
5961
import org.eclipse.syson.sysml.Subsetting;
6062
import org.eclipse.syson.sysml.SysmlPackage;
6163
import org.eclipse.syson.sysml.helper.EMFUtils;
@@ -79,6 +81,7 @@
7981
* @author arichard
8082
*/
8183
@Transactional
84+
@SuppressWarnings("checkstyle:MultipleStringLiterals")
8285
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
8386
public class GVSubNodeRequirementCreationTests extends AbstractIntegrationTests {
8487

@@ -1050,28 +1053,52 @@ public void createRequirementDefinitionChildNodes(EClass childEClass, String com
10501053
.verify(Duration.ofSeconds(10));
10511054
}
10521055

1056+
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
1057+
@Test
1058+
public void createNewStakeholderFromPartInConcernDefinition() {
1059+
this.createNewStakeholderSelectingExistingElementIn(SysmlPackage.eINSTANCE.getConcernDefinition(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CONCERN_DEFINITION_ID, "ConcernDefinition", GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID);
1060+
}
1061+
1062+
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
1063+
@Test
1064+
public void createNewStakeholderFromPartInConcernUsage() {
1065+
this.createNewStakeholderSelectingExistingElementIn(SysmlPackage.eINSTANCE.getConcernUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CONCERN_USAGE_ID, "concern", GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID);
1066+
}
1067+
1068+
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
1069+
@Test
1070+
public void createNewStakeholderFromPartInRequirementDefinition() {
1071+
this.createNewStakeholderSelectingExistingElementIn(SysmlPackage.eINSTANCE.getRequirementDefinition(), GeneralViewWithTopNodesTestProjectData.SemanticIds.REQUIREMENT_DEFINITION_ID, "RequirementDefinition", GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID);
1072+
}
1073+
1074+
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
1075+
@Test
1076+
public void createNewStakeholderFromPartInRequirementUsage() {
1077+
this.createNewStakeholderSelectingExistingElementIn(SysmlPackage.eINSTANCE.getRequirementUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.REQUIREMENT_USAGE_ID, "requirement", GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID);
1078+
}
1079+
10531080
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
10541081
@Test
10551082
public void createNewStakeholderInConcernDefinition() {
1056-
this.createNewStakeholderIn(SysmlPackage.eINSTANCE.getConcernDefinition(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CONCERN_DEFINITION_ID, "ConcernDefinition");
1083+
this.createNewStakeholderWithoutSelectionIn(SysmlPackage.eINSTANCE.getConcernDefinition(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CONCERN_DEFINITION_ID, "ConcernDefinition");
10571084
}
10581085

10591086
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
10601087
@Test
10611088
public void createNewStakeholderInConcernUsage() {
1062-
this.createNewStakeholderIn(SysmlPackage.eINSTANCE.getConcernUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CONCERN_USAGE_ID, "concern");
1089+
this.createNewStakeholderWithoutSelectionIn(SysmlPackage.eINSTANCE.getConcernUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CONCERN_USAGE_ID, "concern");
10631090
}
10641091

10651092
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
10661093
@Test
10671094
public void createNewStakeholderInRequirementDefinition() {
1068-
this.createNewStakeholderIn(SysmlPackage.eINSTANCE.getRequirementDefinition(), GeneralViewWithTopNodesTestProjectData.SemanticIds.REQUIREMENT_DEFINITION_ID, "RequirementDefinition");
1095+
this.createNewStakeholderWithoutSelectionIn(SysmlPackage.eINSTANCE.getRequirementDefinition(), GeneralViewWithTopNodesTestProjectData.SemanticIds.REQUIREMENT_DEFINITION_ID, "RequirementDefinition");
10691096
}
10701097

10711098
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
10721099
@Test
10731100
public void createNewStakeholderInRequirementUsage() {
1074-
this.createNewStakeholderIn(SysmlPackage.eINSTANCE.getRequirementUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.REQUIREMENT_USAGE_ID, "requirement");
1101+
this.createNewStakeholderWithoutSelectionIn(SysmlPackage.eINSTANCE.getRequirementUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.REQUIREMENT_USAGE_ID, "requirement");
10751102
}
10761103

10771104
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@@ -1086,7 +1113,7 @@ public void createNewActorInRequirementDefinition() {
10861113
this.createNewActorIn(SysmlPackage.eINSTANCE.getRequirementDefinition(), GeneralViewWithTopNodesTestProjectData.SemanticIds.REQUIREMENT_DEFINITION_ID, "RequirementDefinition");
10871114
}
10881115

1089-
private void createNewStakeholderIn(EClass eClassWithStakeholderParameter, String targetObjectId, String parentNodeLabel) {
1116+
private void createNewStakeholderSelectingExistingElementIn(EClass eClassWithStakeholderParameter, String targetObjectId, String parentNodeLabel, String existingElementId) {
10901117
var flux = this.givenSubscriptionToDiagram();
10911118

10921119
AtomicReference<Diagram> diagram = new AtomicReference<>();
@@ -1101,8 +1128,7 @@ private void createNewStakeholderIn(EClass eClassWithStakeholderParameter, Strin
11011128
.orElseGet(() -> Assertions.fail("No fitting EReference could be found in '%s'.".formatted(eClassWithStakeholderParameter.getName())));
11021129

11031130
final String stakeholderCreationToolName = "New Stakeholder";
1104-
Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, eClassWithStakeholderParameter, targetObjectId, stakeholderCreationToolName,
1105-
Stream.of(new ToolVariable("selectedObject", /* PartUsage 'part' */ "2c5fe5a5-18fe-40f4-ab66-a2d91ab7df6a", ToolVariableType.OBJECT_ID)).toList());
1131+
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, eClassWithStakeholderParameter, targetObjectId, stakeholderCreationToolName, existingElementId);
11061132

11071133
Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
11081134
var initialDiagram = diagram.get();
@@ -1117,29 +1143,89 @@ private void createNewStakeholderIn(EClass eClassWithStakeholderParameter, Strin
11171143
.check(initialDiagram, newDiagram);
11181144
});
11191145

1120-
final ISemanticChecker semanticChecker = (editingContext) -> {
1121-
final Element semanticRootElement = this.objectSearchService.getObject(editingContext, GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID).filter(Element.class::isInstance)
1122-
.map(Element.class::cast).orElseGet(() -> Assertions.fail("Could not find the expected root semantic object."));
1123-
final List<PartUsage> allStakeholderPartUsages = EMFUtils.allContainedObjectOfType(semanticRootElement, PartUsage.class)
1124-
.filter(element -> Objects.equals(element.getName(), "stakeholder1")).toList();
1125-
assertEquals(1, allStakeholderPartUsages.size());
1146+
Consumer<Object> additionalCheck = referencedObject -> {
1147+
assertThat(referencedObject).isInstanceOf(List.class)
1148+
.asInstanceOf(type(List.class))
1149+
.satisfies(stakeHolders -> {
1150+
assertThat(stakeHolders).size().isEqualTo(1);
1151+
assertThat(stakeHolders.getFirst())
1152+
.isInstanceOf(PartUsage.class)
1153+
.asInstanceOf(type(PartUsage.class))
1154+
.satisfies(stakeholderPartUsage -> {
1155+
final EList<Subsetting> subsettings = stakeholderPartUsage.getOwnedSubsetting();
1156+
assertEquals(1, subsettings.size());
1157+
assertThat(subsettings.get(0).getSubsettedFeature().getName()).isEqualTo("part");
1158+
});
1159+
});
1160+
};
11261161

1127-
final PartUsage stakeholderPartUsage = allStakeholderPartUsages.get(0);
1128-
final EList<Subsetting> subsettings = stakeholderPartUsage.getOwnedSubsetting();
1129-
assertEquals(1, subsettings.size());
1130-
assertThat(subsettings.get(0).getSubsettedFeature().getName()).isEqualTo("part");
1162+
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(
1163+
this.semanticCheckerService.getElementInParentSemanticChecker(parentNodeLabel, stakeholderParameterEReference, SysmlPackage.eINSTANCE.getPartUsage(), additionalCheck));
1164+
1165+
StepVerifier.create(flux)
1166+
.consumeNextWith(initialDiagramContentConsumer)
1167+
.then(createNodeRunnable)
1168+
.consumeNextWith(diagramCheck)
1169+
.then(semanticCheck)
1170+
.thenCancel()
1171+
.verify(Duration.ofSeconds(10));
1172+
}
1173+
1174+
private void createNewStakeholderWithoutSelectionIn(EClass eClassWithStakeholderParameter, String targetObjectId, String parentNodeLabel) {
1175+
var flux = this.givenSubscriptionToDiagram();
1176+
1177+
AtomicReference<Diagram> diagram = new AtomicReference<>();
1178+
Consumer<Object> initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram::set);
1179+
1180+
var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
1181+
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
1182+
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);
1183+
1184+
final EReference stakeholderParameterEReference = eClassWithStakeholderParameter.getEAllReferences().stream()
1185+
.filter(eReference -> eReference.getName().equals("stakeholderParameter") && eReference.getEType() == SysmlPackage.eINSTANCE.getPartUsage()).findFirst()
1186+
.orElseGet(() -> Assertions.fail("No fitting EReference could be found in '%s'.".formatted(eClassWithStakeholderParameter.getName())));
1187+
1188+
final String stakeholderCreationToolName = "New Stakeholder";
1189+
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithoutSelectionProvided(diagramDescriptionIdProvider, diagram, eClassWithStakeholderParameter, targetObjectId, stakeholderCreationToolName);
1190+
1191+
Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
1192+
var initialDiagram = diagram.get();
1193+
new CheckDiagramElementCount(this.diagramComparator)
1194+
.hasNewNodeCount(1)
1195+
.check(initialDiagram, newDiagram);
1196+
new CheckNodeInCompartment(diagramDescriptionIdProvider, this.diagramComparator)
1197+
.withTargetObjectId(targetObjectId)
1198+
.withCompartmentName("stakeholders")
1199+
.hasNodeDescriptionName(this.descriptionNameGenerator.getCompartmentItemName(eClassWithStakeholderParameter, stakeholderParameterEReference))
1200+
.hasCompartmentCount(0)
1201+
.check(initialDiagram, newDiagram);
1202+
});
1203+
1204+
Consumer<Object> additionalCheck = referencedObject -> {
1205+
assertThat(referencedObject).isInstanceOf(List.class)
1206+
.asInstanceOf(type(List.class))
1207+
.satisfies(stakeHolders -> {
1208+
assertThat(stakeHolders).size().isEqualTo(1);
1209+
assertThat(stakeHolders.getFirst())
1210+
.isInstanceOf(PartUsage.class)
1211+
.asInstanceOf(type(PartUsage.class))
1212+
.satisfies(stakeholderPartUsage -> {
1213+
assertThat(stakeholderPartUsage.getOwnedSpecialization()).allMatch(Specialization::isIsImplied);
1214+
assertThat(stakeholderPartUsage.getType())
1215+
.isNotEmpty()
1216+
.allMatch(Element::isIsLibraryElement);
1217+
});
1218+
});
11311219
};
11321220

1133-
Runnable semanticCheck1 = this.semanticCheckerService.checkEditingContext(
1134-
this.semanticCheckerService.getElementInParentSemanticChecker(parentNodeLabel, stakeholderParameterEReference, SysmlPackage.eINSTANCE.getPartUsage()));
1135-
Runnable semanticCheck2 = this.semanticCheckerService.checkEditingContext(semanticChecker);
1221+
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(
1222+
this.semanticCheckerService.getElementInParentSemanticChecker(parentNodeLabel, stakeholderParameterEReference, SysmlPackage.eINSTANCE.getPartUsage(), additionalCheck));
11361223

11371224
StepVerifier.create(flux)
11381225
.consumeNextWith(initialDiagramContentConsumer)
11391226
.then(createNodeRunnable)
11401227
.consumeNextWith(diagramCheck)
1141-
.then(semanticCheck1)
1142-
.then(semanticCheck2)
1228+
.then(semanticCheck)
11431229
.thenCancel()
11441230
.verify(Duration.ofSeconds(10));
11451231
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public void createTimesliceNodeOn(EClass parentEClass, String parentTargetObject
150150
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);
151151

152152

153-
Runnable createNodeRunnable = creationTestsService.createNodeWithSelectionDialog(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Timeslice", selectedObject);
153+
Runnable createNodeRunnable = creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Timeslice", selectedObject);
154154
// The created child EClass depends on the behavior of the selection dialog, here without selection
155155
Consumer<Object> diagramChecker = diagramCheckerService.siblingNodeGraphicalChecker(diagram, diagramDescriptionIdProvider, childEClass, newCompartmentCount, newNodeCount);
156156
Consumer<Object> additionalSemanticCheck = object -> {
@@ -194,7 +194,7 @@ public void createSnapshotNodeOn(EClass parentEClass, String parentTargetObjectI
194194
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
195195
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);
196196

197-
Runnable createNodeRunnable = creationTestsService.createNodeWithSelectionDialog(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Snapshot", selectedObject);
197+
Runnable createNodeRunnable = creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Snapshot", selectedObject);
198198
// The created child EClass depends on the behavior of the selection dialog, here without selection
199199
Consumer<Object> diagramChecker = diagramCheckerService.siblingNodeGraphicalChecker(diagram, diagramDescriptionIdProvider, childEClass, newCompartmentCount, newNodeCount);
200200
Consumer<Object> additionalSemanticCheck = object -> {

backend/application/syson-application/src/test/java/org/eclipse/syson/services/diagrams/NodeCreationTestsService.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ public Runnable createNode(DiagramDescriptionIdProvider diagramDescriptionIdProv
107107
/**
108108
* Creates a runnable that invokes a named node creation tool.
109109
*
110+
* <p>It behaves as if the selection dialog was called without any selection provided.</p>
111+
*
110112
* @param diagramDescriptionIdProvider
111113
* the diagram description ID provider
112114
* @param diagram
@@ -117,15 +119,34 @@ public Runnable createNode(DiagramDescriptionIdProvider diagramDescriptionIdProv
117119
* the ID of the element on which apply the tool
118120
* @param toolName
119121
* the name of the creation tool
120-
* @param selectedObject
121-
* the object ID selected in the selection dialog.
122-
* Most of the time the ID is computed thanks to {@link org.eclipse.sirius.components.core.api.IIdentityService#getId(Object)}.
123-
* Provide an empty string if the selection in the selection dialog is optional and you do not want to provide a selection.
124122
* @return a runnable that performs the node creation
123+
*/
124+
public Runnable createNodeWithSelectionDialogWithoutSelectionProvided(DiagramDescriptionIdProvider diagramDescriptionIdProvider,
125+
AtomicReference<Diagram> diagram, EClass parentEClass, String targetObjectId, String toolName) {
126+
return this.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, parentEClass, targetObjectId, toolName, "");
127+
}
128+
129+
/**
130+
* Creates a runnable that invokes a named node creation tool.
131+
*
132+
* <p>It behaves as if the selection dialog was called, and a single selection has been provided.</p>
125133
*
126-
* @see org.eclipse.sirius.components.view.emf.diagram.SelectionDialogDescriptionConverter
134+
* @param diagramDescriptionIdProvider
135+
* the diagram description ID provider
136+
* @param diagram
137+
* the diagram reference
138+
* @param parentEClass
139+
* the EClass of the parent node
140+
* @param targetObjectId
141+
* the ID of the element on which apply the tool
142+
* @param toolName
143+
* the name of the creation tool
144+
* @param selectedObject
145+
* the object id selected in the selection dialog.
146+
* Put an empty string if the selection is optional and you want the behavior without selection
147+
* @return a runnable that performs the node creation
127148
*/
128-
public Runnable createNodeWithSelectionDialog(DiagramDescriptionIdProvider diagramDescriptionIdProvider,
149+
public Runnable createNodeWithSelectionDialogWithSingleSelection(DiagramDescriptionIdProvider diagramDescriptionIdProvider,
129150
AtomicReference<Diagram> diagram, EClass parentEClass, String targetObjectId, String toolName, String selectedObject) {
130151
return this.createNode(diagramDescriptionIdProvider, diagram, parentEClass, targetObjectId, toolName, List.of(new ToolVariable("selectedObject", selectedObject, ToolVariableType.OBJECT_ID)));
131152
}

0 commit comments

Comments
 (0)