Skip to content

Commit 00e5121

Browse files
committed
[2250] Leverage the selection dialog to improve the assume and require constraints
Bug: #2250 Signed-off-by: Guillaume Coutable <guillaume.coutable@obeo.fr>
1 parent c548da1 commit 00e5121

18 files changed

Lines changed: 870 additions & 43 deletions

File tree

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ One creates a `ConcernUsage` and another one creates `FramedConcernMembership`.
4848
This is currently supported on `Features` (e.g. `Attribute`), `Constraints` and `Transitions` (guard conditions) view new context menu actions (_Create expression_ and _Edit expression_) on the corresponding elements in the _Explorer_.
4949
- https://github.com/eclipse-syson/syson/issues/2247[#2247] [diagrams] Add the support for creating _timeslices/snapshots_ from the different kind of `OccurrenceDefiniton` graphical nodes.
5050
It leverages the selection dialog to either create an _occurrence timeslice/snapshot_, or the _usage timeslice/snapshot_ matching the `OccurrenceDefinition` on which the tool is applied.
51+
- https://github.com/eclipse-syson/syson/issues/2250[#2250] [diagrams] Leverage the selection dialog to improve the graphical node tools creating a _require_ `ConstraintUsage`, or an _assume_ `ConstraintUsage`, from `RequirementUsage` and `RequirementDefinition` graphical nodes.
5152

5253
== v2026.5.0
5354

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

Lines changed: 148 additions & 8 deletions
Large diffs are not rendered by default.

backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramMutationExposeService.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.eclipse.syson.sysml.PartDefinition;
5151
import org.eclipse.syson.sysml.PartUsage;
5252
import org.eclipse.syson.sysml.PortUsage;
53+
import org.eclipse.syson.sysml.RequirementConstraintMembership;
5354
import org.eclipse.syson.sysml.SysmlFactory;
5455
import org.eclipse.syson.sysml.SysmlPackage;
5556
import org.eclipse.syson.sysml.TextualRepresentation;
@@ -140,11 +141,12 @@ public Element expose(Element element, IEditingContext editingContext, DiagramCo
140141
viewUsage.getOwnedRelationship().add(membershipExpose);
141142
new ElementInitializerSwitch().doSwitch(membershipExpose);
142143
// if it is the General View, we want to hide tree elements if a compartment containing the same
143-
// element is displayed or it is displayed as border node
144+
// element is displayed or it is displayed as border node, or if there is another exposed relation
144145
if (selectedNode != null && ViewDefinitionKind.isGeneralView(this.utilService.getViewDefinitionKind(element, List.of(), editingContext))) {
145146
this.hideNodeIfVisibleCompartmentCouldHostTheFutureNode(element, editingContext, diagramContext, selectedNode, convertedNodes);
146147
this.hideNodeIfBorderNodeCouldHostTheFutureNode(element, editingContext, diagramContext, selectedNode, convertedNodes);
147148
this.hideNodeIfNestedIsDefault(element, editingContext, diagramContext, selectedNode, convertedNodes);
149+
this.hideNodeIfHasReferenceSubset(element, editingContext, diagramContext, selectedNode, convertedNodes);
148150
}
149151
}
150152
}
@@ -276,7 +278,7 @@ public boolean removeFromExposedElements(Element element, Node selectedNode, IEd
276278
* Returns the elements contained by {@code parentElement} that should be rendered.
277279
* <p>
278280
* This method is typically used by
279-
* {@link #addToExposedElements(Element, IEditingContext, DiagramContext, Node, Map, boolean)} to navigate the model
281+
* {@link #addToExposedElements(Element, boolean, IEditingContext, DiagramContext, Node, Map)} to navigate the model
280282
* and find the elements to display.
281283
* </p>
282284
*
@@ -486,6 +488,24 @@ private void hideNodeIfNestedIsDefault(Element element, IEditingContext editingC
486488
}
487489
}
488490

491+
private void hideNodeIfHasReferenceSubset(Element element, IEditingContext editingContext, DiagramContext diagramContext, Node selectedNode, Map<org.eclipse.sirius.components.view.diagram.NodeDescription, NodeDescription> convertedNodes) {
492+
var owningMembership = element.getOwningMembership();
493+
if (owningMembership.eClass().equals(SysmlPackage.eINSTANCE.getRequirementConstraintMembership())) {
494+
var requirementConstraintMembership = (RequirementConstraintMembership) owningMembership;
495+
if (requirementConstraintMembership.getReferencedConstraint() != requirementConstraintMembership.getOwnedConstraint() && requirementConstraintMembership.getOwnedConstraint() == element) {
496+
var parentId = this.diagramQueryElementService.getGraphicalParentId(diagramContext, selectedNode);
497+
var descriptionId = this.diagramQueryElementService.getNodeDescriptionId(element, diagramContext.diagram(), editingContext);
498+
if (parentId != null && descriptionId.isPresent()) {
499+
var nodeId = new NodeIdProvider().getNodeId(parentId,
500+
descriptionId.get(),
501+
NodeContainmentKind.CHILD_NODE,
502+
this.siriusWebCoreServices.identityService().getId(element));
503+
diagramContext.diagramEvents().add(new HideDiagramElementEvent(Set.of(nodeId), true));
504+
}
505+
}
506+
}
507+
}
508+
489509
private boolean isItemNotContainedByAction(Element element) {
490510
boolean isItemNotContainedByAction = false;
491511
if (Objects.equals(SysmlPackage.eINSTANCE.getItemUsage(), element.eClass())) {

backend/services/syson-model-services/src/main/java/org/eclipse/syson/model/services/ModelMutationElementService.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
import org.eclipse.emf.ecore.util.EcoreUtil;
2020
import org.eclipse.sirius.components.emf.utils.SiriusEMFCopier;
2121
import org.eclipse.syson.sysml.ConcernUsage;
22+
import org.eclipse.syson.sysml.ConstraintUsage;
2223
import org.eclipse.syson.sysml.Definition;
2324
import org.eclipse.syson.sysml.Element;
2425
import org.eclipse.syson.sysml.FeatureTyping;
2526
import org.eclipse.syson.sysml.FramedConcernMembership;
2627
import org.eclipse.syson.sysml.Namespace;
2728
import org.eclipse.syson.sysml.PartUsage;
2829
import org.eclipse.syson.sysml.Relationship;
30+
import org.eclipse.syson.sysml.RequirementConstraintKind;
31+
import org.eclipse.syson.sysml.RequirementConstraintMembership;
2932
import org.eclipse.syson.sysml.RequirementDefinition;
3033
import org.eclipse.syson.sysml.RequirementUsage;
3134
import org.eclipse.syson.sysml.SatisfyRequirementUsage;
@@ -235,6 +238,42 @@ public FramedConcernMembership createFramedConcern(Type type, ConcernUsage conce
235238
return null;
236239
}
237240

241+
/**
242+
* In a {@link RequirementUsage} or a {@link RequirementDefinition}, creates a {@link RequirementConstraintMembership} containing a {@link ConstraintUsage}.
243+
* The {@link RequirementConstraintKind} is used to indicate whether the constraint is {@code required} or {@code assumed}.
244+
* If a {@link ConstraintUsage} is given, the {@link RequirementConstraintMembership} owned constraint will be subsetted by the given {@link ConstraintUsage}.
245+
*
246+
* @param type
247+
* the type that will hold the {@link RequirementConstraintMembership}, {@code type} must be a {@link RequirementDefinition} or a requirementUsage
248+
* @param constraintUsage
249+
* the {@link ConstraintUsage} subsetted by reference, can be {@code null}
250+
* @param constraintKind
251+
* whether the constraint is {@code required} or {@code assumed}
252+
* @return the created {@link RequirementConstraintMembership} when {@code type} is a {@link RequirementDefinition}, or a {@link RequirementUsage}, {@code null} otherwise
253+
*/
254+
public RequirementConstraintMembership createConstraint(Type type, ConstraintUsage constraintUsage, RequirementConstraintKind constraintKind) {
255+
if (type instanceof RequirementDefinition || type instanceof RequirementUsage) {
256+
var newRequirementConstraintMembership = SysmlFactory.eINSTANCE.createRequirementConstraintMembership();
257+
type.getOwnedRelationship().add(newRequirementConstraintMembership);
258+
newRequirementConstraintMembership.setKind(constraintKind);
259+
260+
var newConstraintUsage = SysmlFactory.eINSTANCE.createConstraintUsage();
261+
newRequirementConstraintMembership.getOwnedRelatedElement().add(newConstraintUsage);
262+
263+
this.metamodelMutationElementService.initialize(newRequirementConstraintMembership);
264+
this.metamodelMutationElementService.initialize(newConstraintUsage);
265+
266+
if (constraintUsage != null) {
267+
var newReferenceSubsetting = SysmlFactory.eINSTANCE.createReferenceSubsetting();
268+
newConstraintUsage.getOwnedRelationship().add(newReferenceSubsetting);
269+
newReferenceSubsetting.setReferencedFeature(constraintUsage);
270+
this.metamodelMutationElementService.initialize(newReferenceSubsetting);
271+
}
272+
return newRequirementConstraintMembership;
273+
}
274+
return null;
275+
}
276+
238277
/**
239278
* Creates a {@link SatisfyRequirementUsage SatisfyRequirement} on {@code parentElement}.
240279
* <p>

backend/services/syson-model-services/src/main/java/org/eclipse/syson/model/services/aql/ModelMutationAQLService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
import org.eclipse.emf.ecore.EObject;
1919
import org.eclipse.syson.model.services.ModelMutationElementService;
2020
import org.eclipse.syson.sysml.ConcernUsage;
21+
import org.eclipse.syson.sysml.ConstraintUsage;
2122
import org.eclipse.syson.sysml.Documentation;
2223
import org.eclipse.syson.sysml.Element;
2324
import org.eclipse.syson.sysml.Membership;
2425
import org.eclipse.syson.sysml.PartUsage;
26+
import org.eclipse.syson.sysml.RequirementConstraintKind;
2527
import org.eclipse.syson.sysml.RequirementUsage;
2628
import org.eclipse.syson.sysml.Type;
2729
import org.eclipse.syson.sysml.ViewUsage;
@@ -113,4 +115,11 @@ public Element setAsView(ViewUsage viewUsage, String newViewDefinition) {
113115
public Element createFramedConcern(Type type, ConcernUsage concernUsage) {
114116
return this.modelMutationElementService.createFramedConcern(type, concernUsage);
115117
}
118+
119+
/**
120+
* {@link ModelMutationElementService#createConstraint(Type, ConstraintUsage, RequirementConstraintKind)}.
121+
*/
122+
public Element createConstraint(Type type, ConstraintUsage constraintUsage, RequirementConstraintKind constraintKind) {
123+
return this.modelMutationElementService.createConstraint(type, constraintUsage, constraintKind);
124+
}
116125
}
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.diagram.common.view.nodes;
14+
15+
import org.eclipse.emf.ecore.EClass;
16+
import org.eclipse.emf.ecore.EReference;
17+
import org.eclipse.sirius.components.view.builder.providers.IColorProvider;
18+
import org.eclipse.syson.sysml.SysmlPackage;
19+
import org.eclipse.syson.util.IDescriptionNameGenerator;
20+
import org.eclipse.syson.util.SysMLMetamodelHelper;
21+
22+
/**
23+
* Used to create a {@link org.eclipse.syson.sysml.ConstraintUsage} compartment item node description.
24+
* <p>
25+
* {@link org.eclipse.syson.sysml.ConstraintUsage} compartment items have to be contained in a {@link org.eclipse.syson.sysml.RequirementConstraintMembership} with {@link org.eclipse.syson.sysml.RequirementConstraintKind#ASSUMPTION}.
26+
* </p>
27+
* @author gcoutable
28+
*/
29+
public class AssumeConstraintCompartmentItemNodeDescription extends CompartmentItemNodeDescriptionProvider {
30+
public static final String COMPARTMENT_ITEM_NAME = " assume constraint";
31+
32+
public AssumeConstraintCompartmentItemNodeDescription(EClass eClass, EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) {
33+
super(eClass, eReference, colorProvider, descriptionNameGenerator);
34+
}
35+
36+
@Override
37+
protected String getDomainType() {
38+
return SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getElement());
39+
}
40+
41+
@Override
42+
protected String getName() {
43+
return super.getName() + COMPARTMENT_ITEM_NAME;
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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.diagram.common.view.nodes;
14+
15+
import java.util.List;
16+
17+
import org.eclipse.emf.ecore.EClass;
18+
import org.eclipse.emf.ecore.EReference;
19+
import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder;
20+
import org.eclipse.sirius.components.view.builder.providers.IColorProvider;
21+
import org.eclipse.sirius.components.view.builder.providers.INodeToolProvider;
22+
import org.eclipse.sirius.components.view.diagram.DiagramDescription;
23+
import org.eclipse.sirius.components.view.diagram.NodeDescription;
24+
import org.eclipse.syson.diagram.common.view.tools.AssumeConstraintNodeToolProvider;
25+
import org.eclipse.syson.util.IDescriptionNameGenerator;
26+
27+
/**
28+
* Compartment node allowing to display {@link org.eclipse.syson.sysml.ConstraintUsage} owned by a {@link org.eclipse.syson.sysml.RequirementConstraintMembership} with {@link org.eclipse.syson.sysml.RequirementConstraintKind#ASSUMPTION}.
29+
*
30+
* @author gcoutable
31+
*/
32+
public class AssumeConstraintCompartmentNodeDescription extends AbstractCompartmentNodeDescriptionProvider {
33+
34+
public static final String COMPARTMENT_NAME = " assume";
35+
36+
public AssumeConstraintCompartmentNodeDescription(EClass eClass, EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) {
37+
super(eClass, eReference, colorProvider, descriptionNameGenerator);
38+
}
39+
40+
@Override
41+
protected String getCompartmentName() {
42+
return this.getDescriptionNameGenerator().getCompartmentName(this.eClass, this.eReference) + COMPARTMENT_NAME;
43+
}
44+
45+
@Override
46+
protected String getCustomCompartmentLabel() {
47+
return "assume constraints";
48+
}
49+
50+
@Override
51+
public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) {
52+
cache.getNodeDescription(this.getCompartmentName()).ifPresent(nodeDescription -> {
53+
cache.getNodeDescription(this.getDescriptionNameGenerator().getCompartmentItemName(this.eClass, this.eReference) + AssumeConstraintCompartmentItemNodeDescription.COMPARTMENT_ITEM_NAME)
54+
.ifPresent(itemNodeDescription -> nodeDescription.getChildrenDescriptions().add(itemNodeDescription));
55+
nodeDescription.setPalette(this.createCompartmentPalette(cache));
56+
});
57+
}
58+
59+
@Override
60+
protected List<INodeToolProvider> getItemCreationToolProviders() {
61+
return List.of(new AssumeConstraintNodeToolProvider());
62+
}
63+
64+
@Override
65+
protected List<NodeDescription> getDroppableNodes(IViewDiagramElementFinder cache) {
66+
return List.of();
67+
}
68+
}
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.diagram.common.view.nodes;
14+
15+
import org.eclipse.emf.ecore.EClass;
16+
import org.eclipse.emf.ecore.EReference;
17+
import org.eclipse.sirius.components.view.builder.providers.IColorProvider;
18+
import org.eclipse.syson.sysml.SysmlPackage;
19+
import org.eclipse.syson.util.IDescriptionNameGenerator;
20+
import org.eclipse.syson.util.SysMLMetamodelHelper;
21+
22+
/**
23+
* Used to create a {@link org.eclipse.syson.sysml.ConstraintUsage} compartment item node description.
24+
* <p>
25+
* {@link org.eclipse.syson.sysml.ConstraintUsage} compartment items have to be contained in a {@link org.eclipse.syson.sysml.RequirementConstraintMembership} with {@link org.eclipse.syson.sysml.RequirementConstraintKind#REQUIREMENT}.
26+
* </p>
27+
* @author gcoutable
28+
*/
29+
public class RequireConstraintCompartmentItemNodeDescription extends CompartmentItemNodeDescriptionProvider {
30+
public static final String COMPARTMENT_ITEM_NAME = " require constraint";
31+
32+
public RequireConstraintCompartmentItemNodeDescription(EClass eClass, EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) {
33+
super(eClass, eReference, colorProvider, descriptionNameGenerator);
34+
}
35+
36+
@Override
37+
protected String getDomainType() {
38+
return SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getElement());
39+
}
40+
41+
@Override
42+
protected String getName() {
43+
return super.getName() + COMPARTMENT_ITEM_NAME;
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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.diagram.common.view.nodes;
14+
15+
import java.util.List;
16+
17+
import org.eclipse.emf.ecore.EClass;
18+
import org.eclipse.emf.ecore.EReference;
19+
import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder;
20+
import org.eclipse.sirius.components.view.builder.providers.IColorProvider;
21+
import org.eclipse.sirius.components.view.builder.providers.INodeToolProvider;
22+
import org.eclipse.sirius.components.view.diagram.DiagramDescription;
23+
import org.eclipse.sirius.components.view.diagram.NodeDescription;
24+
import org.eclipse.syson.diagram.common.view.tools.RequireConstraintNodeToolProvider;
25+
import org.eclipse.syson.util.IDescriptionNameGenerator;
26+
27+
/**
28+
* Compartment node allowing to display {@link org.eclipse.syson.sysml.ConstraintUsage} owned by a {@link org.eclipse.syson.sysml.RequirementConstraintMembership} with {@link org.eclipse.syson.sysml.RequirementConstraintKind#REQUIREMENT}.
29+
*
30+
* @author gcoutable
31+
*/
32+
public class RequireConstraintCompartmentNodeDescription extends AbstractCompartmentNodeDescriptionProvider {
33+
34+
public static final String COMPARTMENT_NAME = " require";
35+
36+
public RequireConstraintCompartmentNodeDescription(EClass eClass, EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) {
37+
super(eClass, eReference, colorProvider, descriptionNameGenerator);
38+
}
39+
40+
@Override
41+
protected String getCompartmentName() {
42+
return this.getDescriptionNameGenerator().getCompartmentName(this.eClass, this.eReference) + COMPARTMENT_NAME;
43+
}
44+
45+
@Override
46+
protected String getCustomCompartmentLabel() {
47+
return "require constraints";
48+
}
49+
50+
@Override
51+
public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) {
52+
cache.getNodeDescription(this.getCompartmentName()).ifPresent(nodeDescription -> {
53+
cache.getNodeDescription(this.getDescriptionNameGenerator().getCompartmentItemName(this.eClass, this.eReference) + RequireConstraintCompartmentItemNodeDescription.COMPARTMENT_ITEM_NAME)
54+
.ifPresent(itemNodeDescription -> nodeDescription.getChildrenDescriptions().add(itemNodeDescription));
55+
nodeDescription.setPalette(this.createCompartmentPalette(cache));
56+
});
57+
}
58+
59+
@Override
60+
protected List<INodeToolProvider> getItemCreationToolProviders() {
61+
return List.of(new RequireConstraintNodeToolProvider());
62+
}
63+
64+
@Override
65+
protected List<NodeDescription> getDroppableNodes(IViewDiagramElementFinder cache) {
66+
return List.of();
67+
}
68+
}

0 commit comments

Comments
 (0)