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
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ This change ensures compatibility with classpath resource resolution, which requ
- https://github.com/eclipse-syson/syson/issues/2045[#2045] [diagrams] In Interconnection View diagrams, fix an issue where the `parts` compartment of a `PartDefinition` graphical node was incorrectly revealed when creating a `PartUsage` from the `PartDefinition` graphical node, even if the `interconnection` compartment was already visible.
- https://github.com/eclipse-syson/syson/issues/2094[#2094] [libraries] Ensure library documents are read-only.
- https://github.com/eclipse-syson/syson/issues/2143[#2143] [configuration] Fixed classpath resource resolution on Windows by enforcing forward slashes (`/`) in library paths.
- https://github.com/eclipse-syson/syson/issues/2185[#2185] [explorer] When creating a `ConstraintUsage` inside a `Requirement` the new constraint is now correctly owned through a `RequirementConstraintMembership`.

=== Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
Expand All @@ -34,6 +35,8 @@
import org.eclipse.sirius.components.collaborative.dto.CreateChildSuccessPayload;
import org.eclipse.sirius.components.core.api.ErrorPayload;
import org.eclipse.sirius.components.core.api.IIdentityService;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext;
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionInput;
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionSuccessPayload;
Expand All @@ -57,9 +60,11 @@
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.ConstraintUsage;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.LibraryPackage;
import org.eclipse.syson.sysml.Namespace;
import org.eclipse.syson.sysml.RequirementConstraintMembership;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.tree.explorer.filters.SysONTreeFilterConstants;
import org.eclipse.syson.tree.explorer.fragments.LibrariesDirectory;
Expand All @@ -73,6 +78,7 @@
import org.springframework.test.context.transaction.TestTransaction;
import org.springframework.transaction.annotation.Transactional;

import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

/**
Expand Down Expand Up @@ -136,6 +142,9 @@ private record TreeItemMatcher(Function<Tree, TreeItem> treeItemFinder, Predicat
@Autowired
private IIdentityService identityService;

@Autowired
private IObjectSearchService objectSearchService;

@Autowired
private ExplorerEventSubscriptionRunner treeEventSubscriptionRunner;

Expand Down Expand Up @@ -407,6 +416,55 @@ public void testSysONFiltersOnSiriusExplorer() {
assertThat(treeFilterIds).isEmpty();
}

@DisplayName("GIVEN the Sirius Explorer View, WHEN creating a constraint inside a requirement, THEN the new constraint is owned through a RequirementConstraintMembership")
@GivenSysONServer({ ExplorerViewDirectEditTestProjectData.SCRIPT_PATH })
@Test
public void testCreateConstraintInRequirement() {
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 newConstraintId = 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-ConstraintUsage");
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");
newConstraintId.set(objectId);
};

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();
assertThat(constraint.getOwningRelationship()).isInstanceOf(RequirementConstraintMembership.class);
return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalContraint.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(checkConstraintOwnership)
.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
@@ -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 @@ -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.ConstraintUsage;
import org.eclipse.syson.sysml.Definition;
import org.eclipse.syson.sysml.Documentation;
import org.eclipse.syson.sysml.Element;
Expand All @@ -27,6 +28,8 @@
import org.eclipse.syson.sysml.Membership;
import org.eclipse.syson.sysml.Namespace;
import org.eclipse.syson.sysml.Package;
import org.eclipse.syson.sysml.RequirementDefinition;
import org.eclipse.syson.sysml.RequirementUsage;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.sysml.TextualRepresentation;
import org.eclipse.syson.sysml.Usage;
Expand Down Expand Up @@ -54,6 +57,19 @@ public Optional<EClass> caseComment(Comment object) {
return Optional.of(SysmlPackage.eINSTANCE.getOwningMembership());
}

@Override
public Optional<EClass> caseConstraintUsage(ConstraintUsage object) {
Optional<EClass> intermediateContainer;
if (this.container instanceof RequirementDefinition || this.container instanceof RequirementUsage) {
// SysML v2 8.3.21.7: "A RequirementConstraintMembership is a FeatureMembership for an assumed or required
// ConstraintUsage of a RequirementDefinition or RequirementUsage."
intermediateContainer = Optional.of(SysmlPackage.eINSTANCE.getRequirementConstraintMembership());
} 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 @@ -16,7 +16,11 @@

* In _Details_ view:

** Fix an issue that allowed to edit library objects via the _Details_ view.
** Fix an issue that allowed to edit library objects via the _Details_ view.

* In the _Explorer_ view:

** When creating a `ConstraintUsage` inside a `Requirement` the new constraint is now correctly owned through a `RequirementConstraintMembership`.

== Improvements

Expand Down
Loading