Skip to content

Commit 2fdbed1

Browse files
committed
[1314] Update ViewUsage#exposedElement when manipulating GeneralView
Bug: #1314 Signed-off-by: Axel RICHARD <axel.richard@obeo.fr>
1 parent 3d33a28 commit 2fdbed1

File tree

4 files changed

+268
-3
lines changed

4 files changed

+268
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 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.common.view.services.handlers;
14+
15+
import java.util.Objects;
16+
import java.util.Optional;
17+
18+
import org.eclipse.sirius.components.collaborative.api.ChangeDescription;
19+
import org.eclipse.sirius.components.collaborative.api.IInputPreProcessor;
20+
import org.eclipse.sirius.components.collaborative.api.IRepresentationEventProcessor;
21+
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
22+
import org.eclipse.sirius.components.collaborative.diagrams.dto.LayoutDiagramInput;
23+
import org.eclipse.sirius.components.collaborative.editingcontext.EditingContextEventProcessorRegistry;
24+
import org.eclipse.sirius.components.core.api.IEditingContext;
25+
import org.eclipse.sirius.components.core.api.IInput;
26+
import org.eclipse.sirius.web.application.editingcontext.EditingContext;
27+
import org.springframework.context.ApplicationContext;
28+
import org.springframework.stereotype.Service;
29+
30+
import reactor.core.publisher.Sinks;
31+
import reactor.core.publisher.Sinks.Many;
32+
33+
/**
34+
* Tests.
35+
*
36+
* @author arichard
37+
*/
38+
@Service
39+
public class SynchronizeExposedElementsInputProcessor implements IInputPreProcessor {
40+
41+
private final ApplicationContext applicationContext;
42+
43+
public SynchronizeExposedElementsInputProcessor(ApplicationContext applicationContext) {
44+
this.applicationContext = Objects.requireNonNull(applicationContext);
45+
}
46+
47+
@Override
48+
public IInput preProcess(IEditingContext editingContext, IInput input, Many<ChangeDescription> changeDescriptionSink) {
49+
if (editingContext instanceof EditingContext && input instanceof LayoutDiagramInput layoutDiagramInput && DiagramRefreshedEventPayload.CAUSE_REFRESH.equals(layoutDiagramInput.cause())) {
50+
EditingContextEventProcessorRegistry eventProcessorRegistry = this.applicationContext.getBean(EditingContextEventProcessorRegistry.class);
51+
Optional<IRepresentationEventProcessor> optionalRepresentationEventProcessor = eventProcessorRegistry.getEditingContextEventProcessors().stream()
52+
.filter(p -> p.getEditingContextId().equals(editingContext.getId()))
53+
.findFirst()
54+
.flatMap(p -> p.getRepresentationEventProcessors().stream()
55+
.filter(rep -> layoutDiagramInput.representationId().equals(rep.getRepresentation().getId()))
56+
.findFirst());
57+
if (optionalRepresentationEventProcessor.isPresent()) {
58+
var diagramInput = new SynchronizedExposedElementsDiagramInput(input.id(), layoutDiagramInput.representationId());
59+
optionalRepresentationEventProcessor.get().handle(Sinks.one(), changeDescriptionSink, diagramInput);
60+
}
61+
}
62+
return input;
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 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.common.view.services.handlers;
14+
15+
import java.util.UUID;
16+
17+
import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput;
18+
19+
/**
20+
* Tests.
21+
*
22+
* @author arichard
23+
*/
24+
public record SynchronizedExposedElementsDiagramInput(UUID id, String representationId) implements IDiagramInput {
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 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.common.view.services.handlers;
14+
15+
import java.util.List;
16+
import java.util.Objects;
17+
import java.util.Optional;
18+
19+
import org.eclipse.sirius.components.collaborative.api.ChangeDescription;
20+
import org.eclipse.sirius.components.collaborative.api.ChangeKind;
21+
import org.eclipse.sirius.components.collaborative.api.IRepresentationSearchService;
22+
import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramContext;
23+
import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramEventHandler;
24+
import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput;
25+
import org.eclipse.sirius.components.core.api.IEditingContext;
26+
import org.eclipse.sirius.components.core.api.IIdentityService;
27+
import org.eclipse.sirius.components.core.api.IObjectSearchService;
28+
import org.eclipse.sirius.components.core.api.IPayload;
29+
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
30+
import org.eclipse.sirius.components.core.api.SuccessPayload;
31+
import org.eclipse.sirius.components.diagrams.Diagram;
32+
import org.eclipse.sirius.components.diagrams.Node;
33+
import org.eclipse.sirius.components.diagrams.ViewCreationRequest;
34+
import org.eclipse.sirius.components.diagrams.components.NodeContainmentKind;
35+
import org.eclipse.sirius.components.diagrams.description.NodeDescription;
36+
import org.eclipse.syson.services.NodeDescriptionService;
37+
import org.eclipse.syson.services.UtilService;
38+
import org.eclipse.syson.sysml.Element;
39+
import org.eclipse.syson.sysml.ViewUsage;
40+
import org.springframework.stereotype.Service;
41+
42+
import reactor.core.publisher.Sinks.Many;
43+
import reactor.core.publisher.Sinks.One;
44+
45+
/**
46+
* Tests.
47+
*
48+
* @author arichard
49+
*/
50+
@Service
51+
public class SynchronizedExposedElementsEventHandler implements IDiagramEventHandler {
52+
53+
private final IRepresentationSearchService representationSearchService;
54+
55+
private final IRepresentationDescriptionSearchService representationDescriptionSearchService;
56+
57+
private final IObjectSearchService objectSearchService;
58+
59+
private final IIdentityService identityService;
60+
61+
private final UtilService utilService;
62+
63+
private final NodeDescriptionService nodeDescriptionService;
64+
65+
public SynchronizedExposedElementsEventHandler(IRepresentationSearchService representationSearchService, IRepresentationDescriptionSearchService representationDescriptionSearchService,
66+
IObjectSearchService objectSearchService, IIdentityService identityService) {
67+
this.representationSearchService = Objects.requireNonNull(representationSearchService);
68+
this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService);
69+
this.objectSearchService = Objects.requireNonNull(objectSearchService);
70+
this.identityService = Objects.requireNonNull(identityService);
71+
this.utilService = new UtilService();
72+
this.nodeDescriptionService = new NodeDescriptionService();
73+
}
74+
75+
@Override
76+
public boolean canHandle(IDiagramInput diagramInput) {
77+
return diagramInput instanceof SynchronizedExposedElementsDiagramInput;
78+
}
79+
80+
@Override
81+
public void handle(One<IPayload> payloadSink, Many<ChangeDescription> changeDescriptionSink, IEditingContext editingContext, IDiagramContext diagramContext, IDiagramInput diagramInput) {
82+
if (diagramInput instanceof SynchronizedExposedElementsDiagramInput synchronizedElementsDiagramInput) {
83+
String representationId = synchronizedElementsDiagramInput.representationId();
84+
Optional<Diagram> optionalDiagram = this.representationSearchService.findById(editingContext, representationId, Diagram.class);
85+
if (optionalDiagram.isPresent()) {
86+
Diagram diagram = optionalDiagram.get();
87+
Optional<ViewUsage> optionalDiagramTarget = this.objectSearchService.getObject(editingContext, diagram.getTargetObjectId())
88+
.filter(ViewUsage.class::isInstance)
89+
.map(ViewUsage.class::cast);
90+
if (optionalDiagramTarget.isPresent()) {
91+
this.synchronizeExposedElements(optionalDiagramTarget.get(), diagram, editingContext, diagramContext);
92+
ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, diagramInput.representationId(), diagramInput);
93+
payloadSink.tryEmitValue(new SuccessPayload(diagramInput.id()));
94+
changeDescriptionSink.tryEmitNext(changeDescription);
95+
}
96+
}
97+
}
98+
}
99+
100+
private void synchronizeExposedElements(ViewUsage viewUsage, Diagram diagram, IEditingContext editingContext, IDiagramContext diagramContext) {
101+
var exposedElements = viewUsage.getExposedElement();
102+
for (Element exposedElement : exposedElements) {
103+
String exposedElementId = this.identityService.getId(exposedElement);
104+
Optional<Node> node = this.getNode(diagram, exposedElementId);
105+
if (node.isEmpty()) {
106+
var owner = this.utilService.getOwningElement(exposedElement);
107+
var diagramDescription = this.representationDescriptionSearchService.findById(editingContext, diagramContext.getDiagram().getDescriptionId());
108+
List<NodeDescription> candidates = diagramDescription
109+
.filter(org.eclipse.sirius.components.diagrams.description.DiagramDescription.class::isInstance)
110+
.map(org.eclipse.sirius.components.diagrams.description.DiagramDescription.class::cast)
111+
.map(org.eclipse.sirius.components.diagrams.description.DiagramDescription::getNodeDescriptions)
112+
.orElse(List.of())
113+
.stream()
114+
.filter(nodeDescription -> this.nodeDescriptionService.canNodeDescriptionRenderElement(nodeDescription, exposedElement, owner))
115+
.toList();
116+
for (NodeDescription candidate : candidates) {
117+
var viewCreationRequest = ViewCreationRequest.newViewCreationRequest()
118+
.containmentKind(NodeContainmentKind.CHILD_NODE)
119+
.descriptionId(candidate.getId())
120+
.parentElementId(diagram.getId())
121+
.targetObjectId(exposedElementId)
122+
.build();
123+
diagramContext.getViewCreationRequests().add(viewCreationRequest);
124+
}
125+
}
126+
}
127+
}
128+
129+
private Optional<Node> getNode(Diagram diagram, String targetObjectId) {
130+
Optional<Node> optionalNode = Optional.empty();
131+
List<Node> nodes = diagram.getNodes();
132+
for (Node node : nodes) {
133+
if (Objects.equals(targetObjectId, node.getTargetObjectId())) {
134+
optionalNode = Optional.of(node);
135+
break;
136+
}
137+
}
138+
if (optionalNode.isEmpty()) {
139+
for (Node node : nodes) {
140+
var optChildNode = this.getChildNode(node, targetObjectId);
141+
if (optChildNode.isPresent() && Objects.equals(targetObjectId, optChildNode.get().getTargetObjectId())) {
142+
optionalNode = Optional.of(optChildNode.get());
143+
break;
144+
}
145+
}
146+
}
147+
return optionalNode;
148+
}
149+
150+
private Optional<Node> getChildNode(Node node, String targetObjectId) {
151+
Optional<Node> optionalChildNode = Optional.empty();
152+
List<Node> childNodes = node.getChildNodes();
153+
for (Node childNode : childNodes) {
154+
if (Objects.equals(targetObjectId, childNode.getTargetObjectId())) {
155+
optionalChildNode = Optional.of(childNode);
156+
break;
157+
}
158+
}
159+
if (optionalChildNode.isEmpty()) {
160+
for (Node childNode : childNodes) {
161+
var optChildNode = this.getChildNode(childNode, targetObjectId);
162+
if (optChildNode.isPresent() && Objects.equals(targetObjectId, optChildNode.get().getTargetObjectId())) {
163+
optionalChildNode = Optional.of(optChildNode.get());
164+
break;
165+
}
166+
}
167+
}
168+
return optionalChildNode;
169+
}
170+
}

backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/menu/context/CreateRepresentationInputPreProcessor.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,15 @@ public IInput preProcess(IEditingContext editingContext, IInput input, Many<Chan
6363
if (editingContext instanceof EditingContext && input instanceof CreateRepresentationInput createRepresentationInput && canHandle(createRepresentationInput)) {
6464
var optElement = getObject(editingContext, createRepresentationInput);
6565
if (optElement.isPresent()) {
66-
var viewUsage = createViewUsage(input, optElement.get(), createRepresentationInput.representationName());
67-
return new CreateRepresentationInput(input.id(), createRepresentationInput.editingContextId(), createRepresentationInput.representationDescriptionId(), viewUsage.getElementId(),
68-
createRepresentationInput.representationName());
66+
Element containerElement = optElement.get();
67+
if (containerElement instanceof ViewUsage) {
68+
// In case of a ViewUsage we want to follow the nominal case.
69+
} else {
70+
// In other cases we want to create a new ViewUsage and associated the new Diagram to this new ViewUsage.
71+
var viewUsage = createViewUsage(input, containerElement, createRepresentationInput.representationName());
72+
return new CreateRepresentationInput(input.id(), createRepresentationInput.editingContextId(), createRepresentationInput.representationDescriptionId(), viewUsage.getElementId(),
73+
createRepresentationInput.representationName());
74+
}
6975
}
7076
}
7177
return input;

0 commit comments

Comments
 (0)