Skip to content

Commit 763b0aa

Browse files
committed
[cleanup] Move ViewNodeService services in syson-diagram-services
Signed-off-by: Axel RICHARD <axel.richard@obeo.fr>
1 parent 83347e2 commit 763b0aa

29 files changed

Lines changed: 837 additions & 870 deletions

CHANGELOG.adoc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@ As a result, the following GraphQL mutations have been removed `exposeRequiremen
1616
- https://github.com/eclipse-syson/syson/issues/2045[#2045] [diagrams] The service `ViewNodeService#revealCompartment` has been changed to reveal a compartment only when it is needed.
1717
+ Only reveal a compartment of a node when none of the revealed compartment can display the `targetElement`.
1818
+ If many compartment candidates exist, choose the first free form compartment.
19+
- [services] As part of the migration to the new diagram service architecture, the following methods have been moved out of `ViewNodeService`:
20+
+
21+
** `List<Element> getExposedElements(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.getExposedElements(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)`
22+
** `List<Element> getExposedElements(Element self, Element parent, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.getExposedElements(Element self, Element parent, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)`
23+
** `boolean isView(Element self, String viewDefinition, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.isView(Element self, String viewDefinition, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)`
24+
** `boolean isView(Element self, String viewDefinition, Node selectedNode, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.isView(Element self, String viewDefinition, Node selectedNode, IEditingContext editingContext, DiagramContext diagramContext)`
25+
** `boolean isHiddenByDefault(Element self, String compartmentName, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.isHiddenByDefault(Element self, String compartmentName, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)`
26+
** `List<PartUsage> getExposedActors(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.getExposedActors(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)`
27+
** `List<PartUsage> getExposedStakeholders(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.getExposedStakeholders(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)`
28+
** `List<ReferenceUsage> getExposedSubjects(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)` to `DiagramQueryAQLService.getExposedSubjects(Element self, EClass domainType, List<Object> ancestors, IEditingContext editingContext, DiagramContext diagramContext)`
29+
** `List<Element> getAllReachableRequirements(EObject self)` to `DiagramQueryAQLService.getAllReachableRequirements(EObject self)`
30+
** `boolean showAnnotatingNode(Element self, DiagramContext diagramContext, IEditingContext editingContext)` to `DiagramQueryAQLService.showAnnotatingNode(Element self, DiagramContext diagramContext, IEditingContext editingContext)`
31+
** `Node revealCompartment(Node selectedNode, Element targetElement, DiagramContext diagramContext, IEditingContext editingContext, Map<org.eclipse.sirius.components.view.diagram.NodeDescription, org.eclipse.sirius.components.diagrams.description.NodeDescription> convertedNodes)` to `DiagramMutationAQLService.revealCompartment(Node selectedNode, Element targetElement, DiagramContext diagramContext, IEditingContext editingContext, Map<org.eclipse.sirius.components.view.diagram.NodeDescription, org.eclipse.sirius.components.diagrams.description.NodeDescription> convertedNodes)`
32+
** `org.eclipse.syson.diagram.common.view.services.ViewFilterSwitch` to `org.eclipse.syson.diagram.services.utils.ViewFilterSwitch`
33+
** `org.eclipse.syson.diagram.common.view.services.RevealCompartmentSwitch` to `org.eclipse.syson.diagram.services.utils.RevealCompartmentSwitch`
34+
+
35+
`ViewNodeService` now only keeps `isAncestorOf(...)` for the remaining edge precondition use cases.
1936

2037
=== Dependency update
2138

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.diagram.services;
14+
15+
import java.util.List;
16+
import java.util.Map;
17+
import java.util.Objects;
18+
import java.util.stream.Stream;
19+
20+
import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext;
21+
import org.eclipse.sirius.components.collaborative.diagrams.DiagramService;
22+
import org.eclipse.sirius.components.collaborative.diagrams.DiagramServices;
23+
import org.eclipse.sirius.components.core.api.IEditingContext;
24+
import org.eclipse.sirius.components.core.api.IObjectSearchService;
25+
import org.eclipse.sirius.components.diagrams.FreeFormLayoutStrategy;
26+
import org.eclipse.sirius.components.diagrams.ListLayoutStrategy;
27+
import org.eclipse.sirius.components.diagrams.Node;
28+
import org.eclipse.sirius.components.diagrams.ViewModifier;
29+
import org.eclipse.sirius.components.diagrams.description.NodeDescription;
30+
import org.eclipse.syson.diagram.services.utils.RevealCompartmentSwitch;
31+
import org.eclipse.syson.services.NodeDescriptionService;
32+
import org.eclipse.syson.services.UtilService;
33+
import org.eclipse.syson.sysml.Element;
34+
import org.eclipse.syson.util.NodeFinder;
35+
import org.eclipse.syson.util.StandardDiagramsConstants;
36+
import org.springframework.stereotype.Service;
37+
38+
/**
39+
* Mutation services related to diagram compartments.
40+
*
41+
* @author arichard
42+
*/
43+
@Service
44+
public class DiagramMutationCompartmentService {
45+
46+
private final IObjectSearchService objectSearchService;
47+
48+
private final UtilService utilService;
49+
50+
private final DiagramQueryViewService diagramQueryViewService;
51+
52+
public DiagramMutationCompartmentService(IObjectSearchService objectSearchService, DiagramQueryViewService diagramQueryViewService) {
53+
this.objectSearchService = Objects.requireNonNull(objectSearchService);
54+
this.utilService = new UtilService();
55+
this.diagramQueryViewService = Objects.requireNonNull(diagramQueryViewService);
56+
}
57+
58+
/**
59+
* Reveals the compartment in {@code node} that can display {@code targetElement}.
60+
*/
61+
public Node revealCompartment(Node node, Element targetElement, DiagramContext diagramContext, IEditingContext editingContext,
62+
Map<org.eclipse.sirius.components.view.diagram.NodeDescription, NodeDescription> convertedNodes) {
63+
64+
if (!this.utilService.isUnsynchronized(targetElement)
65+
&& !this.needToRevealCompartment(targetElement, this.diagramQueryViewService.isView(targetElement, StandardDiagramsConstants.GV_QN, node, editingContext, diagramContext))) {
66+
return node;
67+
}
68+
var nodeDescription = convertedNodes.values().stream()
69+
.filter(nodeDesc -> Objects.equals(nodeDesc.getId(), node.getDescriptionId()))
70+
.findFirst();
71+
72+
List<NodeDescription> allChildNodeDescriptions = nodeDescription.map(nodeDesc -> Stream.concat(
73+
nodeDesc.getChildNodeDescriptions().stream(),
74+
convertedNodes.values().stream().filter(convNode -> nodeDesc.getReusedChildNodeDescriptionIds().contains(convNode.getId())))
75+
.toList())
76+
.orElse(List.of());
77+
78+
var parentObject = this.objectSearchService.getObject(editingContext, node.getTargetObjectId()).orElse(null);
79+
NodeDescriptionService nodeDescriptionService = new NodeDescriptionService(this.objectSearchService);
80+
81+
var compartmentDescriptionCandidates = nodeDescriptionService.getNodeDescriptionsForRenderingElementAsChild(targetElement, parentObject, allChildNodeDescriptions,
82+
convertedNodes, editingContext, diagramContext).stream()
83+
.map(NodeDescription::getId)
84+
.toList();
85+
86+
if (!compartmentDescriptionCandidates.isEmpty()) {
87+
NodeFinder nodeFinder = new NodeFinder(diagramContext.diagram());
88+
List<Node> compartmentNodeCandidates = nodeFinder
89+
.getAllNodesMatching(n -> compartmentDescriptionCandidates.stream().anyMatch(id -> Objects.equals(id, n.getDescriptionId()))
90+
&& Objects.equals(n.getTargetObjectId(), node.getTargetObjectId()));
91+
var noCompartmentToHandleTargetElement = compartmentNodeCandidates.stream()
92+
.allMatch(candidate -> ViewModifier.Hidden.equals(candidate.getState()));
93+
if (noCompartmentToHandleTargetElement) {
94+
compartmentNodeCandidates.stream().reduce((previousCandidate, newCandidate) -> {
95+
if (previousCandidate.getStyle().getChildrenLayoutStrategy() instanceof ListLayoutStrategy && newCandidate.getStyle().getChildrenLayoutStrategy() instanceof FreeFormLayoutStrategy) {
96+
return newCandidate;
97+
}
98+
return previousCandidate;
99+
}).ifPresent(compartmentToReveal -> new DiagramServices().reveal(new DiagramService(diagramContext), List.of(compartmentToReveal)));
100+
}
101+
}
102+
return node;
103+
}
104+
105+
private boolean needToRevealCompartment(Element element, boolean isGeneralView) {
106+
return new RevealCompartmentSwitch(isGeneralView).doSwitch(element);
107+
}
108+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.diagram.services;
14+
15+
import java.util.List;
16+
import java.util.Objects;
17+
import java.util.Optional;
18+
import java.util.stream.Stream;
19+
20+
import org.eclipse.emf.common.util.EList;
21+
import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext;
22+
import org.eclipse.sirius.components.core.api.IEditingContext;
23+
import org.eclipse.sirius.components.core.api.IObjectSearchService;
24+
import org.eclipse.sirius.components.diagrams.Edge;
25+
import org.eclipse.sirius.components.diagrams.IDiagramElement;
26+
import org.eclipse.sirius.components.diagrams.Node;
27+
import org.eclipse.syson.sysml.AnnotatingElement;
28+
import org.eclipse.syson.sysml.Element;
29+
import org.eclipse.syson.sysml.ViewUsage;
30+
import org.springframework.stereotype.Service;
31+
32+
/**
33+
* Query services related to annotating nodes.
34+
*
35+
* @author arichard
36+
*/
37+
@Service
38+
public class DiagramQueryAnnotatingService {
39+
40+
private final IObjectSearchService objectSearchService;
41+
42+
public DiagramQueryAnnotatingService(IObjectSearchService objectSearchService) {
43+
this.objectSearchService = Objects.requireNonNull(objectSearchService);
44+
}
45+
46+
/**
47+
* Returns {@code true} if the provided annotated element of the given {@code element} is represented on the
48+
* diagram, {@code false} otherwise.
49+
*/
50+
public boolean showAnnotatingNode(Element element, DiagramContext diagramContext, IEditingContext editingContext) {
51+
boolean displayAnnotatingNode = false;
52+
if (element instanceof AnnotatingElement ae && diagramContext != null && editingContext != null) {
53+
EList<Element> annotatedElements = ae.getAnnotatedElement();
54+
IDiagramElement matchingDiagramElement = null;
55+
56+
displayAnnotatingNode = this.isAnnotatingNodeOnRoot(diagramContext, editingContext, annotatedElements);
57+
58+
if (!displayAnnotatingNode) {
59+
for (Node node : diagramContext.diagram().getNodes()) {
60+
matchingDiagramElement = this.getOneMatchingAnnotatedNode(node, annotatedElements, diagramContext, editingContext);
61+
if (matchingDiagramElement != null) {
62+
displayAnnotatingNode = true;
63+
break;
64+
}
65+
}
66+
}
67+
if (!displayAnnotatingNode) {
68+
for (Edge edge : diagramContext.diagram().getEdges()) {
69+
matchingDiagramElement = this.getOneMatchingAnnotatedEdge(edge, annotatedElements, diagramContext, editingContext);
70+
if (matchingDiagramElement != null) {
71+
displayAnnotatingNode = true;
72+
break;
73+
}
74+
}
75+
}
76+
} else {
77+
displayAnnotatingNode = true;
78+
}
79+
return displayAnnotatingNode;
80+
}
81+
82+
private boolean isAnnotatingNodeOnRoot(DiagramContext diagramContext, IEditingContext editingContext, EList<Element> annotatedElements) {
83+
boolean isAnnotatingNodeOnRoot = false;
84+
String diagramTargetObjectId = diagramContext.diagram().getTargetObjectId();
85+
Element diagramTargetObject = this.objectSearchService.getObject(editingContext, diagramTargetObjectId).stream()
86+
.filter(Element.class::isInstance)
87+
.map(Element.class::cast)
88+
.findFirst()
89+
.orElse(null);
90+
if (diagramTargetObject instanceof ViewUsage viewUsage) {
91+
if (annotatedElements.contains(viewUsage)) {
92+
isAnnotatingNodeOnRoot = true;
93+
} else {
94+
isAnnotatingNodeOnRoot = annotatedElements.contains(viewUsage.getOwner());
95+
}
96+
}
97+
return isAnnotatingNodeOnRoot;
98+
}
99+
100+
private Edge getOneMatchingAnnotatedEdge(Edge edge, List<Element> annotatedElements, DiagramContext diagramContext, IEditingContext editingContext) {
101+
Edge matchingAnnotatedEdge = null;
102+
Optional<Object> semanticNodeOpt = this.objectSearchService.getObject(editingContext, edge.getTargetObjectId());
103+
if (semanticNodeOpt.isPresent()) {
104+
if (annotatedElements.contains(semanticNodeOpt.get())) {
105+
boolean isDeletingAnnotatingEdge = diagramContext.viewDeletionRequests().stream()
106+
.anyMatch(viewDeletionRequest -> Objects.equals(viewDeletionRequest.getElementId(), edge.getId()));
107+
if (!isDeletingAnnotatingEdge) {
108+
matchingAnnotatedEdge = edge;
109+
}
110+
return matchingAnnotatedEdge;
111+
}
112+
}
113+
return matchingAnnotatedEdge;
114+
}
115+
116+
private Node getOneMatchingAnnotatedNode(Node node, List<Element> annotatedElements, DiagramContext diagramContext, IEditingContext editingContext) {
117+
Node matchingAnnotatedNode = null;
118+
Optional<Object> semanticNodeOpt = this.objectSearchService.getObject(editingContext, node.getTargetObjectId());
119+
if (semanticNodeOpt.isPresent()) {
120+
if (annotatedElements.contains(semanticNodeOpt.get())) {
121+
boolean isDeletingAnnotatingNode = diagramContext.viewDeletionRequests().stream()
122+
.anyMatch(viewDeletionRequest -> Objects.equals(viewDeletionRequest.getElementId(), node.getId()));
123+
if (!isDeletingAnnotatingNode) {
124+
matchingAnnotatedNode = node;
125+
}
126+
return matchingAnnotatedNode;
127+
}
128+
}
129+
matchingAnnotatedNode = this.getFirstMatchingChildAnnotatedNode(node, annotatedElements, diagramContext, editingContext);
130+
return matchingAnnotatedNode;
131+
}
132+
133+
private Node getFirstMatchingChildAnnotatedNode(Node node, List<Element> annotatedElements, DiagramContext diagramContext, IEditingContext editingContext) {
134+
List<Node> childrenNodes = Stream.concat(node.getChildNodes().stream(), node.getBorderNodes().stream()).toList();
135+
for (Node childNode : childrenNodes) {
136+
Node matchingChildAnnotatedNode = this.getOneMatchingAnnotatedNode(childNode, annotatedElements, diagramContext, editingContext);
137+
if (matchingChildAnnotatedNode != null) {
138+
return matchingChildAnnotatedNode;
139+
}
140+
}
141+
return null;
142+
}
143+
}

0 commit comments

Comments
 (0)