Skip to content

Commit

Permalink
[961] Add valid default names for Elements
Browse files Browse the repository at this point in the history
Bug: #961
Signed-off-by: Axel RICHARD <axel.richard@obeo.fr>
  • Loading branch information
AxelRICHARD committed Jan 14, 2025
1 parent fd5aa93 commit 4bc43a0
Show file tree
Hide file tree
Showing 13 changed files with 340 additions and 100 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

- 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.
More precisely, the dates fields were not serialized correctly.
- https://github.com/eclipse-syson/syson/issues/961[#961] [core] Fix an issue where default names of Elements were sometimes invalid because corresponding to SysMLv2 keywords.
New default names now includes a number, this number corresponding to the count of Elements of the same kind in the scope.

=== Improvements

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 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 @@ -136,9 +136,9 @@ public void tearDown() {

private static Stream<Arguments> partUsageNodeParameters() {
return Stream.of(
Arguments.of(SysmlPackage.eINSTANCE.getPartUsage(), "part", 7),
Arguments.of(SysmlPackage.eINSTANCE.getAllocationUsage(), "allocation", 2),
Arguments.of(SysmlPackage.eINSTANCE.getInterfaceUsage(), "interface", 4)
Arguments.of(SysmlPackage.eINSTANCE.getPartUsage(), "part1", 7),
Arguments.of(SysmlPackage.eINSTANCE.getAllocationUsage(), "allocation1", 2),
Arguments.of(SysmlPackage.eINSTANCE.getInterfaceUsage(), "interface1", 4)
);
}

Expand All @@ -156,7 +156,7 @@ public void testApplyTool(EClass eClass, String nodeName, int definitionCompartm

var diagramAfterAddingElement = this.givenDiagram.getDiagram(this.verifier);

this.verifier.then(() -> this.nodeCreationTester.renameNode(SysMLv2Identifiers.GENERAL_VIEW_EMPTY_PROJECT,
this.verifier.then(() -> this.nodeCreationTester.renameRootNode(SysMLv2Identifiers.GENERAL_VIEW_EMPTY_PROJECT,
diagramAfterAddingElement,
nodeName,
this.getNewName(nodeName)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ private void createNewStakeholderIn(EClass eClassWithStakeholderParameter, Strin
final Element semanticRootElement = this.objectService.getObject(editingContext, SysMLv2Identifiers.GENERAL_VIEW_WITH_TOP_NODES_DIAGRAM_OBJECT).filter(Element.class::isInstance)
.map(Element.class::cast).orElseGet(() -> Assertions.fail("Could not find the expected root semantic object."));
final List<PartUsage> allStakeholderPartUsages = EMFUtils.allContainedObjectOfType(semanticRootElement, PartUsage.class)
.filter(element -> Objects.equals(element.getName(), "stakeholder")).toList();
.filter(element -> Objects.equals(element.getName(), "stakeholder1")).toList();
assertEquals(1, allStakeholderPartUsages.size());

final PartUsage stakeholderPartUsage = allStakeholderPartUsages.get(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 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 @@ -145,18 +145,20 @@ public void givenASysMLProjectWhenNewBindingConnectorAsUsageToolOfFirstLevelElem
public void givenASysMLProjectWhenNewBindingConnectorAsUsageToolOfNestedElementIsRequestedOnAPartUsageThenANewPartUsageAndABindingConnectorAsUsageEdgeAreCreated() {
String creationPartToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getFirstLevelNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "New Part");
assertThat(creationPartToolId).as("The tool 'New Part' should exist on a first level PartUsage").isNotNull();
this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT,
this.diagram,
"part1",
creationPartToolId));

this.verifier.then(() -> this.nodeCreationTester.renameNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT, this.diagram, "part1", "firstLevelPart"));

var diagramAfterRenaming = this.givenDiagram.getDiagram(this.verifier);

this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT, diagramAfterRenaming, "firstLevelPart", creationPartToolId));

var diagramAfterNestedPartUsageCreation = this.givenDiagram.getDiagram(this.verifier);

String creationToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "New Binding Connector As Usage");
assertThat(creationToolId).as("The tool 'New Binding Connector As Usage' should exist on a nested PartUsage").isNotNull();
this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT,
diagramAfterNestedPartUsageCreation,
"part",
"part1",
creationToolId));

IDiagramChecker diagramChecker = (initialDiagram, newDiagram) -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024,5 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 @@ -146,18 +146,20 @@ public void givenASysMLProjectWhenNewFlowConnectionToolOfFirstLevelElementIsRequ
public void givenASysMLProjectWhenNewFlowConnectionToolOfNestedElementIsRequestedOnAPartUsageThenANewPartUsageAndAFlowConnectionEdgeAreCreated() {
String creationPartToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getFirstLevelNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "New Part");
assertThat(creationPartToolId).as("The tool 'New Part' should exist on a first level PartUsage").isNotNull();
this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT,
this.diagram,
"part1",
creationPartToolId));

this.verifier.then(() -> this.nodeCreationTester.renameNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT, this.diagram, "part1", "firstLevelPart"));

var diagramAfterRenaming = this.givenDiagram.getDiagram(this.verifier);

this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT, diagramAfterRenaming, "firstLevelPart", creationPartToolId));

var diagramAfterNestedPartUsageCreation = this.givenDiagram.getDiagram(this.verifier);

String creationToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "New Flow Connection");
assertThat(creationToolId).as("The tool 'New Flow Connection' should exist on a nested PartUsage").isNotNull();
this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT,
diagramAfterNestedPartUsageCreation,
"part",
"part1",
creationToolId));

IDiagramChecker diagramChecker = (initialDiagram, newDiagram) -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 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 @@ -114,13 +114,13 @@ public void tearDown() {
}
}

@DisplayName("Given a SysML Project, when New Interface tool of first level element is requested on a PartUsage, then a new PartUsage and a Interface edge are created")
@DisplayName("Given a SysML Project, when New Interface tool of first level element is requested on a PartUsage, then a new PartUsage and an Interface edge are created")
@Sql(scripts = { "/scripts/syson-test-database.sql" }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
@Test
public void givenASysMLProjectWhenNewInterfaceToolIsRequestedOnAPartUsageThenANewPartUsageAndAInterfaceEdgeAreCreated() {
String creationToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getFirstLevelNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "New Interface");
assertThat(creationToolId).as("The tool 'New Interface' should exist on a PartUsage").isNotNull();
assertThat(creationToolId).as("The tool 'New Interface' should exist on a first level PartUsage").isNotNull();
this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT,
this.diagram,
"part1",
Expand All @@ -139,25 +139,28 @@ public void givenASysMLProjectWhenNewInterfaceToolIsRequestedOnAPartUsageThenANe
this.diagramCheckerService.checkDiagram(diagramChecker, this.diagram, this.verifier);
}

@DisplayName("Given a SysML Project, when New Interface tool of nested element is requested on a PartUsage, then a new PartUsage and a Interface edge are created")
@DisplayName("Given a SysML Project, when New Interface tool of nested element is requested on a PartUsage, then a new PartUsage and an Interface edge are created")
@Sql(scripts = { "/scripts/syson-test-database.sql" }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
@Test
public void givenASysMLProjectWhenNewFlowConnectionToolOfNestedElementIsRequestedOnAPartUsageThenANewPartUsageAndAFlowConnectionEdgeAreCreated() {
public void givenASysMLProjectWhenNewInterfaceToolOfNestedElementIsRequestedOnAPartUsageThenANewPartUsageAndAnInterfaceEdgeAreCreated() {
String creationPartToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getFirstLevelNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "New Part");
assertThat(creationPartToolId).as("The tool 'New Part' should exist on a first level PartUsage").isNotNull();
this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT,
this.diagram,
"part1",
creationPartToolId));

this.verifier.then(() -> this.nodeCreationTester.renameNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT, this.diagram, "part1", "firstLevelPart"));

var diagramAfterRenaming = this.givenDiagram.getDiagram(this.verifier);

this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT, diagramAfterRenaming, "firstLevelPart", creationPartToolId));

var diagramAfterNestedPartUsageCreation = this.givenDiagram.getDiagram(this.verifier);

String creationToolId = this.diagramDescriptionIdProvider.getNodeCreationToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "New Interface");
assertThat(creationToolId).as("The tool 'New Interface' should exist on a nested PartUsage").isNotNull();

this.verifier.then(() -> this.nodeCreationTester.createNode(SysMLv2Identifiers.INTERCONNECTION_VIEW_WITH_TOP_NODES_PROJECT,
diagramAfterNestedPartUsageCreation,
"part",
"part1",
creationToolId));

IDiagramChecker diagramChecker = (initialDiagram, newDiagram) -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 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 All @@ -16,6 +16,7 @@

import com.jayway.jsonpath.JsonPath;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
Expand Down Expand Up @@ -82,7 +83,7 @@ public void createNode(String projectId, AtomicReference<Diagram> diagram, Strin
assertThat(typename).isEqualTo(InvokeSingleClickOnDiagramElementToolSuccessPayload.class.getSimpleName());
}

public void renameNode(String projectId, AtomicReference<Diagram> diagram, String nodeName, String newName) {
public void renameRootNode(String projectId, AtomicReference<Diagram> diagram, String nodeName, String newName) {
Optional<Node> optionalNode = diagram.get().getNodes().stream().filter(n -> n.getTargetObjectLabel().equals(nodeName)).findFirst();

assertThat(optionalNode).as("the node " + nodeName + " is not present in the diagram").isNotEmpty();
Expand All @@ -93,4 +94,22 @@ public void renameNode(String projectId, AtomicReference<Diagram> diagram, Strin
String invokeSingleClickOnDiagramElementToolResultTypename = JsonPath.read(invokeSingleClickOnDiagramElementToolResult, "$.data.editLabel.__typename");
assertThat(invokeSingleClickOnDiagramElementToolResultTypename).isEqualTo(EditLabelSuccessPayload.class.getSimpleName());
}

public void renameNode(String projectId, AtomicReference<Diagram> diagram, String nodeName, String newName) {
List<Node> nodes = new ArrayList<>();
List<Node> rootNodes = diagram.get().getNodes();
nodes.addAll(rootNodes);
for (Node node : rootNodes) {
nodes.addAll(node.getChildNodes());
}
Optional<Node> optionalNode = nodes.stream().filter(n -> n.getTargetObjectLabel().equals(nodeName)).findFirst();

assertThat(optionalNode).as("the node " + nodeName + " is not present in the diagram").isNotEmpty();

var input = new EditLabelInput(UUID.randomUUID(), projectId, diagram.get().getId(), optionalNode.get().getInsideLabel().getId(), newName);
var invokeSingleClickOnDiagramElementToolResult = this.editLabelMutationRunner.run(input);

String invokeSingleClickOnDiagramElementToolResultTypename = JsonPath.read(invokeSingleClickOnDiagramElementToolResult, "$.data.editLabel.__typename");
assertThat(invokeSingleClickOnDiagramElementToolResultTypename).isEqualTo(EditLabelSuccessPayload.class.getSimpleName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.syson.sysml.FeatureDirectionKind;
import org.eclipse.syson.sysml.FeatureTyping;
import org.eclipse.syson.sysml.FlowConnectionUsage;
import org.eclipse.syson.sysml.Namespace;
import org.eclipse.syson.sysml.ObjectiveMembership;
import org.eclipse.syson.sysml.OwningMembership;
import org.eclipse.syson.sysml.Package;
Expand Down Expand Up @@ -102,7 +103,8 @@ public Element caseDependency(Dependency object) {

@Override
public Element caseDefinition(Definition object) {
object.setDeclaredName(object.eClass().getName());
var existingElements = this.existingElementsCount(object);
object.setDeclaredName(object.eClass().getName() + existingElements);
return object;
}

Expand All @@ -120,7 +122,8 @@ public Element caseElement(Element object) {
@Override
public Element caseEnumerationDefinition(EnumerationDefinition object) {
object.setIsVariation(true);
object.setDeclaredName(object.eClass().getName());
var existingElements = this.existingElementsCount(object);
object.setDeclaredName(object.eClass().getName() + existingElements);
return object;
}

Expand All @@ -136,17 +139,32 @@ public Element caseFlowConnectionUsage(FlowConnectionUsage object) {

@Override
public Element casePackage(Package object) {
object.setDeclaredName(object.eClass().getName());
var existingElements = this.existingElementsCount(object);
object.setDeclaredName(object.eClass().getName() + existingElements);
return object;
}

@Override
public Element casePartUsage(PartUsage object) {
this.caseUsage(object);
if (object.getOwningMembership() instanceof ActorMembership) {
object.setDeclaredName("actor");
long existingElements = 0;
Namespace owningNamespace = object.getOwningNamespace();
if (owningNamespace != null) {
existingElements = owningNamespace.getOwnedMember().stream()
.filter(member -> object.eClass().equals(member.eClass()) && object.getOwningMembership() instanceof ActorMembership)
.count();
}
object.setDeclaredName("actor" + existingElements);
} else if (object.getOwningMembership() instanceof StakeholderMembership) {
object.setDeclaredName("stakeholder");
long existingElements = 0;
Namespace owningNamespace = object.getOwningNamespace();
if (owningNamespace != null) {
existingElements = owningNamespace.getOwnedMember().stream()
.filter(member -> object.eClass().equals(member.eClass()) && object.getOwningMembership() instanceof StakeholderMembership)
.count();
}
object.setDeclaredName("stakeholder" + existingElements);
}
return object;
}
Expand All @@ -159,7 +177,8 @@ public Element casePerformActionUsage(PerformActionUsage object) {

@Override
public Element casePortDefinition(PortDefinition object) {
object.setDeclaredName(object.eClass().getName());
var existingElements = this.existingElementsCount(object);
object.setDeclaredName(object.eClass().getName() + existingElements);
OwningMembership owningMembership = SysmlFactory.eINSTANCE.createOwningMembership();
object.getOwnedRelationship().add(owningMembership);
// No need to set the declaredName for the ConjugatedPortDefinition here, it is always the same than its
Expand Down Expand Up @@ -236,11 +255,24 @@ public Element caseUsage(Usage object) {
if (defaultName.endsWith("Usage")) {
defaultName = defaultName.substring(0, defaultName.length() - 5);
}
object.setDeclaredName(defaultName);

var existingElements = this.existingElementsCount(object);

object.setDeclaredName(defaultName + existingElements);
object.setIsComposite(true);
return object;
}

private long existingElementsCount(Element element) {
Namespace owningNamespace = element.getOwningNamespace();
if (owningNamespace != null) {
return owningNamespace.getOwnedMember().stream()
.filter(member -> element.eClass().equals(member.eClass()))
.count();
}
return 0;
}

private ParameterMembership createParameterMembershipWithReferenceUsage(String refName, FeatureDirectionKind direction) {
var reference = SysmlFactory.eINSTANCE.createReferenceUsage();
reference.setDirection(direction);
Expand Down
Loading

0 comments on commit 4bc43a0

Please sign in to comment.