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
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Disabling the _Hide expression internals_ filter in the _Explorer_ view allows t
- https://github.com/eclipse-syson/syson/issues/2112[#2112] [diagrams] Add tools to create _Start_ and _Done_ `StateUsages`, available on `StateUsage` and `StateDefinition` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2231[#2231] [diagrams] Add a new tools to create a _frame_ `ConcernUsage` from `RequirementUsage` and `RequirementDefinition` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2231[#2231] [diagrams] Add the support for the _frames_ compartment graphical node in `RequirementUsage` and `RequirementDefinition` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2242[#2242] [explorer] Add two options to the dialog creating a child element of `RequirementUsage` or `RequirementDefinition` tree items.
One creates a `ConcernUsage` and another one creates `FramedConcernMembership`.

== v2026.5.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.syson.sysml.Definition;
import org.eclipse.syson.sysml.EnumerationDefinition;
import org.eclipse.syson.sysml.FeatureMembership;
import org.eclipse.syson.sysml.FramedConcernMembership;
import org.eclipse.syson.sysml.InterfaceUsage;
import org.eclipse.syson.sysml.ItemUsage;
import org.eclipse.syson.sysml.Namespace;
Expand Down Expand Up @@ -134,6 +135,13 @@ public List<EClass> caseFeatureMembership(FeatureMembership object) {
return childrenCandidates;
}

@Override
public List<EClass> caseFramedConcernMembership(FramedConcernMembership object) {
List<EClass> childrenCandidates = new ArrayList<>();
childrenCandidates.add(SysmlPackage.eINSTANCE.getConcernUsage());
return childrenCandidates;
}

@Override
public List<EClass> caseInterfaceUsage(InterfaceUsage object) {
List<EClass> childrenCandidates = new ArrayList<>();
Expand Down Expand Up @@ -224,6 +232,8 @@ public List<EClass> caseRequirementDefinition(RequirementDefinition object) {
List<EClass> childrenCandidates = new ArrayList<>();
childrenCandidates.addAll(this.caseDefinition(object));
childrenCandidates.add(SysmlPackage.eINSTANCE.getSubjectMembership());
childrenCandidates.add(SysmlPackage.eINSTANCE.getFramedConcernMembership());
childrenCandidates.add(SysmlPackage.eINSTANCE.getConcernUsage());
return childrenCandidates;
}

Expand All @@ -232,6 +242,8 @@ public List<EClass> caseRequirementUsage(RequirementUsage object) {
List<EClass> childrenCandidates = new ArrayList<>();
childrenCandidates.addAll(this.caseUsage(object));
childrenCandidates.add(SysmlPackage.eINSTANCE.getSubjectMembership());
childrenCandidates.add(SysmlPackage.eINSTANCE.getFramedConcernMembership());
childrenCandidates.add(SysmlPackage.eINSTANCE.getConcernUsage());
return childrenCandidates;
}

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 @@ -19,6 +19,7 @@
import org.eclipse.emf.ecore.EClass;
import org.eclipse.syson.sysml.SysmlFactory;
import org.eclipse.syson.sysml.SysmlPackage;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
Expand All @@ -28,6 +29,7 @@
*/
public class GetChildCreationSwitchTest {

@DisplayName("Check the list of children that can be created from a Package")
@Test
public void testPackageChildren() {
List<EClass> children = new GetChildCreationSwitch().doSwitch(SysmlFactory.eINSTANCE.createPackage());
Expand All @@ -47,6 +49,7 @@ public void testPackageChildren() {
|| SysmlPackage.eINSTANCE.getPackage().isSuperTypeOf(eClass));
}

@DisplayName("Check the list of children that can be created from a Namespace")
@Test
public void testNamespaceChildren() {
List<EClass> children = new GetChildCreationSwitch().doSwitch(SysmlFactory.eINSTANCE.createNamespace());
Expand All @@ -66,6 +69,7 @@ public void testNamespaceChildren() {
|| SysmlPackage.eINSTANCE.getPackage().isSuperTypeOf(eClass));
}

@DisplayName("Check the list of children that can be created from a ViewUsage")
@Test
public void testViewUsageChildren() {
List<EClass> children = new GetChildCreationSwitch().doSwitch(SysmlFactory.eINSTANCE.createViewUsage());
Expand All @@ -79,4 +83,63 @@ public void testViewUsageChildren() {
children.removeAll(expectedChildren);
assertThat(children).isEmpty();
}

@DisplayName("Check the list of children that can be created from a RequirementDefinition")
@Test
public void testRequirementDefinitionChildren() {
List<EClass> children = new GetChildCreationSwitch().doSwitch(SysmlFactory.eINSTANCE.createRequirementDefinition());
List<EClass> expectedChildren = List.of(
SysmlPackage.eINSTANCE.getSubclassification(),
SysmlPackage.eINSTANCE.getDocumentation(),
SysmlPackage.eINSTANCE.getComment(),
SysmlPackage.eINSTANCE.getTextualRepresentation(),
SysmlPackage.eINSTANCE.getSubjectMembership(),
SysmlPackage.eINSTANCE.getFramedConcernMembership(),
SysmlPackage.eINSTANCE.getConcernUsage()
);
assertThat(children).containsAll(expectedChildren);
children.removeAll(expectedChildren);
assertThat(children).allMatch(eClass -> {
boolean authorizedClasses = SysmlPackage.eINSTANCE.getUsage().isSuperTypeOf(eClass) || SysmlPackage.eINSTANCE.getImport().isSuperTypeOf(eClass);
return !eClass.isAbstract() && !eClass.isInterface() && authorizedClasses;
});
}

@DisplayName("Check the list of children that can be created from a RequirementUsage")
@Test
public void testRequirementUsageChildren() {
List<EClass> children = new GetChildCreationSwitch().doSwitch(SysmlFactory.eINSTANCE.createRequirementUsage());
List<EClass> expectedChildren = List.of(
SysmlPackage.eINSTANCE.getAttributeUsage(),
SysmlPackage.eINSTANCE.getFeatureTyping(),
SysmlPackage.eINSTANCE.getSubsetting(),
SysmlPackage.eINSTANCE.getRedefinition(),
SysmlPackage.eINSTANCE.getReferenceSubsetting(),
SysmlPackage.eINSTANCE.getLiteralBoolean(),
SysmlPackage.eINSTANCE.getLiteralInfinity(),
SysmlPackage.eINSTANCE.getLiteralInteger(),
SysmlPackage.eINSTANCE.getLiteralRational(),
SysmlPackage.eINSTANCE.getLiteralString(),
SysmlPackage.eINSTANCE.getFeatureMembership(),
SysmlPackage.eINSTANCE.getDocumentation(),
SysmlPackage.eINSTANCE.getComment(),
SysmlPackage.eINSTANCE.getTextualRepresentation(),
SysmlPackage.eINSTANCE.getSubjectMembership(),
SysmlPackage.eINSTANCE.getFramedConcernMembership(),
SysmlPackage.eINSTANCE.getConcernUsage()
);
assertThat(children).containsAll(expectedChildren);
children.removeAll(expectedChildren);
assertThat(children).isEmpty();
}

@DisplayName("Check the list of children that can be created from a FramedConcernMembership")
@Test
public void testFramedConcernMembership() {
List<EClass> children = new GetChildCreationSwitch().doSwitch(SysmlFactory.eINSTANCE.createFramedConcernMembership());
List<EClass> expectedChildren = List.of(SysmlPackage.eINSTANCE.getConcernUsage());
assertThat(children).containsAll(expectedChildren);
children.removeAll(expectedChildren);
assertThat(children).isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@
import org.eclipse.syson.application.data.GeneralViewEmptyTestProjectData;
import org.eclipse.syson.application.data.ProjectWithLibraryDependencyContainingLibraryPackageTestProjectData;
import org.eclipse.syson.application.data.WithUserLibrariesTestProjectData;
import org.eclipse.syson.sysml.ConcernUsage;
import org.eclipse.syson.sysml.ConstraintUsage;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.FramedConcernMembership;
import org.eclipse.syson.sysml.LibraryPackage;
import org.eclipse.syson.sysml.Namespace;
import org.eclipse.syson.sysml.RequirementConstraintMembership;
Expand Down Expand Up @@ -446,11 +448,11 @@ public void testCreateConstraintInRequirement() {

Runnable checkConstraintOwnership = () -> {
var editingContextFunctionInput = new ExecuteEditingContextFunctionInput(UUID.randomUUID(), ExplorerViewDirectEditTestProjectData.EDITING_CONTEXT_ID, (editingContext, input) -> {
var optionalContraint = this.objectSearchService.getObject(editingContext, newConstraintId.get());
assertThat(optionalContraint).containsInstanceOf(ConstraintUsage.class);
var constraint = (ConstraintUsage) optionalContraint.get();
var optionalConstraint = this.objectSearchService.getObject(editingContext, newConstraintId.get());
assertThat(optionalConstraint).containsInstanceOf(ConstraintUsage.class);
var constraint = (ConstraintUsage) optionalConstraint.get();
assertThat(constraint.getOwningRelationship()).isInstanceOf(RequirementConstraintMembership.class);
return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalContraint.get());
return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalConstraint.get());
});
Mono<IPayload> result = this.executeEditingContextFunctionRunner.execute(editingContextFunctionInput);
var payload = result.block();
Expand All @@ -466,6 +468,55 @@ public void testCreateConstraintInRequirement() {
.verify(Duration.ofSeconds(10));
}

@DisplayName("GIVEN the Sirius Explorer View, WHEN creating a concern inside a requirement, THEN the new concern is owned through a FramedConcernMembership")
@GivenSysONServer({ ExplorerViewDirectEditTestProjectData.SCRIPT_PATH })
@Test
public void testCreateConcernInRequirement() {
var expandedIds = this.getAllTreeItemIds(ExplorerViewDirectEditTestProjectData.EDITING_CONTEXT_ID);
var activatedFilters = List.of(SysONTreeFilterConstants.HIDE_ROOT_NAMESPACES_ID);
var treeRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONTreeViewDescriptionProvider.getDescriptionId(), expandedIds, activatedFilters);

var treeEventInput = new ExplorerEventInput(UUID.randomUUID(), ExplorerViewDirectEditTestProjectData.EDITING_CONTEXT_ID, treeRepresentationId);
var treeFlux = this.treeEventSubscriptionRunner.run(treeEventInput).flux();

var newConcernId = new AtomicReference<String>(null);

Consumer<Object> ignorePayload = (o) -> {
// Ignore the refresh event payload, we will check the actual semantic model content.
};

Runnable createChildConstraint = () -> {
var input = new CreateChildInput(UUID.randomUUID(), ExplorerViewDirectEditTestProjectData.EDITING_CONTEXT_ID, ExplorerViewDirectEditTestProjectData.SemanticIds.REQ1_RU_ID,
"SysMLv2EditService-ConcernUsage");
var result = this.createChildMutationRunner.run(input);
String typename = JsonPath.read(result.data(), "$.data.createChild.__typename");
assertThat(typename).isEqualTo(CreateChildSuccessPayload.class.getSimpleName());
String objectId = JsonPath.read(result.data(), "$.data.createChild.object.id");
newConcernId.set(objectId);
};

Runnable checkConcernOwnership = () -> {
var editingContextFunctionInput = new ExecuteEditingContextFunctionInput(UUID.randomUUID(), ExplorerViewDirectEditTestProjectData.EDITING_CONTEXT_ID, (editingContext, input) -> {
var optionalConcern = this.objectSearchService.getObject(editingContext, newConcernId.get());
assertThat(optionalConcern).containsInstanceOf(ConstraintUsage.class);
var concern = (ConcernUsage) optionalConcern.get();
assertThat(concern.getOwningRelationship()).isInstanceOf(FramedConcernMembership.class);
return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalConcern.get());
});
Mono<IPayload> result = this.executeEditingContextFunctionRunner.execute(editingContextFunctionInput);
var payload = result.block();
assertThat(payload).isInstanceOf(ExecuteEditingContextFunctionSuccessPayload.class);
};

StepVerifier.create(treeFlux)
.consumeNextWith(ignorePayload)
.then(createChildConstraint)
.consumeNextWith(ignorePayload)
.then(checkConcernOwnership)
.thenCancel()
.verify(Duration.ofSeconds(10));
}

private List<String> getAllTreeItemIds(String editingContextId) {
ExecuteEditingContextFunctionInput executeEditingContextFunctionInput = new ExecuteEditingContextFunctionInput(UUID.randomUUID(), editingContextId, (editingContext, input) -> {
if (editingContext instanceof IEMFEditingContext emfEditingContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.syson.sysml.Comment;
import org.eclipse.syson.sysml.ConcernUsage;
import org.eclipse.syson.sysml.ConstraintUsage;
import org.eclipse.syson.sysml.Definition;
import org.eclipse.syson.sysml.Documentation;
Expand Down Expand Up @@ -70,6 +71,19 @@ public Optional<EClass> caseConstraintUsage(ConstraintUsage object) {
return intermediateContainer;
}

@Override
public Optional<EClass> caseConcernUsage(ConcernUsage object) {
Optional<EClass> intermediateContainer;
if (this.container instanceof RequirementDefinition || this.container instanceof RequirementUsage) {
// SysML v2 8.3.21.5: "A FramedConcernMembership is a RequirementConstraintMembership for a framed ConcernUsage of a
// RequirementDefinition or RequirementUsage."
intermediateContainer = Optional.of(SysmlPackage.eINSTANCE.getFramedConcernMembership());
} else {
intermediateContainer = this.caseFeature(object);
}
return intermediateContainer;
}

@Override
public Optional<EClass> caseDefinition(Definition object) {
return Optional.of(SysmlPackage.eINSTANCE.getOwningMembership());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ a|image::explorer-expression-internals-hidden.png[Internals hidden (default)]
a|image::explorer-expression-internals-visible.png[Internals visible]
|===

** The dialog creating a child element provide two more options for `RequirementUsage` or `RequirementDefinition` tree items.
One creates a `ConcernUsage` and another one creates `FramedConcernMembership`.
The one creating a `ConcernUsage` create a `FramedConcernMembership` as an intermediate container.
The one creating a `FramedConcernMembership` only creates the membership.
In both cases, to display the `FramedConcernMembership` deactivate the `Hide Memberships` filter.

== Bug fixes

== Improvements
Expand Down
Loading