From 553cf8205c19241c9127ab264f8372f5b58d3895 Mon Sep 17 00:00:00 2001 From: Ed Seidewitz Date: Sat, 1 Aug 2026 18:44:27 -0400 Subject: [PATCH 1/6] KERML11-1 Updated Feature.ownedCrossFeature operation per resolution. - Added a test to KERML11_Ballot3_Tests. --- .../java/org/omg/sysml/util/FeatureUtil.java | 8 +- .../sysml/logic/KERML11_Ballot3_Tests.java | 76 +++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java diff --git a/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java b/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java index 30d7ce543..7ceeda8e6 100644 --- a/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java +++ b/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java @@ -35,6 +35,7 @@ import org.eclipse.emf.ecore.InternalEObject; import org.omg.sysml.adapter.FeatureAdapter; import org.omg.sysml.lang.sysml.Behavior; +import org.omg.sysml.lang.sysml.BindingConnector; import org.omg.sysml.lang.sysml.CrossSubsetting; import org.omg.sysml.lang.sysml.Expression; import org.omg.sysml.lang.sysml.Feature; @@ -233,12 +234,15 @@ public static Feature getCrossFeatureOf(Feature feature) { } public static Feature getOwnedCrossFeatureOf(Namespace namespace) { - return !(namespace instanceof Feature) || !((Feature)namespace).isEnd()? null: + return !(namespace instanceof Feature feature) || + !feature.isEnd() || + feature.getOwningType() == null? null: (Feature)namespace.getOwnedMember().stream(). filter(element->element instanceof Feature && !(element instanceof Multiplicity) && !(element instanceof MetadataFeature) && - !(element.getOwningMembership() instanceof FeatureMembership)&& + !(element instanceof BindingConnector) && + !(element.getOwningMembership() instanceof FeatureMembership) && !(element.getOwningMembership() instanceof FeatureValue)). findFirst().orElse(null); } diff --git a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java new file mode 100644 index 000000000..4faa7ac4c --- /dev/null +++ b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * SysML 2 Pilot Implementation + * Copyright (c) 2026 Model Driven Solutions, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Eclipse Public License as published by + * the Eclipse Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Eclipse Public License for more details. + * + * You should have received a copy of theEclipse Public License + * along with this program. If not, see . + * + * @license EPL-2.0 + * + *******************************************************************************/ +package org.omg.sysml.logic; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.BeforeClass; +import org.junit.Test; + +import org.omg.sysml.lang.sysml.Association; +import org.omg.sysml.lang.sysml.BindingConnector; +import org.omg.sysml.lang.sysml.Feature; +import org.omg.sysml.lang.sysml.SysMLFactory; +import org.omg.sysml.util.ConnectorUtil; +import org.omg.sysml.util.FeatureUtil; +import org.omg.sysml.util.NamespaceUtil; +import org.omg.sysml.util.TypeUtil; + +public class KERML11_Ballot3_Tests { + + @BeforeClass + public static void setUp() { + SysMLLogicStandaloneSetup.doSetup(); + } + + /** + * Test resolution to KERML11-1 Binding connectors should not be considered owned cross features + * @throws InvocationTargetException + */ + @Test + public void testKERML11_1() { + Association association = SysMLFactory.eINSTANCE.createAssociation(); + + Feature end1 = SysMLFactory.eINSTANCE.createFeature(); + end1.setDeclaredName("end1"); + end1.setIsEnd(true); + TypeUtil.addOwnedFeatureTo(association, end1); + + Feature end2 = SysMLFactory.eINSTANCE.createFeature(); + end2.setDeclaredName("end2"); + end2.setIsEnd(true); + TypeUtil.addOwnedFeatureTo(association, end2); + + BindingConnector connector = SysMLFactory.eINSTANCE.createBindingConnector(); + FeatureUtil.addTypeFeaturingTo(connector).setFeaturingType(association); + ConnectorUtil.addConnectorEndTo(connector, end1); + ConnectorUtil.addConnectorEndTo(connector, end1); + NamespaceUtil.addOwnedMemberTo(end1, connector); + + Feature feature = SysMLFactory.eINSTANCE.createFeature(); + feature.setDeclaredName("crossFeature"); + NamespaceUtil.addOwnedMemberTo(end1, feature); + + Feature crossFeature = end1.ownedCrossFeature(); + assertNotNull("Not null", crossFeature); + assertEquals("cross feature", feature, crossFeature); + } +} From f35b6a5bbed2a070d41d2462f13930e9ef2837c3 Mon Sep 17 00:00:00 2001 From: Ed Seidewitz Date: Sun, 2 Aug 2026 04:41:24 -0400 Subject: [PATCH 2/6] KERML11-3 Revised impl of checkMultiplicityRangeExpressionTypeFeaturing. - Removed previous proactive change in implementation of featuring type for Multiplicity. - Added Junit test to KERML11_Ballot3_Tests. --- .../xtext/validation/KerMLValidator.xtend | 7 +-- .../omg/sysml/adapter/ExpressionAdapter.java | 36 +++++++++--- .../sysml/adapter/MultiplicityAdapter.java | 19 +----- .../sysml/logic/KERML11_Ballot3_Tests.java | 58 ++++++++++++++++++- 4 files changed, 88 insertions(+), 32 deletions(-) diff --git a/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend b/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend index 0ec6dc1f4..04896a2b0 100644 --- a/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend +++ b/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend @@ -608,13 +608,8 @@ class KerMLValidator extends AbstractKerMLValidator { } // validateFeatureMultiplicityDomain - // TODO: Update OCL for owned cross feature multiplicity featuring type. val m = f.multiplicity; - val featuringTypes = f.featuringType - var mFeaturingTypes = - if (FeatureUtil.isOwnedCrossFeature(f)) (f.owningNamespace as Feature).featuringType - else featuringTypes - if (m !== null && mFeaturingTypes.toSet != m.featuringType.toSet) { + if (m !== null && f.featuringType.toSet != m.featuringType.toSet) { error(INVALID_FEATURE_MULTIPLICITY_DOMAIN_MSG, f, SysMLPackage.eINSTANCE.type_Multiplicity, INVALID_FEATURE_MULTIPLICITY_DOMAIN) } diff --git a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java index 0363dca81..80c22e1dd 100644 --- a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java +++ b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java @@ -26,9 +26,11 @@ import org.omg.sysml.lang.sysml.Expression; import org.omg.sysml.lang.sysml.Feature; import org.omg.sysml.lang.sysml.FeatureValue; -import org.omg.sysml.lang.sysml.Multiplicity; +import org.omg.sysml.lang.sysml.MultiplicityRange; +import org.omg.sysml.lang.sysml.Namespace; import org.omg.sysml.lang.sysml.Type; import org.omg.sysml.util.ExpressionUtil; +import org.omg.sysml.util.FeatureUtil; import org.omg.sysml.util.ImplicitGeneralizationMap; public class ExpressionAdapter extends StepAdapter { @@ -99,20 +101,40 @@ protected List getGeneralTypes(Type type, Element skip) { } // Transformation - + /** * @satisfies checkExpressionTypeFeaturing - * @satisfies checkExpressionResultBindingConnector * @satisfies checkMultiplicityRangeExpressionTypeFeaturing */ @Override + protected void addImplicitFeaturingTypesIfNecessary() { + Expression expression = getTarget(); + Namespace owner = expression.getOwningNamespace(); + if (owner instanceof MultiplicityRange multiplicity && + multiplicity.getBound().contains(expression)) { + owner = multiplicity.getOwningNamespace(); + if (owner instanceof Feature) { + Namespace owningEnd = owner.getOwningNamespace(); + if (FeatureUtil.isOwnedCrossFeature((Feature)owner) && + isImplicitFeaturingTypesEmpty()) { + addFeaturingTypes(((Feature)owningEnd).getFeaturingType()); + } else { + super.addImplicitFeaturingTypesIfNecessary(); + } + } + } else if (expression.getOwningMembership() instanceof FeatureValue) { + super.addImplicitFeaturingTypesIfNecessary(); + } + } + + /** + * @satisfies checkExpressionResultBindingConnector + */ + @Override public void doTransform() { Expression expression = getTarget(); super.doTransform(); - if (expression.getOwningNamespace() instanceof Multiplicity || - expression.getOwningMembership() instanceof FeatureValue) { - addImplicitFeaturingTypesIfNecessary(); - } + addImplicitFeaturingTypesIfNecessary(); createResultConnector(expression.getResult()); } diff --git a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/MultiplicityAdapter.java b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/MultiplicityAdapter.java index 561680cb5..be6d90b97 100644 --- a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/MultiplicityAdapter.java +++ b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/MultiplicityAdapter.java @@ -1,6 +1,6 @@ /******************************************************************************* * SysML 2 Pilot Implementation - * Copyright (c) 2021, 2024, 2025 Model Driven Solutions, Inc. + * Copyright (c) 2021, 2024-2026 Model Driven Solutions, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the Eclipse Public License as published by @@ -27,9 +27,7 @@ import org.omg.sysml.lang.sysml.Element; import org.omg.sysml.lang.sysml.Feature; import org.omg.sysml.lang.sysml.Multiplicity; -import org.omg.sysml.lang.sysml.Namespace; import org.omg.sysml.lang.sysml.Type; -import org.omg.sysml.util.FeatureUtil; public class MultiplicityAdapter extends FeatureAdapter { @@ -64,21 +62,6 @@ protected List getRelevantFeatures(Type type) { /** * @satisfies checkMultiplicityTypeFeaturing */ - @Override - protected void addImplicitFeaturingTypesIfNecessary() { - Feature feature = getTarget(); - Namespace owner = feature.getOwningNamespace(); - if (owner instanceof Feature) { - Namespace owningEnd = owner.getOwningNamespace(); - if (FeatureUtil.isOwnedCrossFeature((Feature)owner) && - isImplicitFeaturingTypesEmpty()) { - addFeaturingTypes(((Feature)owningEnd).getFeaturingType()); - } else { - super.addImplicitFeaturingTypesIfNecessary(); - } - } - } - @Override public void doTransform() { super.doTransform(); diff --git a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java index 4faa7ac4c..455af328f 100644 --- a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java +++ b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java @@ -20,6 +20,7 @@ package org.omg.sysml.logic; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import org.junit.BeforeClass; @@ -27,9 +28,13 @@ import org.omg.sysml.lang.sysml.Association; import org.omg.sysml.lang.sysml.BindingConnector; +import org.omg.sysml.lang.sysml.Classifier; import org.omg.sysml.lang.sysml.Feature; +import org.omg.sysml.lang.sysml.LiteralInteger; +import org.omg.sysml.lang.sysml.Multiplicity; import org.omg.sysml.lang.sysml.SysMLFactory; import org.omg.sysml.util.ConnectorUtil; +import org.omg.sysml.util.ElementUtil; import org.omg.sysml.util.FeatureUtil; import org.omg.sysml.util.NamespaceUtil; import org.omg.sysml.util.TypeUtil; @@ -67,10 +72,61 @@ public void testKERML11_1() { Feature feature = SysMLFactory.eINSTANCE.createFeature(); feature.setDeclaredName("crossFeature"); - NamespaceUtil.addOwnedMemberTo(end1, feature); + NamespaceUtil.addOwnedMemberTo(end1, feature); Feature crossFeature = end1.ownedCrossFeature(); assertNotNull("Not null", crossFeature); assertEquals("cross feature", feature, crossFeature); } + + /** + * Test resolution to KERML11-3 Featuring type of the multiplicity of a cross feature + * @throws InvocationTargetException + */ + @Test + public void testKERML11_3() { + Association association = SysMLFactory.eINSTANCE.createAssociation(); + Classifier classifier = SysMLFactory.eINSTANCE.createClassifier(); + + Feature end1 = SysMLFactory.eINSTANCE.createFeature(); + end1.setDeclaredName("end1"); + end1.setIsEnd(true); + FeatureUtil.addFeatureTypingTo(end1).setType(classifier); + TypeUtil.addOwnedFeatureTo(association, end1); + + Feature end2 = SysMLFactory.eINSTANCE.createFeature(); + end2.setDeclaredName("end2"); + end2.setIsEnd(true); + FeatureUtil.addFeatureTypingTo(end2).setType(classifier); + TypeUtil.addOwnedFeatureTo(association, end2); + + Feature feature = SysMLFactory.eINSTANCE.createFeature(); + feature.setDeclaredName("crossFeature"); + NamespaceUtil.addOwnedMemberTo(end1, feature); + + Multiplicity multiplicityRange = SysMLFactory.eINSTANCE.createMultiplicityRange(); + NamespaceUtil.addOwnedMemberTo(feature, multiplicityRange); + + LiteralInteger lowerBound = SysMLFactory.eINSTANCE.createLiteralInteger(); + lowerBound.setValue(1); + NamespaceUtil.addOwnedMemberTo(multiplicityRange, lowerBound); + LiteralInteger upperBound = SysMLFactory.eINSTANCE.createLiteralInteger(); + upperBound.setValue(1); + NamespaceUtil.addOwnedMemberTo(multiplicityRange, upperBound); + + ElementUtil.transformAll(association, false); + + assertEquals("crossFeature", end1.ownedCrossFeature(), feature); + assertFalse("crossFeature.featuringType.isEmpty", feature.getFeaturingType().isEmpty()); + + assertFalse("multiplicity.featuringType.isEmpty", multiplicityRange.getFeaturingType().isEmpty()); + assertEquals("multiplicity.featuringType", feature.getFeaturingType().get(0), multiplicityRange.getFeaturingType().get(0)); + + assertFalse("lowerBound.featuringType.isEmpty", lowerBound.getFeaturingType().isEmpty()); + assertEquals("lowerBound.featuringType", association, lowerBound.getFeaturingType().get(0)); + + assertFalse("upperBound.featuringType.isEmpty", upperBound.getFeaturingType().isEmpty()); + assertEquals("upperBound.featuringType", association, upperBound.getFeaturingType().get(0)); + } + } From d9231d21e621aeabeafa92aef026b3929c859116 Mon Sep 17 00:00:00 2001 From: Ed Seidewitz Date: Sun, 2 Aug 2026 16:05:43 -0400 Subject: [PATCH 3/6] KERML11-68 Revised validateRedefinitionEndConformance impl as resolved. - Also updated Xpect test Redefinition_End_Invalid.kerml. --- .../Redefinition_End_Invalid.kerml.xt | 23 ++++++++++++++++++- .../xtext/validation/KerMLValidator.xtend | 9 +++++--- .../sysml/logic/KERML11_Ballot3_Tests.java | 4 +++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/org.omg.kerml.xpect.tests/src/org/omg/kerml/xpect/tests/validation/Redefinition_End_Invalid.kerml.xt b/org.omg.kerml.xpect.tests/src/org/omg/kerml/xpect/tests/validation/Redefinition_End_Invalid.kerml.xt index a7aaac6cd..5030bc677 100644 --- a/org.omg.kerml.xpect.tests/src/org/omg/kerml/xpect/tests/validation/Redefinition_End_Invalid.kerml.xt +++ b/org.omg.kerml.xpect.tests/src/org/omg/kerml/xpect/tests/validation/Redefinition_End_Invalid.kerml.xt @@ -3,6 +3,7 @@ XPECT_SETUP org.omg.kerml.xpect.tests.validation.KerMLValidationTest ResourceSet { ThisFile {} File {from ="/library/Base.kerml"} + File {from ="/library/Links.kerml"} File {from ="/library/Occurrences.kerml"} File {from ="/library/Objects.kerml"} File {from ="/library/Performances.kerml"} @@ -12,6 +13,7 @@ XPECT_SETUP org.omg.kerml.xpect.tests.validation.KerMLValidationTest SrcFolder { ThisFile {} File {from ="/library/Base.kerml"} + File {from ="/library/Links.kerml"} File {from ="/library/Occurrences.kerml"} File {from ="/library/Objects.kerml"} File {from ="/library/Performances.kerml"} @@ -26,8 +28,27 @@ package RedefinitionEnd { } classifier B :> A { - // XPECT errors ---> "Redefining feature must be an end feature" at "e" feature :>> e; } + + assoc R { + end a : A; + end b : B; + } + + abstract connector r : R { + end a; + end b; + } + + abstract assoc R1 :> R { + // XPECT errors ---> "Redefining feature must be an end feature" at "a" + feature a1 :>> a; + } + + abstract connector r1 :> r { + // XPECT errors ---> "Redefining feature must be an end feature" at "a" + feature a1 :>> a; + } } \ No newline at end of file diff --git a/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend b/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend index 04896a2b0..019218c84 100644 --- a/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend +++ b/org.omg.kerml.xtext/src/org/omg/kerml/xtext/validation/KerMLValidator.xtend @@ -725,10 +725,13 @@ class KerMLValidator extends AbstractKerMLValidator { } } - // validatRedefinitionEndConformance + // validateRedefinitionEndConformance if (redefinedFeature.isEnd && !redefiningFeature.isEnd) { - error(INVALID_REDEFINITION_END_CONFORMANCE_MSG, redef, - SysMLPackage.eINSTANCE.redefinition_RedefinedFeature, INVALID_REDEFINITION_END_CONFORMANCE) + val redefiningOwner = redefiningFeature.owningType + if (redefiningOwner instanceof Association || redefiningOwner instanceof Connector) { + error(INVALID_REDEFINITION_END_CONFORMANCE_MSG, redef, + SysMLPackage.eINSTANCE.redefinition_RedefinedFeature, INVALID_REDEFINITION_END_CONFORMANCE) + } } } } diff --git a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java index 455af328f..1b7e1a948 100644 --- a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java +++ b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java @@ -22,7 +22,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; - import org.junit.BeforeClass; import org.junit.Test; @@ -129,4 +128,7 @@ public void testKERML11_3() { assertEquals("upperBound.featuringType", association, upperBound.getFeaturingType().get(0)); } + /* + * KERML11-68 is a validation change. + */ } From c695c009fb1237f82823300901ed15a780bb30a4 Mon Sep 17 00:00:00 2001 From: Ed Seidewitz Date: Sun, 2 Aug 2026 16:09:21 -0400 Subject: [PATCH 4/6] KERML11-69 Removed TODO for spec update in IndexExpressionAdapter. --- .../java/org/omg/sysml/adapter/IndexExpressionAdapter.java | 6 ------ .../java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/IndexExpressionAdapter.java b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/IndexExpressionAdapter.java index 18940f9a3..0d764afd4 100644 --- a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/IndexExpressionAdapter.java +++ b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/IndexExpressionAdapter.java @@ -54,12 +54,6 @@ protected void addResultTyping() { ElementUtil.transform(seqArgument); Feature seqResult = seqArgument.getResult(); Type collectionType = getLibraryType(COLLECTIONS_TYPE); - /* - * TODO: Update checkIndexExpressionResultSpecialization - * - * OCL currently only checks for Array type, not any Collection type. - * See KERML11-69 - */ if (!TypeUtil.specializes(seqResult, collectionType)) { Feature resultFeature = target.getResult(); if (resultFeature != null && seqResult != null) { diff --git a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java index 1b7e1a948..6e80bc593 100644 --- a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java +++ b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java @@ -131,4 +131,8 @@ public void testKERML11_3() { /* * KERML11-68 is a validation change. */ + + /* + * KERML11-69 was previously implemented. + */ } From b2e52a3f7b4a11735db95abfdf64a8e0e552fcb7 Mon Sep 17 00:00:00 2001 From: Ed Seidewitz Date: Sun, 2 Aug 2026 19:22:26 -0400 Subject: [PATCH 5/6] KERML11-191 Added Junit test, but issue resolution already implemented. --- .../expressions/xtext/KerMLExpressions.xtext | 3 +- .../src/org/omg/kerml/xtext/KerML.xtext | 3 +- .../sysml/logic/KERML11_Ballot3_Tests.java | 48 +++++++++++++++++++ .../src/org/omg/sysml/xtext/SysML.xtext | 4 +- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/org.omg.kerml.expressions.xtext/src/org/omg/kerml/expressions/xtext/KerMLExpressions.xtext b/org.omg.kerml.expressions.xtext/src/org/omg/kerml/expressions/xtext/KerMLExpressions.xtext index 2df593c9f..ef5ce75d7 100644 --- a/org.omg.kerml.expressions.xtext/src/org/omg/kerml/expressions/xtext/KerMLExpressions.xtext +++ b/org.omg.kerml.expressions.xtext/src/org/omg/kerml/expressions/xtext/KerMLExpressions.xtext @@ -2,7 +2,6 @@ * SysML 2 Pilot Implementation * Copyright (c) 2018-2025 Model Driven Solutions, Inc. * Copyright (c) 2018 IncQuery Labs Ltd. - * Copyright (c) 2019 Maplesoft (Waterloo Maple, Inc.) * Copyright (c) 2019 Mgnite Inc. * * This program is free software: you can redistribute it and/or modify @@ -23,7 +22,7 @@ * Ed Seidewitz, MDS * Zoltan Kiss, IncQuery * Balazs Grill, IncQuery - * Hisashi Miyashita, Maplesoft/Mgnite + * Hisashi Miyashita, Mgnite * *****************************************************************************/ diff --git a/org.omg.kerml.xtext/src/org/omg/kerml/xtext/KerML.xtext b/org.omg.kerml.xtext/src/org/omg/kerml/xtext/KerML.xtext index cf583f04d..605c3f232 100644 --- a/org.omg.kerml.xtext/src/org/omg/kerml/xtext/KerML.xtext +++ b/org.omg.kerml.xtext/src/org/omg/kerml/xtext/KerML.xtext @@ -2,7 +2,6 @@ * SysML 2 Pilot Implementation * Copyright (c) 2018-2025 Model Driven Solutions, Inc. * Copyright (c) 2018 IncQuery Labs Ltd. - * Copyright (c) 2019 Maplesoft (Waterloo Maple, Inc.) * Copyright (c) 2019 Mgnite Inc. * * This program is free software: you can redistribute it and/or modify @@ -23,7 +22,7 @@ * Ed Seidewitz, MDS * Zoltan Kiss, IncQuery * Balazs Grill, IncQuery - * Hisashi Miyashita, Maplesoft/Mgnite + * Hisashi Miyashita, Mgnite * *****************************************************************************/ diff --git a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java index 6e80bc593..3507045cd 100644 --- a/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java +++ b/org.omg.sysml.logic/src/test/java/org/omg/sysml/logic/KERML11_Ballot3_Tests.java @@ -22,6 +22,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + import org.junit.BeforeClass; import org.junit.Test; @@ -31,7 +35,10 @@ import org.omg.sysml.lang.sysml.Feature; import org.omg.sysml.lang.sysml.LiteralInteger; import org.omg.sysml.lang.sysml.Multiplicity; +import org.omg.sysml.lang.sysml.NamespaceImport; +import org.omg.sysml.lang.sysml.Subclassification; import org.omg.sysml.lang.sysml.SysMLFactory; +import org.omg.sysml.lang.sysml.VisibilityKind; import org.omg.sysml.util.ConnectorUtil; import org.omg.sysml.util.ElementUtil; import org.omg.sysml.util.FeatureUtil; @@ -135,4 +142,45 @@ public void testKERML11_3() { /* * KERML11-69 was previously implemented. */ + + /** + * Test resolution to KERML11-191 Featuring type of the multiplicity of a cross feature + * @throws InvocationTargetException + */ + @Test + public void testKERML11_191() { + Classifier A = SysMLFactory.eINSTANCE.createClassifier(); + A.setDeclaredName("A"); + + Feature x = SysMLFactory.eINSTANCE.createFeature(); + x.setDeclaredName("x"); + TypeUtil.addOwnedFeatureTo(A, x); + + Classifier B = SysMLFactory.eINSTANCE.createClassifier(); + B.setDeclaredName("B"); + + NamespaceImport _import = SysMLFactory.eINSTANCE.createNamespaceImport(); + _import.setVisibility(VisibilityKind.PUBLIC); + _import.setImportedNamespace(A); + B.getOwnedRelationship().add(_import); + + Feature y = SysMLFactory.eINSTANCE.createFeature(); + y.setDeclaredName("y"); + TypeUtil.addOwnedFeatureTo(B, y); + + List features = B.getFeature(); + assertTrue("feature B::y", features.contains(y)); + assertFalse("not feature B::x", features.contains(x)); + + Classifier C = SysMLFactory.eINSTANCE.createClassifier(); + C.setDeclaredName("C"); + Subclassification subclassing = SysMLFactory.eINSTANCE.createSubclassification(); + subclassing.setSubclassifier(C); + subclassing.setSuperclassifier(B); + C.getOwnedRelationship().add(subclassing); + + features = C.getFeature(); + assertTrue("feature C::y", features.contains(y)); + assertFalse("not feature C::x", features.contains(x)); + } } diff --git a/org.omg.sysml.xtext/src/org/omg/sysml/xtext/SysML.xtext b/org.omg.sysml.xtext/src/org/omg/sysml/xtext/SysML.xtext index 1bf96c1bd..7f7cbac56 100644 --- a/org.omg.sysml.xtext/src/org/omg/sysml/xtext/SysML.xtext +++ b/org.omg.sysml.xtext/src/org/omg/sysml/xtext/SysML.xtext @@ -2,13 +2,11 @@ * SysML 2 Pilot Implementation * Copyright (c) 2018-2025 Model Driven Solutions, Inc. * Copyright (c) 2018 IncQuery Labs Ltd. - * Copyright (c) 2019 Maplesoft (Waterloo Maple, Inc.) * Copyright (c) 2019 Mgnite Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the Eclipse Public License as published by * the Eclipse Foundation, version 2 of the License. - * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,7 +22,7 @@ * Ed Seidewitz, MDS * Zoltan Kiss, IncQuery * Balazs Grill, IncQuery - * Hisashi Miyashita, Maplesoft/Mgnite + * Hisashi Miyashita, Mgnite * *****************************************************************************/ From 84d8251b345fd25da7d5ad4f499cd21a368a698d Mon Sep 17 00:00:00 2001 From: Ed Seidewitz Date: Wed, 5 Aug 2026 13:40:15 -0400 Subject: [PATCH 6/6] ST6RI-957 Made minor updates in response to review comments. --- .../omg/sysml/adapter/ExpressionAdapter.java | 8 +++---- .../java/org/omg/sysml/util/FeatureUtil.java | 24 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java index 80c22e1dd..75103c288 100644 --- a/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java +++ b/org.omg.sysml.logic/src/main/java/org/omg/sysml/adapter/ExpressionAdapter.java @@ -113,11 +113,11 @@ protected void addImplicitFeaturingTypesIfNecessary() { if (owner instanceof MultiplicityRange multiplicity && multiplicity.getBound().contains(expression)) { owner = multiplicity.getOwningNamespace(); - if (owner instanceof Feature) { - Namespace owningEnd = owner.getOwningNamespace(); - if (FeatureUtil.isOwnedCrossFeature((Feature)owner) && + if (owner instanceof Feature ownerFeature) { + if (FeatureUtil.isOwnedCrossFeature(ownerFeature) && isImplicitFeaturingTypesEmpty()) { - addFeaturingTypes(((Feature)owningEnd).getFeaturingType()); + Feature owningEnd = (Feature) ownerFeature.getOwningNamespace(); + addFeaturingTypes(owningEnd.getFeaturingType()); } else { super.addImplicitFeaturingTypesIfNecessary(); } diff --git a/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java b/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java index 7ceeda8e6..9950230c8 100644 --- a/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java +++ b/org.omg.sysml.logic/src/main/java/org/omg/sysml/util/FeatureUtil.java @@ -234,17 +234,19 @@ public static Feature getCrossFeatureOf(Feature feature) { } public static Feature getOwnedCrossFeatureOf(Namespace namespace) { - return !(namespace instanceof Feature feature) || - !feature.isEnd() || - feature.getOwningType() == null? null: - (Feature)namespace.getOwnedMember().stream(). - filter(element->element instanceof Feature && - !(element instanceof Multiplicity) && - !(element instanceof MetadataFeature) && - !(element instanceof BindingConnector) && - !(element.getOwningMembership() instanceof FeatureMembership) && - !(element.getOwningMembership() instanceof FeatureValue)). - findFirst().orElse(null); + if (!(namespace instanceof Feature feature) || + !feature.isEnd() || feature.getOwningType() == null) { + return null; + } else { + return (Feature)namespace.getOwnedMember().stream(). + filter(element->element instanceof Feature && + !(element instanceof Multiplicity) && + !(element instanceof MetadataFeature) && + !(element instanceof BindingConnector) && + !(element.getOwningMembership() instanceof FeatureMembership) && + !(element.getOwningMembership() instanceof FeatureValue)). + findFirst().orElse(null); + } } public static boolean isOwnedCrossFeature(Feature feature) {