Skip to content

Commit e834485

Browse files
committed
[2013] Add a tool to create and setup a FlowUsage on a ConnectionUsage
Bug: #2013 Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
1 parent 628a9e0 commit e834485

13 files changed

Lines changed: 480 additions & 4 deletions

File tree

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

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,33 @@
1717
import static org.eclipse.sirius.components.diagrams.tests.assertions.DiagramAssertions.assertThat;
1818
import static org.eclipse.sirius.components.diagrams.tests.assertions.DiagramInstanceOfAssertFactories.EDGE_STYLE;
1919

20+
import com.jayway.jsonpath.JsonPath;
21+
2022
import java.time.Duration;
23+
import java.util.List;
2124
import java.util.UUID;
2225
import java.util.concurrent.atomic.AtomicReference;
2326
import java.util.function.Consumer;
2427

2528
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
2629
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
30+
import org.eclipse.sirius.components.collaborative.diagrams.dto.EditLabelInput;
31+
import org.eclipse.sirius.components.collaborative.diagrams.dto.EditLabelSuccessPayload;
32+
import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolInput;
33+
import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolSuccessPayload;
34+
import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariable;
35+
import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariableType;
2736
import org.eclipse.sirius.components.core.api.IIdentityService;
2837
import org.eclipse.sirius.components.core.api.IObjectSearchService;
2938
import org.eclipse.sirius.components.diagrams.ArrowStyle;
3039
import org.eclipse.sirius.components.diagrams.Diagram;
3140
import org.eclipse.sirius.components.diagrams.Edge;
3241
import org.eclipse.sirius.components.diagrams.events.ReconnectEdgeKind;
3342
import org.eclipse.sirius.components.diagrams.tests.assertions.DiagramAssertions;
43+
import org.eclipse.sirius.components.diagrams.tests.graphql.EditLabelMutationRunner;
44+
import org.eclipse.sirius.components.diagrams.tests.graphql.InvokeSingleClickOnDiagramElementToolMutationRunner;
45+
import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator;
46+
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionSuccessPayload;
3447
import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider;
3548
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
3649
import org.eclipse.syson.AbstractIntegrationTests;
@@ -40,13 +53,18 @@
4053
import org.eclipse.syson.application.controllers.diagrams.testers.EdgeCreationTester;
4154
import org.eclipse.syson.application.controllers.diagrams.testers.EdgeReconnectionTester;
4255
import org.eclipse.syson.application.data.GeneralViewFlowConnectionItemUsagesProjectData;
56+
import org.eclipse.syson.application.data.GeneralViewFlowUsageProjectData;
4357
import org.eclipse.syson.services.SemanticRunnableFactory;
4458
import org.eclipse.syson.services.diagrams.DiagramComparator;
4559
import org.eclipse.syson.services.diagrams.DiagramDescriptionIdProvider;
4660
import org.eclipse.syson.services.diagrams.api.IGivenDiagramDescription;
4761
import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription;
4862
import org.eclipse.syson.standard.diagrams.view.SDVDescriptionNameGenerator;
63+
import org.eclipse.syson.sysml.ConnectionUsage;
64+
import org.eclipse.syson.sysml.FeatureTyping;
65+
import org.eclipse.syson.sysml.FlowEnd;
4966
import org.eclipse.syson.sysml.FlowUsage;
67+
import org.eclipse.syson.sysml.PayloadFeature;
5068
import org.eclipse.syson.sysml.SysmlPackage;
5169
import org.eclipse.syson.util.IDescriptionNameGenerator;
5270
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
@@ -86,6 +104,12 @@ public class GVFlowUsageTests extends AbstractIntegrationTests {
86104
@Autowired
87105
private EdgeCreationTester edgeCreationTester;
88106

107+
@Autowired
108+
private EditLabelMutationRunner editLabelMutationRunner;
109+
110+
@Autowired
111+
private InvokeSingleClickOnDiagramElementToolMutationRunner invokeSingleClickOnDiagramElementToolMutationRunner;
112+
89113
@Autowired
90114
private DiagramComparator diagramComparator;
91115

@@ -297,4 +321,115 @@ public void reconnectFlowUsageSource() {
297321
.verify(Duration.ofSeconds(10));
298322
}
299323

324+
@Test
325+
@DisplayName("GIVEN a connection WHEN we create a flow usage in it THEN the flow is correctly setup")
326+
@GivenSysONServer({ GeneralViewFlowUsageProjectData.SCRIPT_PATH })
327+
public void createFlowUsageInConnection() {
328+
var diagramEventInput = new DiagramEventInput(UUID.randomUUID(),
329+
GeneralViewFlowUsageProjectData.EDITING_CONTEXT_ID,
330+
GeneralViewFlowUsageProjectData.GraphicalIds.DIAGRAM_ID);
331+
332+
var flux = this.givenDiagramSubscription.subscribe(diagramEventInput);
333+
334+
var diagramId = new AtomicReference<String>();
335+
var connectionEdgeId = new AtomicReference<String>();
336+
var connectionEdgeLabelId = new AtomicReference<String>();
337+
338+
var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewFlowUsageProjectData.EDITING_CONTEXT_ID,
339+
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
340+
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);
341+
String flowCreationToolId = diagramDescriptionIdProvider.getNodeCreationToolIdOnEdge(this.descriptionNameGenerator.getEdgeName(SysmlPackage.eINSTANCE.getConnectionUsage()), "New Flow");
342+
343+
Consumer<Object> initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> {
344+
diagramId.set(diagram.getId());
345+
var connectionEdge = new DiagramNavigator(diagram).edgeWithId(GeneralViewFlowUsageProjectData.GraphicalIds.CONNECTION_EDGE_ID).getEdge();
346+
connectionEdgeId.set(connectionEdge.getId());
347+
connectionEdgeLabelId.set(connectionEdge.getCenterLabel().id());
348+
});
349+
350+
Runnable renameAndTypeTheConnection = () -> {
351+
var input = new EditLabelInput(UUID.randomUUID(), GeneralViewFlowUsageProjectData.EDITING_CONTEXT_ID, diagramId.get(), connectionEdgeLabelId.get(), "cable : HDMICable");
352+
var result = this.editLabelMutationRunner.run(input);
353+
354+
String typename = JsonPath.read(result.data(), "$.data.editLabel.__typename");
355+
assertThat(typename).isEqualTo(EditLabelSuccessPayload.class.getSimpleName());
356+
List<String> messages = JsonPath.read(result.data(), "$.data.editLabel.messages[*].body");
357+
assertThat(messages).hasSize(0);
358+
};
359+
360+
Consumer<Object> validateLabelEditResult = assertRefreshedDiagramThat(diagram -> {
361+
var edge = new DiagramNavigator(diagram).edgeWithId(connectionEdgeId.get()).getEdge();
362+
DiagramAssertions.assertThat(edge.getCenterLabel()).hasText("cable : HDMICable");
363+
});
364+
365+
Runnable validateSemanticEffectOfLabelEdit = this.semanticRunnableFactory.createRunnable(GeneralViewFlowUsageProjectData.EDITING_CONTEXT_ID,
366+
(editingContext, executeEditingContextFunctionInput) -> {
367+
var optionalConnection = this.objectSearchService.getObject(editingContext, GeneralViewFlowUsageProjectData.SemanticIds.CONNECT_ID);
368+
assertThat(optionalConnection).containsInstanceOf(ConnectionUsage.class);
369+
ConnectionUsage connection = (ConnectionUsage) optionalConnection.get();
370+
assertThat(connection.getType()).hasSize(1);
371+
var connectionType = connection.getType().get(0);
372+
var connectionTypeId = this.identityService.getId(connectionType);
373+
assertThat(connectionTypeId).isEqualTo(GeneralViewFlowUsageProjectData.SemanticIds.HDMI_CABLE_ID);
374+
return new ExecuteEditingContextFunctionSuccessPayload(executeEditingContextFunctionInput.id(), true);
375+
});
376+
377+
Runnable createFlowUsageOnConnection = () -> {
378+
var selectedObjectVariable = new ToolVariable("selectedObject", GeneralViewFlowUsageProjectData.SemanticIds.VIDEO_SIGNAL_ID, ToolVariableType.OBJECT_ID);
379+
var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), GeneralViewFlowUsageProjectData.EDITING_CONTEXT_ID, diagramId.get(), List.of(connectionEdgeId.get()),
380+
flowCreationToolId, 0, 0,
381+
List.of(selectedObjectVariable));
382+
var result = this.invokeSingleClickOnDiagramElementToolMutationRunner.run(input);
383+
String typename = JsonPath.read(result.data(), "$.data.invokeSingleClickOnDiagramElementTool.__typename");
384+
assertThat(typename).isEqualTo(InvokeSingleClickOnDiagramElementToolSuccessPayload.class.getSimpleName());
385+
List<String> messages = JsonPath.read(result.data(), "$.data.invokeSingleClickOnDiagramElementTool.messages[*].body");
386+
assertThat(messages).hasSize(0);
387+
};
388+
389+
Consumer<Object> validateEffectOnLabel = assertRefreshedDiagramThat(diagram -> {
390+
var edge = new DiagramNavigator(diagram).edgeWithId(connectionEdgeId.get()).getEdge();
391+
DiagramAssertions.assertThat(edge.getCenterLabel()).hasText("cable : HDMICable \u25b6 Flow");
392+
});
393+
394+
Runnable validateSemanticEffectOfFlowCreation = this.semanticRunnableFactory.createRunnable(GeneralViewFlowUsageProjectData.EDITING_CONTEXT_ID,
395+
(editingContext, executeEditingContextFunctionInput) -> {
396+
var optionalConnection = this.objectSearchService.getObject(editingContext, GeneralViewFlowUsageProjectData.SemanticIds.CONNECT_ID);
397+
assertThat(optionalConnection).containsInstanceOf(ConnectionUsage.class);
398+
ConnectionUsage connection = (ConnectionUsage) optionalConnection.get();
399+
// The flow usage has been created
400+
var optionalFlowUsage = connection.getOwnedFeature().stream().filter(FlowUsage.class::isInstance).map(FlowUsage.class::cast).findFirst();
401+
assertThat(optionalFlowUsage).isPresent();
402+
var flowUsage = optionalFlowUsage.get();
403+
404+
// The flow has a FeatureMembership with a PayloadFeature typed by "Video Signal" (the passed
405+
// payload)
406+
var optionalPayloadFeature = flowUsage.getOwnedFeature().stream().filter(PayloadFeature.class::isInstance).map(PayloadFeature.class::cast).findFirst();
407+
assertThat(optionalPayloadFeature).isPresent();
408+
var payloadFeature = optionalPayloadFeature.get();
409+
var payloadType = ((FeatureTyping) payloadFeature.getOwnedRelationship().get(0)).getType();
410+
assertThat(this.identityService.getId(payloadType)).isEqualTo(GeneralViewFlowUsageProjectData.SemanticIds.VIDEO_SIGNAL_ID);
411+
412+
// The flow has two FlowEnds: one redefining HDMICable::inputSide, the other HDMICable::outputSide
413+
var flowEnds = flowUsage.getOwnedFeature().stream().filter(FlowEnd.class::isInstance).map(FlowEnd.class::cast).toList();
414+
assertThat(flowEnds).hasSize(2);
415+
var sourceEnd = flowEnds.get(0);
416+
assertThat(sourceEnd.getOwnedFeature().get(0).getOwnedRedefinition().get(0).getRedefinedFeature().getQualifiedName()).isEqualTo("Package1::HDMICable::inputSide");
417+
var targetEnd = flowEnds.get(1);
418+
assertThat(targetEnd.getOwnedFeature().get(0).getOwnedRedefinition().get(0).getRedefinedFeature().getQualifiedName()).isEqualTo("Package1::HDMICable::outputSide");
419+
return new ExecuteEditingContextFunctionSuccessPayload(executeEditingContextFunctionInput.id(), true);
420+
});
421+
422+
StepVerifier.create(flux)
423+
.consumeNextWith(initialDiagramContentConsumer)
424+
.then(renameAndTypeTheConnection)
425+
.consumeNextWith(validateLabelEditResult)
426+
.then(validateSemanticEffectOfLabelEdit)
427+
.then(createFlowUsageOnConnection)
428+
.consumeNextWith(validateEffectOnLabel)
429+
.then(validateSemanticEffectOfFlowCreation)
430+
.thenCancel()
431+
.verify(Duration.ofSeconds(10_000));
432+
}
433+
300434
}
435+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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.data;
14+
15+
/**
16+
* Ids for project "GeneralView-FlowUsage".
17+
*
18+
* @author pcdavid
19+
*/
20+
public class GeneralViewFlowUsageProjectData {
21+
public static final String EDITING_CONTEXT_ID = "4b2c5775-0728-4b12-a520-89a8f2b90041";
22+
23+
public static final String SCRIPT_PATH = "/scripts/database-content/GeneralView-FlowUsage.sql";
24+
25+
/**
26+
* Ids of the graphical elements elements.
27+
*/
28+
public static final class GraphicalIds {
29+
public static final String DIAGRAM_ID = "2a1b62cf-36ea-41d2-8433-8ff781b3f4e5";
30+
31+
public static final String CONNECTION_EDGE_ID = "7f3367d5-a200-339b-820a-2408e5b82c84";
32+
}
33+
34+
/**
35+
* Ids of the semantic elements.
36+
*/
37+
public static final class SemanticIds {
38+
public static final String CONNECT_ID = "1604e1d8-1e30-44fb-a147-9f50f660f803";
39+
40+
public static final String HDMI_CABLE_ID = "1df3f0e9-7d6d-4dd6-93d9-206129fd793f";
41+
42+
public static final String VIDEO_SIGNAL_ID = "d9b2dd49-4bae-44a7-8137-73bcaf0a2d5e";
43+
44+
}
45+
}

backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/GeneralViewPartUsageRedefinitionProjectData.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
package org.eclipse.syson.application.data;
1414

1515
/**
16-
* Ids for project "GeneralView-GeneralView-PartUsage-redefinition".
16+
* Ids for project "GeneralView-PartUsage-redefinition".
1717
*
1818
* @author pcdavid
1919
*/

0 commit comments

Comments
 (0)