Skip to content
Draft
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 @@ -12,6 +12,8 @@

=== Improvements

- https://github.com/eclipse-syson/syson/issues/1583[#1583] [diagrams] Improve support for `Stakeholder`.

=== New features


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,8 @@ private void createNewStakeholderIn(EClass eClassWithStakeholderParameter, Strin
Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
var initialDiagram = diagram.get();
new CheckDiagramElementCount(this.diagramComparator)
.hasNewNodeCount(1)
.hasNewNodeCount(9)
.hasNewEdgeCount(1)
.check(initialDiagram, newDiagram);
new CheckNodeInCompartment(diagramDescriptionIdProvider, this.diagramComparator)
.withParentLabel(parentNodeLabel)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023, 2025 Obeo.
* Copyright (c) 2023, 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 Down Expand Up @@ -66,13 +66,14 @@ public PartUsage getOwnedStakeholderParameter() {
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
* @generated NOT
*/
public PartUsage basicGetOwnedStakeholderParameter() {
// TODO: implement this method to return the 'Owned Stakeholder Parameter' reference
// -> do not perform proxy resolution
// Ensure that you remove @generated or mark it @generated NOT
return null;
return this.getOwnedRelatedElement().stream()
.filter(PartUsage.class::isInstance)
.map(PartUsage.class::cast)
.findFirst()
.orElse(null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*******************************************************************************/
package org.eclipse.syson.sysml.impl;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.List;
Expand All @@ -21,6 +22,7 @@
import org.eclipse.syson.sysml.PartUsage;
import org.eclipse.syson.sysml.RequirementDefinition;
import org.eclipse.syson.sysml.StakeholderMembership;
import org.eclipse.syson.sysml.SubjectMembership;
import org.eclipse.syson.sysml.SysmlFactory;
import org.eclipse.syson.sysml.SysmlPackage;
import org.junit.jupiter.api.Assertions;
Expand Down Expand Up @@ -61,16 +63,35 @@ public static void setUpRequirementDefinition() {

@Test
public void testGetActorParameter() {
// Check that we can find the actors from the Requirement
final List<PartUsage> actorParameterValue = REQUIREMENT_DEFINITION.getActorParameter();
Assertions.assertNotNull(actorParameterValue);
Assertions.assertIterableEquals(ACTOR_PART_USAGES, actorParameterValue);

// Also check that we can get them directly from the ActorMembership themselves
List<PartUsage> actors = REQUIREMENT_DEFINITION.getOwnedMembership().stream()
.filter(ActorMembership.class::isInstance)
.map(ActorMembership.class::cast)
.map(ActorMembership::getOwnedActorParameter)
.toList();
Assertions.assertIterableEquals(ACTOR_PART_USAGES, actors);
}

@Test
public void testGetStakeholderParameter() {
// Check that we can find the stakeholders from the Requirement
final List<PartUsage> stakeholderParameterValue = REQUIREMENT_DEFINITION.getStakeholderParameter();
Assertions.assertNotNull(stakeholderParameterValue);
Assertions.assertIterableEquals(STAKEHOLDER_PART_USAGES, stakeholderParameterValue);

// Also check that we can get them directly from the StakeholderMembership themselves
List<PartUsage> stakeholders = REQUIREMENT_DEFINITION.getOwnedMembership().stream()
.filter(StakeholderMembership.class::isInstance)
.map(StakeholderMembership.class::cast)
.map(StakeholderMembership::getOwnedStakeholderParameter)
.toList();
Assertions.assertIterableEquals(STAKEHOLDER_PART_USAGES, stakeholders);
assertThat(stakeholders).hasSameElementsAs(STAKEHOLDER_PART_USAGES);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,11 @@ public Optional<String> getNodeDescriptionId(Element element, Diagram diagram, I
.filter(nodeDesc -> nodeDesc.getName().equals("GV Node " + SysmlPackage.eINSTANCE.getPackage().getName()))
.map(nodeDesc -> this.diagramIdProvider.getId(nodeDesc))
.findFirst();
} else if (this.metamodelQueryElementService.isStakeholder(element)) {
nodeDescriptionId = EMFUtils.allContainedObjectOfType(optViewDD.get(), org.eclipse.sirius.components.view.diagram.NodeDescription.class)
.filter(nodeDesc -> nodeDesc.getName().equals("GV Node Stakeholder"))
.map(nodeDesc -> this.diagramIdProvider.getId(nodeDesc))
.findFirst();
} else {
nodeDescriptionId = EMFUtils.allContainedObjectOfType(optViewDD.get(), org.eclipse.sirius.components.view.diagram.NodeDescription.class)
.filter(nodeDesc -> nodeDesc.getName().equals("GV Node " + element.eClass().getName()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ public boolean isActor(Element element) {
return this.metamodelQueryElementService.isActor(element);
}

/**
* {@link MetamodelQueryElementService#isStakeholder(Element)}.
*/
public boolean isStakeholder(Element element) {
return this.metamodelQueryElementService.isStakeholder(element);
}

/**
* {@link MetamodelQueryElementService#isSubject(Element)}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.syson.sysml.FeatureValue;
import org.eclipse.syson.sysml.PartUsage;
import org.eclipse.syson.sysml.ReferenceUsage;
import org.eclipse.syson.sysml.StakeholderMembership;
import org.eclipse.syson.sysml.SubjectMembership;

/**
Expand Down Expand Up @@ -63,6 +64,20 @@ public boolean isSubject(Element element) {
return element instanceof ReferenceUsage && element.getOwningMembership() instanceof SubjectMembership;
}

/**
* Return {@code true} if the provided {@code element} is a stakeholder, {@code false} otherwise.
* <p>
* A stakeholder is a kind of parameter stored in an {@link StakeholderMembership}.
* </p>
*
* @param element
* the element to check
* @return {@code true} if the provided {@code element} is an stakeholder, {@code false} otherwise
*/
public boolean isStakeholder(Element element) {
return element instanceof PartUsage && element.getOwningMembership() instanceof StakeholderMembership;
}

/**
* Get the source of a {@link Connector}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.eclipse.syson.diagram.services.aql.DiagramQueryAQLService;
import org.eclipse.syson.services.DeleteService;
import org.eclipse.syson.services.UtilService;
import org.eclipse.syson.util.AQLConstants;
import org.eclipse.syson.util.IDescriptionNameGenerator;
import org.eclipse.syson.util.ServiceMethod;
import org.eclipse.syson.util.SysMLMetamodelHelper;
Expand Down Expand Up @@ -168,6 +169,7 @@ public NodeDescription create() {
.collapsible(true)
.defaultHeightExpression(defaultSizeExpression.defaultHeightExpression())
.defaultWidthExpression(defaultSizeExpression.defaultWidthExpression())
.isHiddenByDefaultExpression(this.getHiddenByDefaultExpression())
.domainType(domainType)
.insideLabel(this.createInsideLabelDescription())
.outsideLabels(this.createOutsideLabelDescriptions().toArray(OutsideLabelDescription[]::new))
Expand Down Expand Up @@ -202,6 +204,10 @@ public void link(DiagramDescription diagramDescription, IViewDiagramElementFinde
});
}

protected String getHiddenByDefaultExpression() {
return AQLConstants.AQL_FALSE;
}

protected InsideLabelDescription createInsideLabelDescription() {
return this.diagramBuilderHelper.newInsideLabelDescription()
.labelExpression(ServiceMethod.of0(DiagramQueryAQLService::getContainerLabel).aqlSelf())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,30 @@ public List<PartUsage> getExposedActors(Element element, EClass domainType, List
.toList();
}

/**
* Get all Stakeholder ({@link PartUsage}) in {@link ViewUsage}'s exposed elements.
*
* @param element
* the {@link Element} for which we want the Stakeholders.
* @param domainType
* the domain type to the elements to retrieve
* @param ancestors
* the given ancestors (semantic elements of the graphical nodes that are the ancestors) of the Node on
* which this service has been called.
* @param editingContext
* the given {@link IEditingContext} in which this service has been called.
* @param diagramContext
* the given {@link DiagramContext} in which this service has been called.
* @return the list of Actor {@link PartUsage}s in {@link ViewUsage}'s exposed elements.
*/
public List<PartUsage> getExposedStakeholders(Element element, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext) {
return this.getExposedElements(element, domainType, ancestors, editingContext, diagramContext).stream()
.filter(PartUsage.class::isInstance)
.map(PartUsage.class::cast)
.filter(this.metamodelQueryElementService::isStakeholder)
.toList();
}

/**
* Get all Subjects ({@link ReferenceUsage}) in {@link ViewUsage}'s exposed elements.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import org.eclipse.syson.sysml.PartUsage;
import org.eclipse.syson.sysml.RequirementDefinition;
import org.eclipse.syson.sysml.RequirementUsage;
import org.eclipse.syson.sysml.StakeholderMembership;
import org.eclipse.syson.sysml.StateDefinition;
import org.eclipse.syson.sysml.StateUsage;
import org.eclipse.syson.sysml.SubjectMembership;
Expand Down Expand Up @@ -236,6 +237,38 @@ public Element reconnectSourceNestedActorEdge(Element self, Element newSource, E
return otherEnd;
}

/**
* Reconnects the source of a nested stakeholder edge.
* <p>
* The source of this edge is a Requirement, and can only be reconnected to Requirements.
* </p>
*
* @param self
* the current Requirement
* @param newSource
* the new Requirement
* @param otherEnd
* the Stakeholder connected to the Requirement
* @return the Stakeholder
*/
public Element reconnectSourceNestedStakeholderEdge(Element self, Element newSource, Element otherEnd) {
if (newSource instanceof RequirementUsage || newSource instanceof RequirementDefinition) {
if (otherEnd.getOwningMembership() instanceof StakeholderMembership stakeholderMembership) {
newSource.getOwnedRelationship().add(stakeholderMembership);
} else {
// This is an error, an Stakeholder should always be contained in an StakeholderMembership.
String errorMessage = "Cannot reconnect the Stakeholder, it is not owned by an " + StakeholderMembership.class.getSimpleName();
this.logger.error(errorMessage);
this.feedbackMessageService.addFeedbackMessage(new Message(errorMessage, MessageLevel.ERROR));
}
} else {
String errorMessage = "Cannot reconnect an Stakeholder to non-Requirement element";
this.logger.warn(errorMessage);
this.feedbackMessageService.addFeedbackMessage(new Message(errorMessage, MessageLevel.WARNING));
}
return otherEnd;
}

/**
* Reconnects the source of a nested subject edge.
* <p>
Expand Down
Loading
Loading