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 @@ -81,6 +81,7 @@ It is also now possible to create new concerns using the _New Concern_ tool from
- https://github.com/eclipse-syson/syson/issues/2397[#2397] [diagrams] Display existing binary requirement derivations as edges in the _General View_.
A requirement derivation is a `ConnectionUsage` annotated with the `#derivation` metadata or typed by `DerivationConnections::Derivation`.
The edge goes from the derived requirement to the original one and is displayed as a dashed `«derive»` line, so it can be distinguished from a `«satisfy»` edge.
- https://github.com/eclipse-syson/syson/issues/2403[#2403] [diagrams] Add support for the inheritance of `ItemUsage` border nodes on `ActionDefinition` and `ActionUsage` graphical nodes.

== v2026.7.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,8 @@ private List<String> getExpectedFlowTargetDescriptionNames() {
this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedPort()),
this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem()),
this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem()),
this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem()),
this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem()),
this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage()),
this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,11 @@ private static Stream<Arguments> actionsCompartmentItemInheritanceArguments() {
private static Stream<Arguments> itemsCompartmentItemInheritanceArguments() {
NestedElementTestArgument nestedItemWithBorderNode = new NestedElementTestArgument("New Item", "items", "item1", "", 1, 1, 0);
return Stream.of(
Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, FEATURE_TYPING_ARGUMENT),
Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_DEFINITION_ARGUMENT, SUBCLASSIFICATION_ARGUMENT),
Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, SUBSETTING_ARGUMENT),
Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REFERENCE_SUBSETTING_ARGUMENT),
Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REDEFINITION_ARGUMENT),
Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, FEATURE_TYPING_ARGUMENT.withExtraBorderNodes(1)),
Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_DEFINITION_ARGUMENT, SUBCLASSIFICATION_ARGUMENT.withExtraBorderNodes(1)),
Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, SUBSETTING_ARGUMENT.withExtraBorderNodes(1)),
Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REFERENCE_SUBSETTING_ARGUMENT.withExtraBorderNodes(1)),
Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REDEFINITION_ARGUMENT.withExtraBorderNodes(1)),
Arguments.of(PORT_USAGE_ARGUMENT, nestedItemWithBorderNode, PORT_USAGE_ARGUMENT, SUBSETTING_ARGUMENT),
Arguments.of(PORT_USAGE_ARGUMENT, nestedItemWithBorderNode, PORT_USAGE_ARGUMENT, REFERENCE_SUBSETTING_ARGUMENT),
Arguments.of(PORT_DEFINITION_ARGUMENT, nestedItemWithBorderNode, PORT_DEFINITION_ARGUMENT, SUBCLASSIFICATION_ARGUMENT)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*******************************************************************************
* Copyright (c) 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.diagram.common.view.nodes;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.eclipse.emf.ecore.EReference;
import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder;
import org.eclipse.sirius.components.view.builder.providers.IColorProvider;
import org.eclipse.sirius.components.view.diagram.ConditionalNodeStyle;
import org.eclipse.sirius.components.view.diagram.DiagramDescription;
import org.eclipse.sirius.components.view.diagram.EdgeTool;
import org.eclipse.sirius.components.view.diagram.NodeDescription;
import org.eclipse.sirius.components.view.diagram.NodePalette;
import org.eclipse.sirius.components.view.diagram.NodeStyleDescription;
import org.eclipse.sirius.components.view.diagram.OutsideLabelDescription;
import org.eclipse.sirius.components.view.diagram.OutsideLabelStyle;
import org.eclipse.sirius.components.view.diagram.SynchronizationPolicy;
import org.eclipse.sirius.components.view.diagram.UserResizableDirection;
import org.eclipse.syson.diagram.common.view.services.ViewEdgeToolService;
import org.eclipse.syson.services.UtilService;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.util.AQLConstants;
import org.eclipse.syson.util.IDescriptionNameGenerator;
import org.eclipse.syson.util.ServiceMethod;
import org.eclipse.syson.util.SysMLMetamodelHelper;
import org.eclipse.syson.util.ViewConstants;

/**
* Common behavior for all item usage border node description.
*
* @author gcoutabe
*/
public abstract class AbstractItemUsageBorderNodeDescriptionProvider extends AbstractNodeDescriptionProvider {

protected final IDescriptionNameGenerator descriptionNameGenerator;

protected final EReference eReference;

public AbstractItemUsageBorderNodeDescriptionProvider(EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) {
super(colorProvider);
this.eReference = Objects.requireNonNull(eReference);
this.descriptionNameGenerator = Objects.requireNonNull(descriptionNameGenerator);
}

protected abstract String getSemanticCandidatesExpression();

protected abstract String getName();

protected abstract OutsideLabelDescription createOutsideLabelDescription();

protected abstract List<EdgeTool> getEdgeTools(IViewDiagramElementFinder cache, NodeDescription nodeDescription);

protected abstract NodePalette createNodePalette(IViewDiagramElementFinder cache, NodeDescription nodeDescription);

@Override
public NodeDescription create() {
String domainType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getItemUsage());
return this.diagramBuilderHelper.newNodeDescription()
.defaultHeightExpression("10")
.defaultWidthExpression("10")
.domainType(domainType)
.outsideLabels(this.createOutsideLabelDescription())
.name(this.getName())
.semanticCandidatesExpression(this.getSemanticCandidatesExpression())
.style(this.createItemUnsetNodeStyle())
.conditionalStyles(this.createItemUsageConditionalNodeStyles().toArray(ConditionalNodeStyle[]::new))
.userResizable(UserResizableDirection.NONE)
.synchronizationPolicy(SynchronizationPolicy.SYNCHRONIZED)
.build();
}

protected IDescriptionNameGenerator getDescriptionNameGenerator() {
return this.descriptionNameGenerator;
}

private NodeStyleDescription createItemUnsetNodeStyle() {
return this.diagramBuilderHelper.newRectangularNodeStyleDescription()
.borderColor(this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR))
.borderRadius(0)
.background(this.colorProvider.getColor(ViewConstants.DEFAULT_BACKGROUND_COLOR))
.build();
}

protected OutsideLabelStyle createOutsideLabelStyle() {
return this.diagramBuilderHelper.newOutsideLabelStyle()
.bold(false)
.borderSize(0)
.fontSize(12)
.italic(false)
.labelColor(this.colorProvider.getColor(ViewConstants.DEFAULT_LABEL_COLOR))
.showIconExpression(AQLConstants.AQL_FALSE)
.strikeThrough(false)
.underline(false)
.build();
}

private List<ConditionalNodeStyle> createItemUsageConditionalNodeStyles() {
var borderColor = this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR);
return List.of(
this.diagramBuilderHelper.newConditionalNodeStyle()
.condition(ServiceMethod.of0(UtilService::isInFeature).aqlSelf())
.style(this.createImageNodeStyleDescription("/images/feature_in.svg", borderColor, true))
.build(),
this.diagramBuilderHelper.newConditionalNodeStyle()
.condition(ServiceMethod.of0(UtilService::isOutFeature).aqlSelf())
.style(this.createImageNodeStyleDescription("/images/feature_out.svg", borderColor, true))
.build(),
this.diagramBuilderHelper.newConditionalNodeStyle()
.condition(ServiceMethod.of0(UtilService::isInOutFeature).aqlSelf())
.style(this.createImageNodeStyleDescription("/images/feature_inout.svg", borderColor, true))
.build());
}

@Override
public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) {
var optItemUsageBorderNodeDescription = cache.getNodeDescription(this.getName());

NodeDescription nodeDescription = optItemUsageBorderNodeDescription.get();
nodeDescription.setPalette(this.createNodePalette(cache, nodeDescription));
}

private List<NodeDescription> getBindingConnectorAsUsageToolTarget(IViewDiagramElementFinder cache) {
var nodeDescriptions = new ArrayList<NodeDescription>();
cache.getNodeDescription(this.getName()).ifPresent(nodeDescriptions::add);
cache.getNodeDescription(this.getDescriptionNameGenerator().getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), this.eReference)).ifPresent(nodeDescriptions::add);
return nodeDescriptions;
}

protected EdgeTool createBindingConnectorAsUsageEdgeTool(IViewDiagramElementFinder cache) {
return this.getViewEdgeToolService(cache).createBindingConnectorAsUsageEdgeTool(this.getBindingConnectorAsUsageToolTarget(cache));
}

protected EdgeTool createFlowUsageEdgeTool(IViewDiagramElementFinder cache) {
return this.getViewEdgeToolService(cache).createFlowUsageEdgeTool(this.getFlowUsageToolTargetDescriptions(cache, this.descriptionNameGenerator));
}

protected ViewEdgeToolService getViewEdgeToolService(IViewDiagramElementFinder cache) {
return new ViewEdgeToolService(this.viewBuilderHelper, this.diagramBuilderHelper, cache.getNodeDescriptions(), this.descriptionNameGenerator);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ protected List<NodeDescription> getFlowUsageToolTargetDescriptions(IViewDiagramE
cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedPort())).ifPresent(nodes::add);
cache.getNodeDescription(descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add);
cache.getNodeDescription(descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add);
cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add);
cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add);
cache.getNodeDescription(descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(nodes::add);
cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(nodes::add);
return nodes;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.diagram.common.view.nodes;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.ecore.EReference;
import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder;
import org.eclipse.sirius.components.view.builder.providers.IColorProvider;
import org.eclipse.sirius.components.view.diagram.EdgeTool;
import org.eclipse.sirius.components.view.diagram.NodeDescription;
import org.eclipse.sirius.components.view.diagram.NodePalette;
import org.eclipse.sirius.components.view.diagram.OutsideLabelDescription;
import org.eclipse.sirius.components.view.diagram.OutsideLabelPosition;
import org.eclipse.syson.diagram.services.aql.DiagramQueryAQLService;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.util.AQLConstants;
import org.eclipse.syson.util.AQLUtils;
import org.eclipse.syson.util.IDescriptionNameGenerator;
import org.eclipse.syson.util.ServiceMethod;

/**
* Used to create the inherited item usage border node description.
*
* @author gcoutable
*/
public class InheritedItemUsageBorderNodeDescriptionProvider extends AbstractItemUsageBorderNodeDescriptionProvider {

public InheritedItemUsageBorderNodeDescriptionProvider(EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) {
super(eReference, colorProvider, descriptionNameGenerator);
}

@Override
protected String getSemanticCandidatesExpression() {
return ServiceMethod.of1(DiagramQueryAQLService::getInheritedCompartmentItems).aqlSelf(AQLUtils.aqlString(this.eReference.getName()));
}

@Override
protected String getName() {
return this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), this.eReference);
}

@Override
protected OutsideLabelDescription createOutsideLabelDescription() {
return this.diagramBuilderHelper.newOutsideLabelDescription()
.labelExpression(AQLConstants.AQL + "'^' + self.getBorderNodeUsageLabel()")
.position(OutsideLabelPosition.BOTTOM_CENTER)
.style(this.createOutsideLabelStyle())
.build();
}

@Override
protected List<EdgeTool> getEdgeTools(IViewDiagramElementFinder cache, NodeDescription nodeDescription) {
List<EdgeTool> edgeTools = new ArrayList<>();
edgeTools.add(this.createBindingConnectorAsUsageEdgeTool(cache));
edgeTools.add(this.createFlowUsageEdgeTool(cache));
return edgeTools;
}

@Override
protected NodePalette createNodePalette(IViewDiagramElementFinder cache, NodeDescription nodeDescription) {
return this.diagramBuilderHelper.newNodePalette()
.toolSections(this.defaultToolsFactory.createDefaultHideRevealNodeToolSection())
.edgeTools(this.getEdgeTools(cache, nodeDescription).toArray(EdgeTool[]::new))
.build();
}
}
Loading
Loading