Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
- https://github.com/eclipse-syson/syson/issues/2198[#2198] [diagrams] Improve diagram-to-diagram drag and drop to support dropping multiple graphical nodes at once, leveraging Sirius Web's `droppedNodes` and `droppedElements` variables.
- https://github.com/eclipse-syson/syson/issues/2194[#2194] [diagrams] Properly report feedback messages to user when using _ISysMLMoveElementService_.
- https://github.com/eclipse-syson/syson/issues/2182[#2182] [services] Provide a way for downstream applications to extend _ISysMLMoveElementService_;
- https://github.com/eclipse-syson/syson/issues/2240[#2240] [diagrams] Update the choice of _timeslice_ and _snapshot_ elements that can be created in the selection dialog of tools creating _timeslice_ and _snapshot_ elements.
Before, the selection dialog option with selection allowed choosing between all _timeslice/snapshot_ types.
Now, the choice is restricted to the _timeslice/snapshot_ type that match the graphical node type on which the tool is applied.


=== New features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.type;
import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat;
import static org.eclipse.sirius.components.trees.tests.TreeEventPayloadConsumer.assertRefreshedTreeThat;

import com.jayway.jsonpath.JsonPath;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
Expand All @@ -26,11 +32,16 @@
import org.eclipse.emf.ecore.EClass;
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
import org.eclipse.sirius.components.collaborative.selection.dto.SelectionDialogTreeEventInput;
import org.eclipse.sirius.components.core.api.IIdentityService;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.diagrams.Diagram;
import org.eclipse.sirius.components.diagrams.tests.graphql.PaletteQueryRunner;
import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider;
import org.eclipse.sirius.web.tests.graphql.SelectionDialogDescriptionQueryRunner;
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
import org.eclipse.sirius.web.tests.services.representation.RepresentationIdBuilder;
import org.eclipse.sirius.web.tests.services.selection.SelectionDialogTreeEventSubscriptionRunner;
import org.eclipse.syson.AbstractIntegrationTests;
import org.eclipse.syson.GivenSysONServer;
import org.eclipse.syson.application.controller.editingcontext.checkers.SemanticCheckerService;
Expand Down Expand Up @@ -68,6 +79,7 @@
*/
@Transactional
@SuppressWarnings("checkstyle:MultipleStringLiterals")
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GVTimesliceSnapshotNodeCreationTests extends AbstractIntegrationTests {

Expand Down Expand Up @@ -98,8 +110,24 @@ public class GVTimesliceSnapshotNodeCreationTests extends AbstractIntegrationTes
@Autowired
private IIdentityService identityService;

@Autowired
private PaletteQueryRunner paletteQueryRunner;

@Autowired
private SelectionDialogDescriptionQueryRunner selectionDialogDescriptionQueryRunner;

@Autowired
private RepresentationIdBuilder representationIdBuilder;

@Autowired
private SelectionDialogTreeEventSubscriptionRunner selectionDialogTreeEventSubscriptionRunner;

private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator();

private NodeCreationTestsService creationTestsService;

private SemanticCheckerService semanticCheckerService;

private Flux<DiagramRefreshedEventPayload> givenSubscriptionToDiagram(String editingContextId, String diagramId) {
var diagramEventInput = new DiagramEventInput(UUID.randomUUID(), editingContextId, diagramId);
return this.givenDiagramSubscription.subscribe(diagramEventInput);
Expand All @@ -122,18 +150,27 @@ private static Stream<Arguments> portionKingNodeParameters() {
).map(TestNameGenerator::namedArguments);
}

private static Stream<Arguments> portionKindSelectionDialogTreeParameters() {
return Stream.of(
Arguments.of(SysmlPackage.eINSTANCE.getAllocationUsage(), GeneralViewWithTopNodesTestProjectData.GraphicalIds.ALLOCATION_USAGE_ID, GeneralViewWithTopNodesTestProjectData.SemanticIds.ALLOCATION_USAGE_ID),
Arguments.of(SysmlPackage.eINSTANCE.getInterfaceUsage(), GeneralViewWithTopNodesTestProjectData.GraphicalIds.INTERFACE_USAGE_ID, GeneralViewWithTopNodesTestProjectData.SemanticIds.INTERFACE_USAGE_ID),
Arguments.of(SysmlPackage.eINSTANCE.getItemUsage(), GeneralViewWithTopNodesTestProjectData.GraphicalIds.ITEM_USAGE_ID, GeneralViewWithTopNodesTestProjectData.SemanticIds.ITEM_USAGE_ID),
Arguments.of(SysmlPackage.eINSTANCE.getOccurrenceUsage(), GeneralViewWithTopNodesTestProjectData.GraphicalIds.OCCURRENCE_USAGE_ID, GeneralViewWithTopNodesTestProjectData.SemanticIds.OCCURRENCE_USAGE_ID),
Arguments.of(SysmlPackage.eINSTANCE.getPartUsage(), GeneralViewWithTopNodesTestProjectData.GraphicalIds.PART_USAGE_ID, GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID)
).map(TestNameGenerator::namedArguments);
};

@BeforeEach
public void setUp() {
this.givenInitialServerState.initialize();
this.creationTestsService = new NodeCreationTestsService(this.nodeCreationTester, this.descriptionNameGenerator, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID);
this.semanticCheckerService = new SemanticCheckerService(this.semanticRunnableFactory, this.objectSearchService, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID);
}

@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@ParameterizedTest()
@MethodSource("portionKingNodeParameters")
public void createTimesliceNodeOn(EClass parentEClass, String parentTargetObjectId, String parentLabel, int newCompartmentCount, int newNodeCount, boolean provideSelection, EClass childEClass) {
var creationTestsService = new NodeCreationTestsService(this.nodeCreationTester, this.descriptionNameGenerator, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID);
var semanticCheckerService = new SemanticCheckerService(this.semanticRunnableFactory, this.objectSearchService, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID);
var diagramCheckerService = new DiagramCheckerService(this.diagramComparator, this.descriptionNameGenerator);
String selectedObject = "";
if (provideSelection) {
Expand All @@ -150,7 +187,7 @@ public void createTimesliceNodeOn(EClass parentEClass, String parentTargetObject
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);


Runnable createNodeRunnable = creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Timeslice", selectedObject);
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Timeslice", selectedObject);
// The created child EClass depends on the behavior of the selection dialog, here without selection
Consumer<Object> diagramChecker = diagramCheckerService.siblingNodeGraphicalChecker(diagram, diagramDescriptionIdProvider, childEClass, newCompartmentCount, newNodeCount);
Consumer<Object> additionalSemanticCheck = object -> {
Expand All @@ -162,7 +199,7 @@ public void createTimesliceNodeOn(EClass parentEClass, String parentTargetObject
});
}
};
Runnable semanticCheck = semanticCheckerService.checkEditingContext(semanticCheckerService.getElementInParentSemanticChecker(parentLabel, SysmlPackage.eINSTANCE.getUsage_NestedUsage(), SysmlPackage.eINSTANCE.getOccurrenceUsage(), additionalSemanticCheck));
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, SysmlPackage.eINSTANCE.getUsage_NestedUsage(), SysmlPackage.eINSTANCE.getOccurrenceUsage(), additionalSemanticCheck));
StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(createNodeRunnable)
Expand All @@ -172,13 +209,9 @@ public void createTimesliceNodeOn(EClass parentEClass, String parentTargetObject
.verify(Duration.ofSeconds(10));
}

@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@ParameterizedTest()
@MethodSource("portionKingNodeParameters")
public void createSnapshotNodeOn(EClass parentEClass, String parentTargetObjectId, String parentLabel, int newCompartmentCount, int newNodeCount, boolean provideSelection, EClass childEClass) {
var creationTestsService = new NodeCreationTestsService(this.nodeCreationTester, this.descriptionNameGenerator, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID);
var semanticCheckerService = new SemanticCheckerService(this.semanticRunnableFactory, this.objectSearchService, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID);
var diagramCheckerService = new DiagramCheckerService(this.diagramComparator, this.descriptionNameGenerator);
String selectedObject = "";
if (provideSelection) {
Expand All @@ -194,7 +227,7 @@ public void createSnapshotNodeOn(EClass parentEClass, String parentTargetObjectI
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);

Runnable createNodeRunnable = creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Snapshot", selectedObject);
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, parentEClass, parentTargetObjectId, "New Snapshot", selectedObject);
// The created child EClass depends on the behavior of the selection dialog, here without selection
Consumer<Object> diagramChecker = diagramCheckerService.siblingNodeGraphicalChecker(diagram, diagramDescriptionIdProvider, childEClass, newCompartmentCount, newNodeCount);
Consumer<Object> additionalSemanticCheck = object -> {
Expand All @@ -206,7 +239,7 @@ public void createSnapshotNodeOn(EClass parentEClass, String parentTargetObjectI
});
}
};
Runnable semanticCheck = semanticCheckerService.checkEditingContext(semanticCheckerService.getElementInParentSemanticChecker(parentLabel, SysmlPackage.eINSTANCE.getUsage_NestedUsage(), SysmlPackage.eINSTANCE.getOccurrenceUsage(), additionalSemanticCheck));
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, SysmlPackage.eINSTANCE.getUsage_NestedUsage(), SysmlPackage.eINSTANCE.getOccurrenceUsage(), additionalSemanticCheck));
StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(createNodeRunnable)
Expand All @@ -216,4 +249,87 @@ public void createSnapshotNodeOn(EClass parentEClass, String parentTargetObjectI
.verify(Duration.ofSeconds(10));
}

@ParameterizedTest
@MethodSource("portionKindSelectionDialogTreeParameters")
public void testCheckAvailableElementsInTimesliceSelectionDialog(EClass elementClass, String graphicalId, String semanticId) {
var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);

String toolId = diagramDescriptionIdProvider.getNodeToolId(this.descriptionNameGenerator.getNodeName(elementClass), "New Timeslice");
var treeRepresentationId = this.getSelectionDialogTreeDescriptionId(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, GeneralViewWithTopNodesTestProjectData.GraphicalIds.DIAGRAM_ID, toolId, graphicalId, semanticId);
var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, treeRepresentationId);
var flux = this.selectionDialogTreeEventSubscriptionRunner.run(input).flux();

Consumer<Object> initialTreeContentConsumer = assertRefreshedTreeThat(tree -> {
assertThat(tree).isNotNull();
assertThat(tree.getChildren()).size().isEqualTo(1);
assertThat(tree.getChildren().getFirst().getId()).isEqualTo(identityService.getId(elementClass));
});

StepVerifier.create(flux)
.consumeNextWith(initialTreeContentConsumer)
.thenCancel()
.verify(Duration.ofSeconds(10));
}

@ParameterizedTest
@MethodSource("portionKindSelectionDialogTreeParameters")
public void testCheckAvailableElementsInSnapshotSelectionDialog(EClass elementClass, String graphicalId, String semanticId) {
var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);

String toolId = diagramDescriptionIdProvider.getNodeToolId(this.descriptionNameGenerator.getNodeName(elementClass), "New Snapshot");
var treeRepresentationId = this.getSelectionDialogTreeDescriptionId(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, GeneralViewWithTopNodesTestProjectData.GraphicalIds.DIAGRAM_ID, toolId, graphicalId, semanticId);
var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, treeRepresentationId);
var flux = this.selectionDialogTreeEventSubscriptionRunner.run(input).flux();

Consumer<Object> initialTreeContentConsumer = assertRefreshedTreeThat(tree -> {
assertThat(tree).isNotNull();
assertThat(tree.getChildren()).size().isEqualTo(1);
assertThat(tree.getChildren().getFirst().getId()).isEqualTo(identityService.getId(elementClass));
});

StepVerifier.create(flux)
.consumeNextWith(initialTreeContentConsumer)
.thenCancel()
.verify(Duration.ofSeconds(10));
}

private String getSelectionDialogTreeDescriptionId(String editingContextId, String representationId, String toolId, String graphicalId, String semanticId) {

// Retrieve the dialog description of the given tool
Map<String, Object> paletteQueryVariables = Map.of(
"editingContextId", editingContextId,
"representationId", representationId,
"diagramElementIds", List.of(graphicalId)
);
var paletteQueryResult = this.paletteQueryRunner.run(paletteQueryVariables);
assertThat(paletteQueryResult.errors()).isEmpty();

List<String> toolDialogDescriptionIds = JsonPath.read(paletteQueryResult.data(), "data.viewer.editingContext.representation.description.palette.paletteEntries..tools[?(@.id == '" + toolId + "')].dialogDescriptionId");
assertThat(toolDialogDescriptionIds).size().isEqualTo(1);

// From the dialog description, retrieve the tree selection id
String selectionDialogRepresentationId = "selectionDialog://?representationDescription=" + URLEncoder.encode(toolDialogDescriptionIds.getFirst(), StandardCharsets.UTF_8);
List<Map<String, Object>> variablesParameter = List.of(
Map.of(
"name", "targetObjectId",
"value", semanticId
)
);
Map<String, Object> selectionDialogDescriptionQueryVariables = Map.of(
"editingContextId", editingContextId,
"representationId", selectionDialogRepresentationId,
"variables", variablesParameter
);
var selectionDialogDescriptionQueryResult = this.selectionDialogDescriptionQueryRunner.run(selectionDialogDescriptionQueryVariables);
assertThat(selectionDialogDescriptionQueryResult.errors()).isEmpty();

String treeSelectionId = JsonPath.read(selectionDialogDescriptionQueryResult.data(), "data.viewer.editingContext.representation.description.treeDescription.id");
assertThat(treeSelectionId).isNotBlank();

return this.representationIdBuilder.buildSelectionRepresentationId(treeSelectionId, semanticId, List.of());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public static class GraphicalIds {

public static final String ACTION_USAGE_ID = "61aaf64a-4fbc-356e-ba73-4bd47b386989";

public static final String ALLOCATION_USAGE_ID = "361506fb-2a1d-3edc-be2d-8cd60a235f53";

public static final String ATTRIBUTE_USAGE_ID = "7b8e6835-c563-35cd-8991-e2f894fc2139";

public static final String CONCERN_USAGE_ID = "0999b8c3-d37c-3644-a1d6-b9777a499d11";
Expand All @@ -38,16 +40,22 @@ public static class GraphicalIds {

public static final String ITEM_DEFINITION_ID = "df3542d9-6314-3da5-993c-a296f4042674";

public static final String PART_USAGE_ID = "4c4fe0d5-4974-377e-9113-9ab022c75f8c";
public static final String ITEM_USAGE_ID = "78a84b8a-e91c-3338-b447-864793773dd9";

public static final String INTERFACE_USAGE_ID = "6bc0765c-4f9f-3a9e-ab45-3d717519535c";

public static final String PART_DEFINITION_ID = "fa617798-658e-3812-92f2-52e2fc39f851";

public static final String PART_DEFINITION_TEXTUAL_REP_ID = "3a992e49-95fa-384a-bb54-47284825bf17";

public static final String REQUIREMENT_USAGE_ID = "3eea9d01-7033-3f31-b7ef-561b5bc86d10";
public static final String PART_USAGE_ID = "4c4fe0d5-4974-377e-9113-9ab022c75f8c";

public static final String OCCURRENCE_USAGE_ID = "47653014-87d1-3dc6-856b-72454aa93154";

public static final String REQUIREMENT_DEFINITION_ID = "b83f2b54-1602-382d-beb1-c500e08a8684";

public static final String REQUIREMENT_USAGE_ID = "3eea9d01-7033-3f31-b7ef-561b5bc86d10";

public static final String STATE_USAGE_ID = "1541c013-2cc7-3dd7-a39f-6e33d07b411e";
}

Expand Down
Loading
Loading