From 53f5e94f8fd2579feedf9a83df972efbbbe6ae50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Bausson?= Date: Wed, 30 Oct 2024 15:47:47 +0100 Subject: [PATCH] [818] Support of OccurrenceDefinition & OccurrenceUsage types export. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Timeslice * Snapshot Bug: https://github.com/eclipse-syson/syson/issues/818 Signed-off-by: Étienne Bausson --- CHANGELOG.adoc | 4 ++- .../sysml/export/SysMLElementSerializer.java | 33 ++++++++++++++--- .../export/utils/SysMLKeywordSwitch.java | 14 ++++++++ .../export/SysMLElementSerializerTest.java | 36 +++++++++++++++++++ .../pages/release-notes/2025.1.0.adoc | 1 + 5 files changed, 83 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 906266039..cd30bd5be 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -11,6 +11,7 @@ === Improvements - https://github.com/eclipse-syson/syson/issues/829[#829] [metamodel] `OccurrenceUsag#portionKind` is now unsettable and its default value is `null`. +- https://github.com/eclipse-syson/syson/issues/818[#818] [export] Add partial support of `OccurrenceDefinition` and 'OccurrenceUsage` in export from model to textual SysMLv2. === New features @@ -106,7 +107,8 @@ This reduces the time required to build SysON, especially when using Spring Tool - https://github.com/eclipse-syson/syson/issues/803[#803] [libraries] All standard libraries have been updated to comply with the SysML Beta 2.2 specification. - https://github.com/eclipse-syson/syson/issues/805[#805] [import] Improve non regression tests. Added source sysml file and unaltered ast.json result. - +- https://github.com/eclipse-syson/syson/issues/829[#829] [metamodel] Changed cardinality of PortionKind on OccurrenceUsage to [0..1], now unsettable. Now default to null. +- https://github.com/eclipse-syson/syson/issues/812[#812] [export] Fix visibility issue when resolving name of privately imported element during export. === New features - https://github.com/eclipse-syson/syson/issues/694[#694] [diagrams] Add a new custom node note among possible node style descriptions. diff --git a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java index 89cb1d9ac..71d660839 100644 --- a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java +++ b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java @@ -98,6 +98,7 @@ import org.eclipse.syson.sysml.PerformActionUsage; import org.eclipse.syson.sysml.PortDefinition; import org.eclipse.syson.sysml.PortUsage; +import org.eclipse.syson.sysml.PortionKind; import org.eclipse.syson.sysml.Redefinition; import org.eclipse.syson.sysml.ReferenceSubsetting; import org.eclipse.syson.sysml.ReferenceUsage; @@ -237,6 +238,11 @@ public String caseAttributeDefinition(AttributeDefinition attrDef) { return this.appendDefaultDefinition(this.newAppender(), attrDef).toString(); } + @Override + public String caseOccurrenceDefinition(OccurrenceDefinition occDef) { + return this.appendDefaultDefinition(this.newAppender(), occDef).toString(); + } + @Override public String casePortDefinition(PortDefinition portDef) { return this.appendDefaultDefinition(this.newAppender(), portDef).toString(); @@ -252,6 +258,19 @@ public String casePartUsage(PartUsage partUsage) { return this.appendDefaultUsage(this.newAppender(), partUsage).toString(); } + @Override + public String caseOccurrenceUsage(OccurrenceUsage occurrenceUsage) { + String serializedDeclaration; + if (PortionKind.SNAPSHOT.equals(occurrenceUsage.getPortionKind())) { + serializedDeclaration = this.serializeDeclarationWithModifiers(this.newAppender(), occurrenceUsage, "snapshot"); + } else if (PortionKind.TIMESLICE.equals(occurrenceUsage.getPortionKind())) { + serializedDeclaration = this.serializeDeclarationWithModifiers(this.newAppender(), occurrenceUsage, "timeslice"); + } else { + serializedDeclaration = this.appendDefaultUsage(this.newAppender(), occurrenceUsage); + } + return serializedDeclaration; + } + @Override public String caseReferenceUsage(ReferenceUsage reference) { Appender builder = new Appender(this.lineSeparator, this.indentation); @@ -473,10 +492,14 @@ public String caseLiteralInteger(LiteralInteger literal) { } private String appendDefaultUsage(Appender builder, Usage usage) { + return this.serializeDeclarationWithModifiers(builder, usage, this.getUsageKeyword(usage)); + } + + private String serializeDeclarationWithModifiers(Appender builder, Usage usage, String keyword) { this.appendUsagePrefix(builder, usage); - builder.appendSpaceIfNeeded().append(this.getUsageKeyword(usage)); + builder.appendSpaceIfNeeded().append(keyword); this.appendUsageDeclaration(builder, usage); @@ -1508,7 +1531,7 @@ private void appendUsagePrefix(Appender builder, Usage usage) { this.appendBasicUsagePrefix(builder, usage); final String isRef; - if (usage.isIsReference() && !this.isImplicitlyReferencial(usage)) { + if (usage.isIsReference() && !this.isImplicitlyReferential(usage)) { isRef = "ref"; } else { isRef = ""; @@ -1533,8 +1556,10 @@ private void appendOccurrenceUsagePrefix(Appender builder, OccurrenceUsage occUs this.appendExtensionKeyword(builder, occUsage); } - private boolean isImplicitlyReferencial(Usage usage) { - return usage instanceof AttributeUsage || usage instanceof ReferenceUsage || usage.getOwningMembership() instanceof ActorMembership; + private boolean isImplicitlyReferential(Usage usage) { + return usage.getOwningMembership() instanceof ActorMembership + || usage instanceof AttributeUsage + || usage instanceof ReferenceUsage; } private void appendExtensionKeyword(Appender builder, Type type) { diff --git a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/SysMLKeywordSwitch.java b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/SysMLKeywordSwitch.java index 3f9a3114f..89f9f2f8f 100644 --- a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/SysMLKeywordSwitch.java +++ b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/SysMLKeywordSwitch.java @@ -28,6 +28,8 @@ import org.eclipse.syson.sysml.InterfaceUsage; import org.eclipse.syson.sysml.ItemDefinition; import org.eclipse.syson.sysml.ItemUsage; +import org.eclipse.syson.sysml.OccurrenceDefinition; +import org.eclipse.syson.sysml.OccurrenceUsage; import org.eclipse.syson.sysml.PartDefinition; import org.eclipse.syson.sysml.PartUsage; import org.eclipse.syson.sysml.PerformActionUsage; @@ -61,6 +63,8 @@ public class SysMLKeywordSwitch extends SysmlSwitch { private static final String ITEM_KEYWORD = "item"; + private static final String OCCURRENCE_KEYWORD = "occurrence"; + private static final String ENUM_KEYWORD = "enum"; private static final String ATTRIBUTE_KEYWORD = "attribute"; @@ -135,6 +139,16 @@ public String caseItemUsage(ItemUsage object) { return ITEM_KEYWORD; } + @Override + public String caseOccurrenceDefinition(OccurrenceDefinition object) { + return OCCURRENCE_KEYWORD; + } + + @Override + public String caseOccurrenceUsage(OccurrenceUsage object) { + return OCCURRENCE_KEYWORD; + } + @Override public String caseInterfaceDefinition(InterfaceDefinition object) { return INTERFACE_KEYWORD; diff --git a/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLElementSerializerTest.java b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLElementSerializerTest.java index 3badbfa2f..b7aeb5992 100644 --- a/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLElementSerializerTest.java +++ b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLElementSerializerTest.java @@ -55,6 +55,7 @@ import org.eclipse.syson.sysml.Namespace; import org.eclipse.syson.sysml.NamespaceImport; import org.eclipse.syson.sysml.ObjectiveMembership; +import org.eclipse.syson.sysml.OccurrenceDefinition; import org.eclipse.syson.sysml.OccurrenceUsage; import org.eclipse.syson.sysml.OperatorExpression; import org.eclipse.syson.sysml.OwningMembership; @@ -66,6 +67,7 @@ import org.eclipse.syson.sysml.PortConjugation; import org.eclipse.syson.sysml.PortDefinition; import org.eclipse.syson.sysml.PortUsage; +import org.eclipse.syson.sysml.PortionKind; import org.eclipse.syson.sysml.Redefinition; import org.eclipse.syson.sysml.ReferenceSubsetting; import org.eclipse.syson.sysml.ReferenceUsage; @@ -122,6 +124,8 @@ public class SysMLElementSerializerTest { private static final String ANNOTATING1 = "Annotating1"; + private static final String OCCURRENCE1 = "occurrence1"; + private static final String BODY = "A body"; private ModelBuilder builder; @@ -360,6 +364,11 @@ public void interfaceDefinition() { this.checkBasicDefinitionDeclaration(InterfaceDefinition.class, "interface def"); } + @Test + public void occurrenceDefinition() { + this.checkBasicDefinitionDeclaration(OccurrenceDefinition.class, "occurrence def"); + } + private void checkBasicDefinitionDeclaration(Class type, String keyword) { Package p1 = this.builder.createWithName(Package.class, PACKAGE1); @@ -1588,4 +1597,31 @@ public void itemUsage() { } }""", model.getItemTest()); } + + @Test + public void occurrenceUsage() { + OccurrenceUsage occurrenceUsage = this.builder.createWithName(OccurrenceUsage.class, OCCURRENCE1); + occurrenceUsage.setIsComposite(true); + + this.assertTextualFormEquals("occurrence occurrence1;", occurrenceUsage); + } + + @Test + public void occurrenceUsageAsSnapshot() { + OccurrenceUsage occurrenceUsage = this.builder.createWithName(OccurrenceUsage.class, OCCURRENCE1); + occurrenceUsage.setIsComposite(true); + occurrenceUsage.setPortionKind(PortionKind.SNAPSHOT); + + this.assertTextualFormEquals("snapshot occurrence1;", occurrenceUsage); + } + + @Test + public void occurrenceUsageAsTimeslice() { + OccurrenceUsage occurrenceUsage = this.builder.createWithName(OccurrenceUsage.class, OCCURRENCE1); + occurrenceUsage.setIsComposite(true); + occurrenceUsage.setPortionKind(PortionKind.TIMESLICE); + + this.assertTextualFormEquals("timeslice occurrence1;", occurrenceUsage); + } + } diff --git a/doc/content/modules/user-manual/pages/release-notes/2025.1.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2025.1.0.adoc index 12716bf1a..49308b32c 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2025.1.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2025.1.0.adoc @@ -11,5 +11,6 @@ == Improvements - `OccurrenceUsag#portionKind` is now unsettable and its default value is `null` in the SysMLv2 metamodel to conform to the specification. +- Add support of `OccurrenceDefinition` and 'OccurrenceUsage` in export from model to textual SysMLv2. == New features