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
3 changes: 2 additions & 1 deletion CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

=== Breaking changes

- [services] As part of the migration to the new diagram service architecture, the methods that were exposed by `ViewToolService` (which has been deleted) are now split between `org.eclipse.syson.diagram.services.aql.DiagramMutationAQLService` for mutation services, `org.eclipse.syson.diagram.services.aql.DiagramQueryAQLService` for diagram query and tool precondition services, and `org.eclipse.syson.tree.services.aql.TreeQueryAQLService` for selection dialog tree query services.

=== Dependency update

=== Bug fixes
Expand All @@ -17,7 +19,6 @@
=== New features

- https://github.com/eclipse-syson/syson/issues/2316[#2316] [diagrams] Add support for list item inheritance in _perform actions_ compartments
s

== v2026.7.0

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 Down Expand Up @@ -30,6 +30,8 @@
import org.eclipse.syson.services.UtilService;
import org.eclipse.syson.standard.diagrams.view.SDVDiagramDescriptionProvider;
import org.eclipse.syson.standard.diagrams.view.SDVJavaServiceProvider;
import org.eclipse.syson.tree.explorer.view.SysONExplorerJavaServiceProvider;
import org.eclipse.syson.tree.explorer.view.SysONExplorerTreeDescriptionProvider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -55,8 +57,10 @@ public void setUp() {
RepresentationDescription description = provider.create(colorProvider);
this.view.getDescriptions().add(description);
});
var sysONExplorerTreeView = new SysONExplorerTreeDescriptionProvider().createView();
this.view.getDescriptions().addAll(sysONExplorerTreeView.getDescriptions());

List<IJavaServiceProvider> javaServiceProviders = List.of(new SDVJavaServiceProvider());
List<IJavaServiceProvider> javaServiceProviders = List.of(new SDVJavaServiceProvider(), new SysONExplorerJavaServiceProvider());
this.serviceClasses = javaServiceProviders.stream()
.flatMap(provider -> provider.getServiceClasses(this.view).stream())
.collect(Collectors.toSet());
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*******************************************************************************
* 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.services;

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

import org.eclipse.emf.ecore.EClass;
import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.diagrams.Node;
import org.eclipse.syson.services.UtilService;
import org.eclipse.syson.services.api.ViewDefinitionKind;
import org.eclipse.syson.sysml.ActionDefinition;
import org.eclipse.syson.sysml.ActionUsage;
import org.eclipse.syson.sysml.Definition;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.Package;
import org.eclipse.syson.sysml.StateDefinition;
import org.eclipse.syson.sysml.StateUsage;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.sysml.Type;
import org.eclipse.syson.sysml.Usage;
import org.eclipse.syson.sysml.ViewDefinition;
import org.eclipse.syson.sysml.ViewUsage;
import org.eclipse.syson.util.StandardDiagramsConstants;
import org.springframework.stereotype.Service;

/**
* Tool-related services doing queries for diagrams.
*
* @author arichard
*/
@Service
public class DiagramQueryToolService {

private final IObjectSearchService objectSearchService;

private final UtilService utilService;

public DiagramQueryToolService(IObjectSearchService objectSearchService) {
this.objectSearchService = Objects.requireNonNull(objectSearchService);
this.utilService = new UtilService();
}

/**
* Tool precondition for control node actions (Start/Done/Decision/Fork/Join/Merge) invoked on diagram background.
*
* @param element
* the given {@link Element}.
* @return <code>true</code> if the tool should be available, <code>false</code> otherwise.
*/
public boolean isControlNodeActionCreationToolInsideActionOnAFV(Element element, IEditingContext editingContext, DiagramContext diagramContext) {
if (this.isAFVDiagram(editingContext, diagramContext)) {
var owner = this.utilService.getViewUsageOwner(element);
return owner instanceof ActionUsage || owner instanceof ActionDefinition;
}
return false;
}

/**
* Tool precondition for control node actions (Start/Done/Decision/Fork/Join/Merge) invoked on a selected node.
*
* @param editingContext
* the (non-{@code null}) {@link IEditingContext}.
* @param selectedNode
* the selected node. It corresponds to a variable accessible from the variable manager.
* @return <code>true</code> if the tool should be available, <code>false</code> otherwise.
*/
public boolean isControlNodeActionCreationToolInAction(IEditingContext editingContext, Node selectedNode) {
return this.objectSearchService.getObject(editingContext, selectedNode.getTargetObjectId())
.map(object -> {
return object instanceof ActionUsage || object instanceof ActionDefinition;
}).orElse(false);
}

/**
* Checks if a tool creating the given type should be available for the provided diagram context.
*
* @param element
* the semantic context element
* @param editingContext
* the editing context
* @param diagramContext
* the diagram context
* @param newElementType
* the type created by the tool
* @return {@code true} if the tool should be available, {@code false} otherwise
*/
public boolean toolShouldBeAvailable(Element element, IEditingContext editingContext, DiagramContext diagramContext, EClass newElementType) {
ViewDefinitionKind viewDefinitionKind = this.utilService.getViewDefinitionKind(element, List.of(), editingContext);
var elt = this.utilService.getViewUsageOwner(element);

return switch (viewDefinitionKind) {
case INTERCONNECTION_VIEW -> this.toolShouldBeAvailableOnInterconnectionView(elt, newElementType);
case ACTION_FLOW_VIEW -> this.toolShouldBeAvailableOnActionFlowView(elt, newElementType);
case STATE_TRANSITION_VIEW -> this.toolShouldBeAvailableOnStateTransitionView(elt, newElementType);
default -> this.toolShouldBeAvailableOnGeneralView(elt, newElementType);
};
}

private boolean toolShouldBeAvailableOnGeneralView(Element element, EClass domainClass) {
boolean toolShouldBeAvailable = false;
if (element instanceof Package) {
toolShouldBeAvailable = true;
} else if (element instanceof Usage && !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
} else if (element instanceof Definition && !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
}
return toolShouldBeAvailable;
}

private boolean toolShouldBeAvailableOnInterconnectionView(Element element, EClass domainClass) {
boolean toolShouldBeAvailable = false;
if (element instanceof Package) {
toolShouldBeAvailable = true;
if (SysmlPackage.eINSTANCE.getAttributeUsage().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = false;
} else if (SysmlPackage.eINSTANCE.getPortUsage().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = false;
}
} else if (element instanceof Usage && !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
} else if (element instanceof Definition && !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
}
return toolShouldBeAvailable;
}

private boolean toolShouldBeAvailableOnActionFlowView(Element element, EClass domainClass) {
boolean toolShouldBeAvailable = false;
if (element instanceof ActionUsage) {
toolShouldBeAvailable = !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass);
} else if (element instanceof ActionDefinition) {
toolShouldBeAvailable = !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass);
} else {
if (SysmlPackage.eINSTANCE.getActionUsage().equals(domainClass) || SysmlPackage.eINSTANCE.getActionUsage().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
} else if (SysmlPackage.eINSTANCE.getActionDefinition().equals(domainClass) || SysmlPackage.eINSTANCE.getActionDefinition().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
}
}
return toolShouldBeAvailable;
}

private boolean toolShouldBeAvailableOnStateTransitionView(Element element, EClass domainClass) {
boolean toolShouldBeAvailable = false;
if (element instanceof StateUsage) {
toolShouldBeAvailable = !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass);
} else if (element instanceof StateDefinition) {
toolShouldBeAvailable = !SysmlPackage.eINSTANCE.getDefinition().isSuperTypeOf(domainClass);
} else {
if (SysmlPackage.eINSTANCE.getStateUsage().equals(domainClass) || SysmlPackage.eINSTANCE.getStateUsage().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
} else if (SysmlPackage.eINSTANCE.getStateDefinition().equals(domainClass) || SysmlPackage.eINSTANCE.getStateDefinition().isSuperTypeOf(domainClass)) {
toolShouldBeAvailable = true;
}
}
return toolShouldBeAvailable;
}

private boolean isAFVDiagram(IEditingContext editingContext, DiagramContext diagramContext) {
var objectId = diagramContext.diagram().getTargetObjectId();
return this.objectSearchService.getObject(editingContext, objectId)
.map(object -> {
if (object instanceof ViewUsage viewUsage) {
if (!viewUsage.getType().isEmpty()) {
Type type = viewUsage.getType().getFirst();
return type instanceof ViewDefinition && StandardDiagramsConstants.AFV_QN.equals(type.getQualifiedName());
}
}
return false;
}).orElse(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.syson.diagram.services.DiagramMutationElementService;
import org.eclipse.syson.diagram.services.DiagramMutationExposeService;
import org.eclipse.syson.diagram.services.DiagramMutationLabelService;
import org.eclipse.syson.diagram.services.DiagramMutationToolService;
import org.eclipse.syson.sysml.BindingConnectorAsUsage;
import org.eclipse.syson.sysml.ConnectionUsage;
import org.eclipse.syson.sysml.Connector;
Expand All @@ -35,6 +36,7 @@
import org.eclipse.syson.sysml.FlowUsage;
import org.eclipse.syson.sysml.InterfaceUsage;
import org.eclipse.syson.sysml.PortUsage;
import org.eclipse.syson.sysml.RequirementUsage;
import org.eclipse.syson.sysml.SatisfyRequirementUsage;
import org.eclipse.syson.sysml.StateUsage;
import org.eclipse.syson.sysml.Type;
Expand All @@ -61,15 +63,50 @@ public class DiagramMutationAQLService {

private final DiagramMutationCompartmentService diagramMutationCompartmentService;

private final DiagramMutationToolService diagramMutationToolService;

/**
* Creates a new diagram mutation AQL service.
*
* @param diagramMutationDndService
* the diagram drag and drop mutation service
* @param diagramMutationElementService
* the diagram element mutation service
* @param diagramMutationExposeService
* the diagram exposed element mutation service
* @param diagramMutationLabelService
* the diagram label mutation service
* @param diagramMutationDiagramService
* the diagram mutation service
* @param diagramMutationCompartmentService
* the diagram compartment mutation service
* @param diagramMutationToolService
* the diagram tool mutation service
*/
public DiagramMutationAQLService(DiagramMutationDndService diagramMutationDndService, DiagramMutationElementService diagramMutationElementService,
DiagramMutationExposeService diagramMutationExposeService, DiagramMutationLabelService diagramMutationLabelService, DiagramMutationDiagramService diagramMutationDiagramService,
DiagramMutationCompartmentService diagramMutationCompartmentService) {
DiagramMutationCompartmentService diagramMutationCompartmentService, DiagramMutationToolService diagramMutationToolService) {
this.diagramMutationDndService = Objects.requireNonNull(diagramMutationDndService);
this.diagramMutationElementService = Objects.requireNonNull(diagramMutationElementService);
this.diagramMutationExposeService = Objects.requireNonNull(diagramMutationExposeService);
this.diagramMutationLabelService = Objects.requireNonNull(diagramMutationLabelService);
this.diagramMutationDiagramService = Objects.requireNonNull(diagramMutationDiagramService);
this.diagramMutationCompartmentService = Objects.requireNonNull(diagramMutationCompartmentService);
this.diagramMutationToolService = Objects.requireNonNull(diagramMutationToolService);
}

/**
* {@link DiagramMutationToolService#becomeNestedUsage(Usage, Element)}.
*/
public Usage becomeNestedUsage(Usage usage, Element newContainer) {
return this.diagramMutationToolService.becomeNestedUsage(usage, newContainer);
}

/**
* {@link DiagramMutationToolService#becomeObjectiveRequirement(RequirementUsage, Element)}.
*/
public RequirementUsage becomeObjectiveRequirement(RequirementUsage requirement, Element newContainer) {
return this.diagramMutationToolService.becomeObjectiveRequirement(requirement, newContainer);
}

/**
Expand Down Expand Up @@ -257,6 +294,34 @@ public Element expose(Element element, IEditingContext editingContext, DiagramCo
return this.diagramMutationExposeService.expose(element, editingContext, diagramContext, selectedNode, convertedNodes);
}

/**
* {@link DiagramMutationToolService#moveToClosestContainingPackage(Usage)}.
*/
public Element moveToClosestContainingPackage(Usage usage) {
return this.diagramMutationToolService.moveToClosestContainingPackage(usage);
}

/**
* {@link DiagramMutationToolService#reconnectSourceNestedActorEdge(Element, Element, Element)}.
*/
public Element reconnectSourceNestedActorEdge(Element self, Element newSource, Element otherEnd) {
return this.diagramMutationToolService.reconnectSourceNestedActorEdge(self, newSource, otherEnd);
}

/**
* {@link DiagramMutationToolService#reconnectSourceNestedStakeholderEdge(Element, Element, Element)}.
*/
public Element reconnectSourceNestedStakeholderEdge(Element self, Element newSource, Element otherEnd) {
return this.diagramMutationToolService.reconnectSourceNestedStakeholderEdge(self, newSource, otherEnd);
}

/**
* {@link DiagramMutationToolService#reconnectSourceNestedSubjectEdge(Element, Element, Element)}.
*/
public Element reconnectSourceNestedSubjectEdge(Element self, Element newSource, Element otherEnd) {
return this.diagramMutationToolService.reconnectSourceNestedSubjectEdge(self, newSource, otherEnd);
}

/**
* {@link DiagramMutationElementService#reconnectSatisfyRequirementSource(SatisfyRequirementUsage, Element)}.
*/
Expand All @@ -271,6 +336,13 @@ public SatisfyRequirementUsage reconnectSatisfyRequirementTarget(SatisfyRequirem
return this.diagramMutationElementService.reconnectSatisfyRequirementTarget(sru, newTarget);
}

/**
* {@link DiagramMutationToolService#reconnnectSourceCompositionEdge(Element, Element, Element)}.
*/
public Element reconnnectSourceCompositionEdge(Element self, Element newSource, Element otherEnd) {
return this.diagramMutationToolService.reconnnectSourceCompositionEdge(self, newSource, otherEnd);
}

/**
* {@link DiagramMutationElementService#reconnectSource(Connector, Feature, Node, Node, IEditingContext, Diagram)}.
*/
Expand All @@ -287,6 +359,27 @@ public Connector reconnectTarget(Connector connector, Feature newTarget, Node so
return this.diagramMutationElementService.reconnectTarget(connector, newTarget, sourceNode, newTargetNode, editingContext, diagram);
}

/**
* {@link DiagramMutationToolService#reconnnectTargetAnnotatedEdge(Element, Element)}.
*/
public Element reconnnectTargetAnnotatedEdge(Element self, Element newTarget) {
return this.diagramMutationToolService.reconnnectTargetAnnotatedEdge(self, newTarget);
}

/**
* {@link DiagramMutationToolService#reconnnectTargetCompositionEdge(Element, Element, Element, Element)}.
*/
public Element reconnnectTargetCompositionEdge(Element self, Element oldTarget, Element newTarget, Element otherEnd) {
return this.diagramMutationToolService.reconnnectTargetCompositionEdge(self, oldTarget, newTarget, otherEnd);
}

/**
* {@link DiagramMutationToolService#reconnectTargetNestedActorEdge(Element)}.
*/
public Element reconnectTargetNestedActorEdge(Element self) {
return this.diagramMutationToolService.reconnectTargetNestedActorEdge(self);
}

/**
* {@link DiagramMutationExposeService#removeFromExposedElements(Element, Node, IEditingContext, DiagramContext)}.
*/
Expand Down
Loading
Loading