From 50e50e39ef5638451da54a650e9fd31b6868de24 Mon Sep 17 00:00:00 2001 From: Arthur Daussy Date: Mon, 3 Jun 2024 18:29:09 +0200 Subject: [PATCH] [344] Implement effectiveName for SysML and KerML elements Bug: https://github.com/eclipse-syson/syson/issues/344 Signed-off-by: Arthur Daussy --- CHANGELOG.adoc | 4 +- .../impl/ConjugatedPortDefinitionImpl.java | 28 ++---- .../eclipse/syson/sysml/impl/ElementImpl.java | 6 +- .../eclipse/syson/sysml/impl/FeatureImpl.java | 51 ++++++++++- .../syson/sysml/impl/LifeClassImpl.java | 8 ++ .../syson/sysml/impl/ReferenceUsageImpl.java | 16 ++++ .../eclipse/syson/sysml/impl/UsageImpl.java | 19 ++++ .../ConjugatedPortDefinitionImplTest.java | 39 +++++++++ .../syson/sysml/impl/FeatureImplTest.java | 56 ++++++++++++ .../syson/sysml/impl/UsageImplTest.java | 86 +++++++++++++++++++ .../syson/sysml/util/ModelBuilder.java | 55 ++++++------ 11 files changed, 316 insertions(+), 52 deletions(-) create mode 100644 backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImplTest.java create mode 100644 backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/FeatureImplTest.java create mode 100644 backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/UsageImplTest.java diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index aeca398e3..ccdb9b3e0 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -23,8 +23,8 @@ - https://github.com/eclipse-syson/syson/issues/298[#298] [syson] Add root Namespace to SysON models and libraries - https://github.com/eclipse-syson/syson/issues/324[#324] [diagrams] Improve support for whitespaces, quotes, and special characters in direct edit - https://github.com/eclipse-syson/syson/issues/307[#307] [diagrams] Fix parallel states tooling conditions -- https://github.com/eclipse-syson/syson/issues/269[#269] [diagrams] Handle action start and done nodes in Action Flow View diagram - +- https://github.com/eclipse-syson/syson/issues/269[#269] [diagrams] Handle action start and done nodes in Action Flow View & General View diagrams +- https://github.com/eclipse-syson/syson/issues/344[#344] [metamodel] Improve implementation of getName and getShortName === New features diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImpl.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImpl.java index bcd6096fd..df19c093c 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImpl.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImpl.java @@ -19,7 +19,6 @@ import org.eclipse.syson.sysml.PortConjugation; import org.eclipse.syson.sysml.PortDefinition; import org.eclipse.syson.sysml.SysmlPackage; -import org.eclipse.syson.sysml.helper.LabelConstants; /** * An implementation of the model object 'Conjugated Port Definition'. - * - * @generated NOT - */ - @Override - public String getDeclaredName() { - PortDefinition originalPortDefinition = this.getOriginalPortDefinition(); - if (originalPortDefinition != null) { - StringBuilder declaredName = new StringBuilder(); - declaredName.append(LabelConstants.CONJUGATED); - declaredName.append(originalPortDefinition.getDeclaredName()); - return declaredName.toString(); + public String effectiveName() { + PortDefinition portDef = this.getOriginalPortDefinition(); + if (portDef != null && portDef.getName() != null) { + return "~" + portDef.getName(); } return null; } @@ -140,12 +126,14 @@ public String getDeclaredName() { public Object eGet(int featureID, boolean resolve, boolean coreType) { switch (featureID) { case SysmlPackage.CONJUGATED_PORT_DEFINITION__ORIGINAL_PORT_DEFINITION: - if (resolve) + if (resolve) { return this.getOriginalPortDefinition(); + } return this.basicGetOriginalPortDefinition(); case SysmlPackage.CONJUGATED_PORT_DEFINITION__OWNED_PORT_CONJUGATOR: - if (resolve) + if (resolve) { return this.getOwnedPortConjugator(); + } return this.basicGetOwnedPortConjugator(); } return super.eGet(featureID, resolve, coreType); diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ElementImpl.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ElementImpl.java index 1abc1f98c..f412af256 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ElementImpl.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ElementImpl.java @@ -362,7 +362,8 @@ public boolean isIsLibraryElement() { */ @Override public String getName() { - return this.getDeclaredName(); + // Return an effective name for this Element. By default this is the same as its declaredName. + return this.effectiveName(); } /** @@ -574,7 +575,8 @@ public String getQualifiedName() { */ @Override public String getShortName() { - return this.getDeclaredShortName(); + // Return an effective shortName for this Element. By default this is the same as its declaredShortName. + return this.effectiveShortName(); } /** diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java index 04732f332..071e5ec6e 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/FeatureImpl.java @@ -699,13 +699,14 @@ public boolean isFeaturedWithin(Type type) { /** * * - * @generated + * @generated NOT */ @Override public Feature namingFeature() { - // TODO: implement this method - // Ensure that you remove @generated or mark it @generated NOT - return null; + return this.getOwnedRedefinition().stream() + .findFirst() + .map(red -> red.getRedefiningFeature()) + .orElse(null); } /** @@ -875,6 +876,48 @@ public void eUnset(int featureID) { super.eUnset(featureID); } + /** + * @generated NOT + */ + @Override + public String effectiveName() { + String dName = this.getDeclaredName(); + String dShortName = this.getDeclaredShortName(); + final String effectiveName; + if (dName != null || dShortName != null) { + effectiveName = dName; + } else { + Feature namingFeature = this.namingFeature(); + if (namingFeature != null && namingFeature != this) { + effectiveName = namingFeature.effectiveName(); + } else { + effectiveName = null; + } + } + return effectiveName; + } + + /** + * @generated NOT + */ + @Override + public String effectiveShortName() { + String dName = this.getDeclaredName(); + String dShortName = this.getDeclaredShortName(); + final String effectiveName; + if (dName != null || dShortName != null) { + effectiveName = dShortName; + } else { + Feature namingFeature = this.namingFeature(); + if (namingFeature != null && namingFeature != this) { + effectiveName = namingFeature.effectiveShortName(); + } else { + effectiveName = null; + } + } + return effectiveName; + } + /** * * diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/LifeClassImpl.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/LifeClassImpl.java index 42a90dbbe..2a98bf4bf 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/LifeClassImpl.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/LifeClassImpl.java @@ -31,6 +31,14 @@ protected LifeClassImpl() { super(); } + /** + * @generated NOT + */ + @Override + public String effectiveName() { + return "Life"; + } + /** * * diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ReferenceUsageImpl.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ReferenceUsageImpl.java index 9ab0c8ab6..6478e5654 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ReferenceUsageImpl.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ReferenceUsageImpl.java @@ -20,9 +20,12 @@ import org.eclipse.emf.ecore.util.EcoreEList; import org.eclipse.syson.sysml.ActionUsage; import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.Feature; import org.eclipse.syson.sysml.ReferenceUsage; import org.eclipse.syson.sysml.SysmlPackage; import org.eclipse.syson.sysml.TextualRepresentation; +import org.eclipse.syson.sysml.TransitionUsage; +import org.eclipse.syson.sysml.Type; /** * An implementation of the model object 'Reference Usage'. * diff --git a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImplTest.java b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImplTest.java new file mode 100644 index 000000000..cb12bd5dd --- /dev/null +++ b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/ConjugatedPortDefinitionImplTest.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2024 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 + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.sysml.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.syson.sysml.ConjugatedPortDefinition; +import org.eclipse.syson.sysml.PortDefinition; +import org.eclipse.syson.sysml.helper.LabelConstants; +import org.eclipse.syson.sysml.util.ModelBuilder; +import org.junit.jupiter.api.Test; + +/** + * Test class for {@link ConjugatedPortDefinition}. + * + * @author Arthur Daussy + */ +public class ConjugatedPortDefinitionImplTest { + + private final ModelBuilder builder = new ModelBuilder(); + + @Test + public void getNames() { + PortDefinition port = this.builder.createWithName(PortDefinition.class, "p1"); + ConjugatedPortDefinition conjugatedPort = this.builder.createInWithName(ConjugatedPortDefinition.class, port, "unusedName"); + assertEquals(LabelConstants.CONJUGATED + "p1", conjugatedPort.getName()); + + } +} diff --git a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/FeatureImplTest.java b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/FeatureImplTest.java new file mode 100644 index 000000000..2152f1dc2 --- /dev/null +++ b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/FeatureImplTest.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2024 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 + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.sysml.impl; + +import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.util.ModelBuilder; +import org.junit.jupiter.api.Test; + +/** + * Test class for {@link FeatureImpl}. + * + * @author Arthur Daussy + */ +public class FeatureImplTest { + + private final ModelBuilder builder = new ModelBuilder(); + + @Test + public void testNames() { + Feature f1 = this.builder.createWithName(Feature.class, "f1"); + f1.setDeclaredShortName("f"); + + assertEquals("f1", f1.getName()); + assertEquals("f1", f1.effectiveName()); + assertEquals("f", f1.getShortName()); + assertEquals("f", f1.effectiveShortName()); + + Feature f2 = this.builder.create(Feature.class); + assertNull(f2.getName()); + assertNull(f2.effectiveName()); + assertNull(f2.getShortName()); + assertNull(f2.effectiveShortName()); + + // Test redefinition + + this.builder.addRedefinition(f2, f1); + assertEquals("f1", f2.getName()); + assertEquals("f1", f2.effectiveName()); + assertEquals("f", f2.getShortName()); + assertEquals("f", f2.effectiveShortName()); + } + +} diff --git a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/UsageImplTest.java b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/UsageImplTest.java new file mode 100644 index 000000000..eecfe12d0 --- /dev/null +++ b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/impl/UsageImplTest.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2024 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 + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.sysml.impl; + +import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.Usage; +import org.eclipse.syson.sysml.VariantMembership; +import org.eclipse.syson.sysml.util.ModelBuilder; +import org.junit.jupiter.api.Test; + +/** + * Test class for {@link UsageImpl}. + * + * @author Arthur Daussy + */ +public class UsageImplTest { + + private final ModelBuilder builder = new ModelBuilder(); + + @Test + public void getNamesFromReferenceSubsetting() { + + Usage usage = this.builder.create(Usage.class); + + assertNull(usage.getName()); + assertNull(usage.getShortName()); + + Feature feature = this.builder.createWithName(Feature.class, "f1"); + feature.setDeclaredShortName("f"); + + this.builder.addReferenceSubsetting(usage, feature); + + assertEquals("f1", usage.getName()); + assertEquals("f", usage.getShortName()); + + // define a name and short name + + usage.setDeclaredName("u1"); + usage.setDeclaredShortName("u"); + + assertEquals("u1", usage.getName()); + assertEquals("u", usage.getShortName()); + } + + @Test + public void getNamesFromRedefinitionInVariant() { + + VariantMembership variantMembership = this.builder.create(VariantMembership.class); + Usage usage = this.builder.create(Usage.class); + + variantMembership.getOwnedRelatedElement().add(usage); + + assertNull(usage.getName()); + assertNull(usage.getShortName()); + + Feature feature = this.builder.createWithName(Feature.class, "f1"); + feature.setDeclaredShortName("f"); + + this.builder.addRedefinition(usage, feature); + + assertEquals("f1", usage.getName()); + assertEquals("f", usage.getShortName()); + + // define a name and short name + + usage.setDeclaredName("u1"); + usage.setDeclaredShortName("u"); + + assertEquals("u1", usage.getName()); + assertEquals("u", usage.getShortName()); + } + +} diff --git a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/util/ModelBuilder.java b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/util/ModelBuilder.java index a348b4932..1090638ea 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/util/ModelBuilder.java +++ b/backend/metamodel/syson-sysml-metamodel/src/test/java/org/eclipse/syson/sysml/util/ModelBuilder.java @@ -27,6 +27,7 @@ import org.eclipse.syson.sysml.FeatureTyping; import org.eclipse.syson.sysml.OwningMembership; import org.eclipse.syson.sysml.Redefinition; +import org.eclipse.syson.sysml.ReferenceSubsetting; import org.eclipse.syson.sysml.Relationship; import org.eclipse.syson.sysml.Subclassification; import org.eclipse.syson.sysml.SysmlFactory; @@ -38,7 +39,7 @@ /** * Helper used to build SysML model. - * + * * @author Arthur Daussy */ public class ModelBuilder { @@ -53,7 +54,7 @@ public class ModelBuilder { } public void addSuperType(Classifier child, Classifier parent) { - Subclassification subClassification = fact.createSubclassification(); + Subclassification subClassification = this.fact.createSubclassification(); // Workaround waiting for the subset/refine implementation subClassification.setGeneral(parent); subClassification.setSpecific(child); @@ -64,38 +65,44 @@ public void addSuperType(Classifier child, Classifier parent) { } - public void addRedefinition(Feature child, Feature parent) { - Redefinition redefinition = fact.createRedefinition(); - redefinition.setGeneral(parent); - redefinition.setSpecific(child); + public void addRedefinition(Feature redefinedFeature, Feature redefiningFeature) { + Redefinition redefinition = this.fact.createRedefinition(); + redefinition.setGeneral(redefiningFeature); + redefinition.setSpecific(redefinedFeature); // Workaround waiting for the subset/refine implementation - redefinition.setRedefinedFeature(child); - redefinition.setRedefiningFeature(parent); - redefinition.setSubsettedFeature(child); - redefinition.setSubsettingFeature(parent); + redefinition.setRedefinedFeature(redefinedFeature); + redefinition.setRedefiningFeature(redefiningFeature); + redefinition.setSubsettedFeature(redefinedFeature); + redefinition.setSubsettingFeature(redefiningFeature); + + redefinedFeature.getOwnedRelationship().add(redefinition); - child.getOwnedRelationship().add(redefinition); + } + public void addReferenceSubsetting(Element owner, Feature subSettedFeature) { + ReferenceSubsetting refSubsetting = this.fact.createReferenceSubsetting(); + refSubsetting.setReferencedFeature(subSettedFeature); + owner.getOwnedRelationship().add(refSubsetting); } public T create(Class type) { - return createIn(type, null); + return this.createIn(type, null); } public T createWithName(Class type, String name) { - return createInWithFullName(type, null, name, null); + return this.createInWithFullName(type, null, name, null); } public T createIn(Class type, Element parent) { - return createInWithName(type, parent, null); + return this.createInWithName(type, parent, null); } public T createInWithName(Class type, Element parent, String name) { - return createInWithFullName(type, parent, name, null); + return this.createInWithFullName(type, parent, name, null); } public void setType(Feature feature, Type type) { - FeatureTyping featureTyping = fact.createFeatureTyping(); + FeatureTyping featureTyping = this.fact.createFeatureTyping(); featureTyping.setSpecific(feature); featureTyping.setTypedFeature(feature); // Waiting for subset/refine implementation @@ -105,7 +112,7 @@ public void setType(Feature feature, Type type) { } public T createInWithFullName(Class type, Element parent, String name, String shortName) { - T newInstance = (T) fact.create(CLASS_TO_ECLASS.get(type)); + T newInstance = (T) this.fact.create(CLASS_TO_ECLASS.get(type)); if (name != null) { newInstance.setDeclaredName(name); } @@ -117,26 +124,26 @@ public T createInWithFullName(Class type, Element parent, if (newInstance instanceof Relationship newInstanceRelationship && !(newInstance instanceof Definition)) { parent.getOwnedRelationship().add(newInstanceRelationship); } else if (newInstance instanceof EnumerationUsage feature && parent instanceof EnumerationDefinition) { - addVariantMembership(parent, feature); + this.addVariantMembership(parent, feature); } else if (newInstance instanceof Feature feature) { - addFeatureMembership(parent, feature); + this.addFeatureMembership(parent, feature); } else { - addOwnedMembership(parent, newInstance); + this.addOwnedMembership(parent, newInstance); } } return newInstance; } private void addVariantMembership(Element parent, EnumerationUsage feature) { - addOwnedMembership(parent, feature, VariantMembership.class, null); + this.addOwnedMembership(parent, feature, VariantMembership.class, null); } private void addOwnedMembership(Element parent, Element ownedElement) { - addOwnedMembership(parent, ownedElement, OwningMembership.class, null); + this.addOwnedMembership(parent, ownedElement, OwningMembership.class, null); } private T addOwnedMembership(Element parent, Element ownedElement, Class relationshipType, VisibilityKind visibility) { - T ownedRelation = (T) fact.create(CLASS_TO_ECLASS.get(relationshipType)); + T ownedRelation = (T) this.fact.create(CLASS_TO_ECLASS.get(relationshipType)); parent.getOwnedRelationship().add(ownedRelation); ownedRelation.getOwnedRelatedElement().add(ownedElement); // I guess this should be done automatically when adding to ownedRelatedElement but waiting for subset and super @@ -154,7 +161,7 @@ private T addOwnedMembership(Element parent, Elemen } private void addFeatureMembership(Element parent, Feature feature) { - FeatureMembership relationship = addOwnedMembership(parent, feature, FeatureMembership.class, null); + FeatureMembership relationship = this.addOwnedMembership(parent, feature, FeatureMembership.class, null); // Workaround waiting for subset/refine implementation relationship.setFeature(feature); }