Skip to content
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ The cache holding standard libraries can be invalidated for a specific test meth
- https://github.com/eclipse-syson/syson/issues/2170[#2170] [diagrams] Improve the _Add existing elements_ diagram tool on graphical nodes to support multi-selection in standard diagrams.
- https://github.com/eclipse-syson/syson/issues/2148[#2148] [diagrams] Merge the two perform action creation tools into a single tool, leveraging the updated selection dialog.
- https://github.com/eclipse-syson/syson/issues/2152[#2152] [diagrams] Leverage the latest selection dialog changes to allow creating a sub action with and without associating the sub action with another `ActionUsage`.
- https://github.com/eclipse-syson/syson/issues/2161[#2161] [diagrams] Leverage the latest selection dialog changes to optionally allow creating a `SatisfyRequirement` graphical node, either standalone, feature typed, or subsetting a `RequirementUsage` by reference.
Also use that same tool in the `interconnection` compartment.

=== New features

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public CheckNodeOnDiagram hasVisibleCompartmentCount(int expectedVisibleCompartm
return this;
}

@Deprecated
public CheckNodeOnDiagram hasTargetObjectLabel(String expectedTargetObjectLabel) {
this.targetObjectLabel = Objects.requireNonNull(expectedTargetObjectLabel);
return this;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ public void createPartDefinitionSiblingNodes(EClass childEClass, EReference cont
@ParameterizedTest
@MethodSource("partDefinitionSiblingAndChildNodeParameters")
public void createPartDefinitionSiblingAndChildNodes(EClass childEClass, String compartmentName, EReference containmentReference, int expectedNumberOfNewNodes,
int expectedNumberOfNewEdges, String compartmentNodeDecriptionNameSuffix) {
int expectedNumberOfNewEdges, String compartmentNodeDescriptionNameSuffix) {
var flux = this.givenSubscriptionToDiagram();

var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
Expand All @@ -822,14 +822,15 @@ public void createPartDefinitionSiblingAndChildNodes(EClass childEClass, String
EClass parentEClass = SysmlPackage.eINSTANCE.getPartDefinition();
String targetObjectId = GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_DEFINITION_ID;

Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, parentEClass, targetObjectId, childEClass);
var variables = List.of(new ToolVariable("selectedObject", "", ToolVariableType.OBJECT_ID));
Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, parentEClass, targetObjectId, childEClass, variables);

Consumer<Object> diagramChecker = assertRefreshedDiagramThat(newDiagram -> {
new CheckDiagramElementCount(this.diagramComparator)
.hasNewNodeCount(expectedNumberOfNewNodes)
.hasNewEdgeCount(expectedNumberOfNewEdges)
.check(diagram.get(), newDiagram);
String compartmentItemNodeDescriptionName = this.descriptionNameGenerator.getCompartmentItemName(parentEClass, containmentReference) + compartmentNodeDecriptionNameSuffix;
String compartmentItemNodeDescriptionName = this.descriptionNameGenerator.getCompartmentItemName(parentEClass, containmentReference) + compartmentNodeDescriptionNameSuffix;
new CheckNodeInCompartment(diagramDescriptionIdProvider, this.diagramComparator)
.withTargetObjectId(targetObjectId)
.withCompartmentName(compartmentName)
Expand Down Expand Up @@ -929,7 +930,8 @@ public void createPartUsageSiblingAndChildNodes(EClass childEClass, String compa
EClass parentEClass = SysmlPackage.eINSTANCE.getPartUsage();
String targetObjectId = GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID;

Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, parentEClass, targetObjectId, childEClass);
var variables = List.of(new ToolVariable("selectedObject", "", ToolVariableType.OBJECT_ID));
Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, parentEClass, targetObjectId, childEClass, variables);

Consumer<Object> diagramChecker = assertRefreshedDiagramThat(newDiagram -> {
new CheckDiagramElementCount(this.diagramComparator)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariable;
import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariableType;
import org.eclipse.sirius.components.diagrams.tests.graphql.InvokeSingleClickOnDiagramElementToolExecutor;
import org.eclipse.sirius.components.diagrams.tests.graphql.PaletteQueryRunner;
import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator;
Expand Down Expand Up @@ -135,7 +137,7 @@ public void testQueryPaletteAndExecuteTools() {
diagramId.get(), List.of(interconnectionCompartmentNodeId.get()), newActionToolId.get(), 0, 0, List.of())
.isSuccess();
Runnable createSatisfyRequirementTool = () -> this.invokeSingleClickOnDiagramElementToolExecutor.execute(InterconnectionViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
diagramId.get(), List.of(interconnectionCompartmentNodeId.get()), newSatisfyRequirementToolId.get(), 0, 0, List.of())
diagramId.get(), List.of(interconnectionCompartmentNodeId.get()), newSatisfyRequirementToolId.get(), 0, 0, List.of(new ToolVariable("selectedObject", "", ToolVariableType.OBJECT_ID)))
.isSuccess();

Consumer<Object> afterCreatePartToolConsumer = assertRefreshedDiagramThat(diagram -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.sirius.components.emf.utils.SiriusEMFCopier;
import org.eclipse.syson.sysml.Definition;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.FeatureTyping;
import org.eclipse.syson.sysml.Namespace;
Expand Down Expand Up @@ -198,6 +199,47 @@ public SatisfyRequirementUsage createSatisfy(Element element, RequirementUsage e
return newSatisfyRequirementUsage;
}

/**
* Creates a {@link SatisfyRequirementUsage SatisfyRequirement} on {@code parentElement}.
* <p>
* Depending on the value of {@code selectedObject} the new {@link SatisfyRequirementUsage SatisfyRequirement} will be:
* <ul>
* <li>typed with {@code selectedObject} if the {@code selectedObject} is a {@link Definition}</li>
* <li>subsetted by reference by {@code selectedObject} if the {@code selectedObject} is a {@link RequirementUsage}</li>
* <li>standalone otherwise</li>
* </ul>
* </p>
*
* @param parentElement
* The parent element of the new {@link SatisfyRequirementUsage SatisfyRequirement}
* @param selectedObject
* The optionally selected object which will be used to provide additional behavior depending on its value
* @return The new created {@link SatisfyRequirementUsage SatisfyRequirement}
*
* @see ModelMutationElementService#createSatisfy(Element, RequirementUsage)
*/
public SatisfyRequirementUsage createSatisfyRequirement(Element parentElement, Element selectedObject) {
// create a new SatisfyRequirementUsage as child of the given Element
var newSatisfyRequirementUsage = SysmlFactory.eINSTANCE.createSatisfyRequirementUsage();
this.metamodelMutationElementService.addChildInParent(parentElement, newSatisfyRequirementUsage);

if (selectedObject instanceof Definition definition) {
var newFeatureTyping = SysmlFactory.eINSTANCE.createFeatureTyping();
newSatisfyRequirementUsage.getOwnedRelationship().add(newFeatureTyping);
newFeatureTyping.setType(definition);
newFeatureTyping.setTypedFeature(newSatisfyRequirementUsage);
this.metamodelMutationElementService.initialize(newFeatureTyping);
} else if (selectedObject instanceof RequirementUsage requirementUsage) {
var newReferenceSubsetting = SysmlFactory.eINSTANCE.createReferenceSubsetting();
newSatisfyRequirementUsage.getOwnedRelationship().add(newReferenceSubsetting);
newReferenceSubsetting.setReferencedFeature(requirementUsage);
this.metamodelMutationElementService.initialize(newReferenceSubsetting);
}

this.metamodelMutationElementService.initialize(newSatisfyRequirementUsage);
return newSatisfyRequirementUsage;
}

/**
* Creates a {@link ViewUsage}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ public Element createSatisfy(Element element, RequirementUsage existingRequireme
return this.modelMutationElementService.createSatisfy(element, existingRequirement);
}

/**
* {@link ModelMutationElementService#createSatisfyRequirement(Element, Element)}.
*/
public Element createSatisfyRequirement(Element self, Element selectedObject) {
return this.modelMutationElementService.createSatisfyRequirement(self, selectedObject);
}

/**
* {@link MetamodelMutationElementService#createOccurrenceInOccurrence(OccurrenceUsage, EClass)}.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024, 2025 Obeo.
* Copyright (c) 2024, 2026 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -13,6 +13,7 @@
package org.eclipse.syson.util;

import java.util.List;
import java.util.stream.Collectors;

/**
* Tooling around AQL expressions.
Expand Down Expand Up @@ -117,4 +118,15 @@ public static String getServiceCallExpression(String var, String serviceName, Li
return AQLConstants.AQL + var + '.' + serviceName + '(' + String.join(",", parameters) + ')';
}

/**
* Returns an AQL sequence from the given members.
*
* @param members
* The members to transform into a sequence
* @return the AQL sequence made from the members
*/
public static String aqlSequence(List<String> members) {
return members.stream().collect(Collectors.joining(",", "Sequence{", "}"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.eclipse.sirius.components.view.diagram.UserResizableDirection;
import org.eclipse.syson.diagram.common.view.services.description.ToolConstants;
import org.eclipse.syson.diagram.common.view.tools.ActionFlowCompartmentNodeToolProvider;
import org.eclipse.syson.diagram.common.view.tools.SatisfyRequirementNodeToolProvider;
import org.eclipse.syson.diagram.services.aql.DiagramQueryAQLService;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.SysmlPackage;
Expand Down Expand Up @@ -110,7 +111,7 @@ protected NodePalette createCompartmentPalette(IViewDiagramElementFinder cache)
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.STRUCTURE,
this.toolDescriptionService.createNodeTool(nodeDesc, SysmlPackage.eINSTANCE.getActionUsage()));
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.REQUIREMENTS,
this.toolDescriptionService.createNodeTool(nodeDesc, SysmlPackage.eINSTANCE.getSatisfyRequirementUsage()));
new SatisfyRequirementNodeToolProvider().create(cache));
});

this.toolDescriptionService.removeEmptyNodeToolSections(toolSections);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*******************************************************************************/
package org.eclipse.syson.diagram.common.view.tools;

import java.util.List;

import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.diagrams.Node;
Expand All @@ -26,6 +28,7 @@
import org.eclipse.syson.model.services.aql.ModelMutationAQLService;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.util.AQLConstants;
import org.eclipse.syson.util.AQLUtils;
import org.eclipse.syson.util.ServiceMethod;
import org.eclipse.syson.util.SysMLMetamodelHelper;

Expand All @@ -47,8 +50,8 @@ public NodeTool create(IViewDiagramElementFinder cache) {
String reqUsageType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getRequirementUsage());

var selectionDialogTree = this.diagramBuilderHelper.newSelectionDialogTreeDescription()
.elementsExpression(ServiceMethod.of1(ViewToolService::getSelectionDialogElements).aql(IEditingContext.EDITING_CONTEXT, "Sequence{" + reqUsageType + "}"))
.childrenExpression(ServiceMethod.of1(ViewToolService::getSelectionDialogChildren).aqlSelf("Sequence{" + reqUsageType + "}"))
.elementsExpression(ServiceMethod.of1(ViewToolService::getSelectionDialogElements).aql(IEditingContext.EDITING_CONTEXT, AQLUtils.aqlSequence(List.of(reqUsageType))))
.childrenExpression(ServiceMethod.of1(ViewToolService::getSelectionDialogChildren).aqlSelf(AQLUtils.aqlSequence(List.of(reqUsageType))))
.isSelectableExpression(AQLConstants.AQL_SELF + ".oclIsKindOf(" + reqUsageType + ")")
.build();
var selectionDialog = this.diagramBuilderHelper.newSelectionDialogDescription()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,36 @@
*******************************************************************************/
package org.eclipse.syson.diagram.common.view.tools;

import java.util.List;

import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.diagrams.Node;
import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder;
import org.eclipse.sirius.components.view.builder.generated.diagram.DiagramBuilders;
import org.eclipse.sirius.components.view.builder.generated.view.ViewBuilders;
import org.eclipse.sirius.components.view.builder.providers.INodeToolProvider;
import org.eclipse.sirius.components.view.diagram.DialogDescription;
import org.eclipse.sirius.components.view.diagram.NodeTool;
import org.eclipse.sirius.components.view.emf.diagram.ViewDiagramDescriptionConverter;
import org.eclipse.syson.diagram.common.view.services.ViewCreateService;
import org.eclipse.syson.diagram.common.view.services.ViewToolService;
import org.eclipse.syson.diagram.services.aql.DiagramMutationAQLService;
import org.eclipse.syson.model.services.aql.ModelMutationAQLService;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.util.AQLConstants;
import org.eclipse.syson.util.AQLUtils;
import org.eclipse.syson.util.ServiceMethod;
import org.eclipse.syson.util.SysMLMetamodelHelper;

/**
* Node Tool allowing to create a SatisfyRequirement.
*
* @author arichard
*/
public class SatisfyRequirementNodeToolProvider implements INodeToolProvider {

private static final String TOOL_NAME = "New Satisfy Requirement";

private final DiagramBuilders diagramBuilderHelper = new DiagramBuilders();

private final ViewBuilders viewBuilderHelper = new ViewBuilders();
Expand All @@ -46,26 +54,43 @@ public NodeTool create(IViewDiagramElementFinder cache) {
.expression(ServiceMethod.of4(DiagramMutationAQLService::expose).aqlSelf(IEditingContext.EDITING_CONTEXT, DiagramContext.DIAGRAM_CONTEXT, Node.SELECTED_NODE,
ViewDiagramDescriptionConverter.CONVERTED_NODES_VARIABLE));

var changeContextNewInstance = this.viewBuilderHelper.newChangeContext()
.expression("aql:newInstance")
.children(addToExposedElements.build());
var newSatisfyRequirementTool = this.viewBuilderHelper.newChangeContext()
.expression(ServiceMethod.of1(ModelMutationAQLService::createSatisfyRequirement).aqlSelf("selectedObject"))
.children(addToExposedElements.build())
.build();

var changeContextInitializeNewInstance = this.viewBuilderHelper.newChangeContext()
.expression(ServiceMethod.of0(ViewCreateService::elementInitializer).aql("newInstance"));
return builder.name(TOOL_NAME)
.iconURLsExpression("/icons/full/obj16/SatisfyRequirementUsage.svg")
.dialogDescription(this.getDialogDescription())
.body(newSatisfyRequirementTool)
.build();
}

var createEClassInstance = this.viewBuilderHelper.newCreateInstance()
.typeName(SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getSatisfyRequirementUsage()))
.referenceName(SysmlPackage.eINSTANCE.getRelationship_OwnedRelatedElement().getName())
.variableName("newInstance")
.children(changeContextInitializeNewInstance.build(), changeContextNewInstance.build());
private DialogDescription getDialogDescription() {
var reqUsageType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getRequirementUsage());
var defType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getDefinition());
var selectableTypes = List.of(reqUsageType, defType);

var createMembership = this.viewBuilderHelper.newChangeContext()
.expression(ServiceMethod.of0(ModelMutationAQLService::createMembership).aqlSelf())
.children(createEClassInstance.build());
var selectionDialogTreeDescription = this.diagramBuilderHelper.newSelectionDialogTreeDescription()
.elementsExpression(ServiceMethod.of1(ViewToolService::getSelectionDialogElements).aql(IEditingContext.EDITING_CONTEXT, AQLUtils.aqlSequence(selectableTypes)))
.childrenExpression(ServiceMethod.of1(ViewToolService::getSelectionDialogChildren).aqlSelf(AQLUtils.aqlSequence(selectableTypes)))
.isSelectableExpression(AQLConstants.AQL + "self.oclIsKindOf(" + defType + ") or self.oclIsKindOf(" + reqUsageType + ")")
.build();

return builder.name("New Satisfy Requirement")
.iconURLsExpression("/icons/full/obj16/SatisfyRequirementUsage.svg")
.body(createMembership.build())
return this.diagramBuilderHelper.newSelectionDialogDescription()
.selectionDialogTreeDescription(selectionDialogTreeDescription)
.defaultTitleExpression(TOOL_NAME)
.noSelectionTitleExpression(TOOL_NAME)
.withSelectionTitleExpression(TOOL_NAME)
.descriptionExpression(AQLConstants.AQL + "'Create a Satisfy Requirement with ' + self.name + ' as subject:'")
.noSelectionActionLabelExpression("Create a new Satisfy Requirement")
.noSelectionActionDescriptionExpression("Create a new Satisfy Requirement without specialization")
.withSelectionActionLabelExpression("Select an existing Element as specialization")
.withSelectionActionDescriptionExpression("Create a new specialized Satisfy Requirement")
.noSelectionActionStatusMessageExpression("It will create a new Satisfy Requirement without specialization")
.selectionRequiredWithoutSelectionStatusMessageExpression("Select one Element to specialize the new Satisfy Requirement")
.selectionRequiredWithSelectionStatusMessageExpression(AQLConstants.AQL + "'It will create a Satisfy Requirement specialized with ' + selectedObjects->first().name")
.optional(true)
.build();
}
}
Loading
Loading