Skip to content

Commit e20a537

Browse files
committed
[961] Add valid default names for Elements
Bug: #961 Signed-off-by: Axel RICHARD <axel.richard@obeo.fr>
1 parent fd5aa93 commit e20a537

File tree

4 files changed

+204
-7
lines changed

4 files changed

+204
-7
lines changed

CHANGELOG.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
- https://github.com/eclipse-syson/syson/issues/953[#953] [rest-apis] Fix an issue where the server could crash when successive REST APIs calls are executed.
1616
More precisely, the dates fields were not serialized correctly.
17+
- https://github.com/eclipse-syson/syson/issues/960[#960] [core] Fix an issue where default names of Elements were sometimes invalid because corresponding to SysMLv2 keywords.
18+
New default names now includes a number, this number corresponding to the count of Elements of the same kind in the scope.
1719

1820
=== Improvements
1921

backend/services/syson-services/src/main/java/org/eclipse/syson/services/ElementInitializerSwitch.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ public Element caseDependency(Dependency object) {
102102

103103
@Override
104104
public Element caseDefinition(Definition object) {
105-
object.setDeclaredName(object.eClass().getName());
105+
var existingElements = this.existingElementsCount(object);
106+
object.setDeclaredName(object.eClass().getName() + existingElements);
106107
return object;
107108
}
108109

@@ -120,7 +121,8 @@ public Element caseElement(Element object) {
120121
@Override
121122
public Element caseEnumerationDefinition(EnumerationDefinition object) {
122123
object.setIsVariation(true);
123-
object.setDeclaredName(object.eClass().getName());
124+
var existingElements = this.existingElementsCount(object);
125+
object.setDeclaredName(object.eClass().getName() + existingElements);
124126
return object;
125127
}
126128

@@ -136,17 +138,24 @@ public Element caseFlowConnectionUsage(FlowConnectionUsage object) {
136138

137139
@Override
138140
public Element casePackage(Package object) {
139-
object.setDeclaredName(object.eClass().getName());
141+
var existingElements = this.existingElementsCount(object);
142+
object.setDeclaredName(object.eClass().getName() + existingElements);
140143
return object;
141144
}
142145

143146
@Override
144147
public Element casePartUsage(PartUsage object) {
145148
this.caseUsage(object);
146149
if (object.getOwningMembership() instanceof ActorMembership) {
147-
object.setDeclaredName("actor");
150+
var existingElements = object.getOwningNamespace().getOwnedMember().stream()
151+
.filter(member -> object.eClass().equals(member.eClass()) && object.getOwningMembership() instanceof ActorMembership)
152+
.count();
153+
object.setDeclaredName("actor" + existingElements);
148154
} else if (object.getOwningMembership() instanceof StakeholderMembership) {
149-
object.setDeclaredName("stakeholder");
155+
var existingElements = object.getOwningNamespace().getOwnedMember().stream()
156+
.filter(member -> object.eClass().equals(member.eClass()) && object.getOwningMembership() instanceof StakeholderMembership)
157+
.count();
158+
object.setDeclaredName("stakeholder" + existingElements);
150159
}
151160
return object;
152161
}
@@ -159,7 +168,8 @@ public Element casePerformActionUsage(PerformActionUsage object) {
159168

160169
@Override
161170
public Element casePortDefinition(PortDefinition object) {
162-
object.setDeclaredName(object.eClass().getName());
171+
var existingElements = this.existingElementsCount(object);
172+
object.setDeclaredName(object.eClass().getName() + existingElements);
163173
OwningMembership owningMembership = SysmlFactory.eINSTANCE.createOwningMembership();
164174
object.getOwnedRelationship().add(owningMembership);
165175
// No need to set the declaredName for the ConjugatedPortDefinition here, it is always the same than its
@@ -236,11 +246,20 @@ public Element caseUsage(Usage object) {
236246
if (defaultName.endsWith("Usage")) {
237247
defaultName = defaultName.substring(0, defaultName.length() - 5);
238248
}
239-
object.setDeclaredName(defaultName);
249+
250+
var existingElements = this.existingElementsCount(object);
251+
252+
object.setDeclaredName(defaultName + existingElements);
240253
object.setIsComposite(true);
241254
return object;
242255
}
243256

257+
private long existingElementsCount(Element element) {
258+
return element.getOwningNamespace().getOwnedMember().stream()
259+
.filter(member -> element.eClass().equals(member.eClass()))
260+
.count();
261+
}
262+
244263
private ParameterMembership createParameterMembershipWithReferenceUsage(String refName, FeatureDirectionKind direction) {
245264
var reference = SysmlFactory.eINSTANCE.createReferenceUsage();
246265
reference.setDirection(direction);
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
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.services;
14+
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
17+
import org.eclipse.emf.common.util.URI;
18+
import org.eclipse.emf.ecore.EClass;
19+
import org.eclipse.emf.ecore.resource.Resource;
20+
import org.eclipse.emf.ecore.resource.ResourceSet;
21+
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
22+
import org.eclipse.sirius.components.emf.services.EditingContextCrossReferenceAdapter;
23+
import org.eclipse.sirius.emfjson.resource.JsonResourceFactoryImpl;
24+
import org.eclipse.syson.sysml.Element;
25+
import org.eclipse.syson.sysml.Membership;
26+
import org.eclipse.syson.sysml.OwningMembership;
27+
import org.eclipse.syson.sysml.Relationship;
28+
import org.eclipse.syson.sysml.SysmlFactory;
29+
import org.eclipse.syson.sysml.SysmlPackage;
30+
import org.junit.jupiter.api.BeforeEach;
31+
import org.junit.jupiter.api.DisplayName;
32+
import org.junit.jupiter.api.Test;
33+
34+
/**
35+
* ElementInitializerSwitch-related tests.
36+
*
37+
* @author arichard
38+
*/
39+
public class ElementInitializerSwitchTest {
40+
41+
private static final String ROOT = "root";
42+
43+
private ResourceSet rSet;
44+
45+
private Resource resource;
46+
47+
private ElementInitializerSwitch elementInitializerSwitch;
48+
49+
@BeforeEach
50+
public void setUp() {
51+
this.rSet = new ResourceSetImpl();
52+
// Make sure the resources we manipulate use the Sirius Web CrossReferenceAdapter.
53+
// This is particularly important when manipulating memberships, where the cross-referencer may produce
54+
// unexpected behaviors that cannot be observed in a resource without it.
55+
this.rSet.eAdapters().add(new EditingContextCrossReferenceAdapter());
56+
this.resource = new JsonResourceFactoryImpl().createResource(URI.createURI("ElementInitializerSwitchTest"));
57+
this.rSet.getResources().add(this.resource);
58+
this.elementInitializerSwitch = new ElementInitializerSwitch();
59+
}
60+
61+
@DisplayName("Given a PartUsage, when it is initialized, then it's name contains the count of the same kind of elements")
62+
@Test
63+
public void testPartUsageDefaultName() {
64+
var root = SysmlFactory.eINSTANCE.createPackage();
65+
this.resource.getContents().add(root);
66+
root.setDeclaredName(ROOT);
67+
var p1 = SysmlFactory.eINSTANCE.createPartUsage();
68+
this.addInParent(p1, root);
69+
var initializedP1 = this.elementInitializerSwitch.doSwitch(p1);
70+
assertThat(initializedP1.getDeclaredName()).isEqualTo("part1");
71+
var p2 = SysmlFactory.eINSTANCE.createPartUsage();
72+
this.addInParent(p2, root);
73+
var initializedP2 = this.elementInitializerSwitch.doSwitch(p2);
74+
assertThat(initializedP2.getDeclaredName()).isEqualTo("part2");
75+
}
76+
77+
@DisplayName("Given a PartDefinition, when it is initialized, then it's name contains the count of the same kind of elements")
78+
@Test
79+
public void testPartDefinitionDefaultName() {
80+
var root = SysmlFactory.eINSTANCE.createPackage();
81+
this.resource.getContents().add(root);
82+
root.setDeclaredName(ROOT);
83+
var p1 = SysmlFactory.eINSTANCE.createPartDefinition();
84+
this.addInParent(p1, root);
85+
var initializedP1 = this.elementInitializerSwitch.doSwitch(p1);
86+
assertThat(initializedP1.getDeclaredName()).isEqualTo("PartDefinition1");
87+
var p2 = SysmlFactory.eINSTANCE.createPartDefinition();
88+
this.addInParent(p2, root);
89+
var initializedP2 = this.elementInitializerSwitch.doSwitch(p2);
90+
assertThat(initializedP2.getDeclaredName()).isEqualTo("PartDefinition2");
91+
}
92+
93+
@DisplayName("Given a EnumerationDefinition, when it is initialized, then it's name contains the count of the same kind of elements")
94+
@Test
95+
public void testEnumerationDefinitionDefaultName() {
96+
var root = SysmlFactory.eINSTANCE.createPackage();
97+
this.resource.getContents().add(root);
98+
root.setDeclaredName(ROOT);
99+
var ed1 = SysmlFactory.eINSTANCE.createEnumerationDefinition();
100+
this.addInParent(ed1, root);
101+
var initializedED1 = this.elementInitializerSwitch.doSwitch(ed1);
102+
assertThat(initializedED1.getDeclaredName()).isEqualTo("EnumerationDefinition1");
103+
var ed2 = SysmlFactory.eINSTANCE.createEnumerationDefinition();
104+
this.addInParent(ed2, root);
105+
var initializedED2 = this.elementInitializerSwitch.doSwitch(ed2);
106+
assertThat(initializedED2.getDeclaredName()).isEqualTo("EnumerationDefinition2");
107+
}
108+
109+
@DisplayName("Given a Package, when it is initialized, then it's name contains the count of the same kind of elements")
110+
@Test
111+
public void testPackageDefaultName() {
112+
var root = SysmlFactory.eINSTANCE.createPackage();
113+
this.resource.getContents().add(root);
114+
root.setDeclaredName(ROOT);
115+
var p1 = SysmlFactory.eINSTANCE.createPackage();
116+
this.addInParent(p1, root);
117+
var initializedP1 = this.elementInitializerSwitch.doSwitch(p1);
118+
assertThat(initializedP1.getDeclaredName()).isEqualTo("Package1");
119+
var p2 = SysmlFactory.eINSTANCE.createPackage();
120+
this.addInParent(p2, root);
121+
var initializedP2 = this.elementInitializerSwitch.doSwitch(p2);
122+
assertThat(initializedP2.getDeclaredName()).isEqualTo("Package2");
123+
}
124+
125+
@DisplayName("Given an Actor, when it is initialized, then it's name contains the count of the same kind of elements")
126+
@Test
127+
public void testActorDefaultName() {
128+
var root = SysmlFactory.eINSTANCE.createPackage();
129+
this.resource.getContents().add(root);
130+
root.setDeclaredName(ROOT);
131+
var p1 = SysmlFactory.eINSTANCE.createPartUsage();
132+
this.addInParent(p1, root);
133+
var a1 = SysmlFactory.eINSTANCE.createPartUsage();
134+
this.addInParent(a1, p1, SysmlPackage.eINSTANCE.getActorMembership());
135+
var initializedA1 = this.elementInitializerSwitch.doSwitch(a1);
136+
assertThat(initializedA1.getDeclaredName()).isEqualTo("actor1");
137+
var a2 = SysmlFactory.eINSTANCE.createPartUsage();
138+
this.addInParent(a2, p1, SysmlPackage.eINSTANCE.getActorMembership());
139+
var initializedA2 = this.elementInitializerSwitch.doSwitch(a2);
140+
assertThat(initializedA2.getDeclaredName()).isEqualTo("actor2");
141+
}
142+
143+
@DisplayName("Given a Stakeholder, when it is initialized, then it's name contains the count of the same kind of elements")
144+
@Test
145+
public void testStakeholderDefaultName() {
146+
var root = SysmlFactory.eINSTANCE.createPackage();
147+
this.resource.getContents().add(root);
148+
root.setDeclaredName(ROOT);
149+
var p1 = SysmlFactory.eINSTANCE.createPartUsage();
150+
this.addInParent(p1, root);
151+
var s1 = SysmlFactory.eINSTANCE.createPartUsage();
152+
this.addInParent(s1, p1, SysmlPackage.eINSTANCE.getStakeholderMembership());
153+
var initializedS1 = this.elementInitializerSwitch.doSwitch(s1);
154+
assertThat(initializedS1.getDeclaredName()).isEqualTo("stakeholder1");
155+
var s2 = SysmlFactory.eINSTANCE.createPartUsage();
156+
this.addInParent(s2, p1, SysmlPackage.eINSTANCE.getStakeholderMembership());
157+
var initializedS2 = this.elementInitializerSwitch.doSwitch(s2);
158+
assertThat(initializedS2.getDeclaredName()).isEqualTo("stakeholder2");
159+
}
160+
161+
private void addInParent(Element element, Element parent) {
162+
OwningMembership owningMembership = SysmlFactory.eINSTANCE.createOwningMembership();
163+
parent.getOwnedRelationship().add(owningMembership);
164+
owningMembership.getOwnedRelatedElement().add(element);
165+
}
166+
167+
private void addInParent(Element element, Element parent, EClass membershipKind) {
168+
var membership = SysmlFactory.eINSTANCE.create(membershipKind);
169+
assertThat(membership).isInstanceOf(Membership.class);
170+
parent.getOwnedRelationship().add((Relationship) membership);
171+
((Relationship) membership).getOwnedRelatedElement().add(element);
172+
}
173+
}

doc/content/modules/user-manual/pages/release-notes/2025.2.0.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
- Fix an issue where the server could crash when successive REST APIs calls are executed.
1313
More precisely, the dates fields were not serialized correctly.
14+
- Fix an issue where default names of `Elements` were sometimes invalid because corresponding to SysMLv2 keywords.
15+
New default names now includes a number, this number corresponding to the count of `Elements` of the same kind in the scope.
16+
For example, if a `PartDefinition` already define 5 parts, then a new `Part` created under this `PartDefinition` would have _part6_ for name.
1417

1518
== New features
1619

0 commit comments

Comments
 (0)