Skip to content

Commit a916c5f

Browse files
committed
ST6RI-897 Moved the InvocationExpression operand mechanism to adapter.
- Updated CustomUML2EcoreConverter to add SysML EAnnotation to the Element::operand EAttribute, when it adds that to the Ecore metamodel, so that a setting delegation is generated. - Also changed uses of getOperand to getArgument in plantuml/VPath and VSequence.
1 parent 3410252 commit a916c5f

15 files changed

Lines changed: 360 additions & 174 deletions

File tree

org.omg.sysml.interactive.tests/src/org/omg/sysml/interactive/tests/ModelLevelEvaluationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ protected Expression checkFilterExpression(SysMLInteractive instance, String tex
5757
assertFalse("'" + text + "': No filter conditions", filterConditions.isEmpty());
5858
Expression filterCondition = filterConditions.get(0);
5959
assertTrue("'" + text + "': Not operator expression", filterCondition instanceof OperatorExpression);
60-
List<Expression> operands = ((OperatorExpression)filterCondition).getOperand();
60+
List<Expression> operands = ((OperatorExpression)filterCondition).getArgument();
6161
assertFalse("'" + text + "': No operands", operands.isEmpty());
6262
return operands.get(0);
6363
}

org.omg.sysml.plantuml/src/org/omg/sysml/plantuml/VPath.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ private class PCFeatureChainExpression extends PC {
170170
private final FeatureChainExpression fce;
171171

172172
private Expression getTargetExp() {
173-
List<Expression> ops = fce.getOperand();
173+
List<Expression> ops = fce.getArgument();
174174
if (ops.isEmpty()) {
175175
return null;
176176
} else {

org.omg.sysml.plantuml/src/org/omg/sysml/plantuml/VSequence.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ private static boolean isTarget(Feature f) {
110110
}
111111

112112
private Element next(FeatureChainExpression fce, boolean first) {
113-
List<Expression> ops = fce.getOperand();
113+
List<Expression> ops = fce.getArgument();
114114
int size = ops.size();
115115
if (size == 0) return null;
116116
Expression ex = ops.get(0);

org.omg.sysml.uml.ecore.importer/src/org/omg/sysml/uml/ecore/importer/CustomUML2EcoreConverter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ private void customConvert(DiagnosticChain diagnostics) {
5959
addSysMLAnnotation("Feature::isNonUnique", isNonUniqueAttribute);
6060
} else if ("InvocationExpression".equals(name)) {
6161
EClassifier expressionClass = eClass.getEStructuralFeature("argument").getEType();
62-
addStructuralFeature(eClass, EcoreFactory.eINSTANCE.createEReference(), "operand", expressionClass, 0, -1, null, true);
62+
EReference operandReference = EcoreFactory.eINSTANCE.createEReference();
63+
addStructuralFeature(eClass, operandReference, "operand", expressionClass, 0, -1, null, true);
64+
addSysMLAnnotation("InvocationExpression::operand", operandReference);
6365
}
6466
}
6567
}

org.omg.sysml/model/SysML.ecore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
<details key="documentation" value="&lt;p>An &lt;code>InvocationExpression&lt;/code> is an &lt;code>InstantiationExpression&lt;/code> whose &lt;code>instantiatedType&lt;/code> must be a &lt;code>Behavior&lt;/code> or a &lt;code>Feature&lt;/code> typed by a single &lt;code>Behavior&lt;/code> (such as a &lt;code>Step&lt;/code>). Each of the input &lt;code>parameters&lt;/code> of the &lt;code>instantiatedType&lt;/code> are bound to the &lt;code>result&lt;/code> of an &lt;code>argument&lt;/code> &lt;code>Expression&lt;/code>. If the &lt;code>instantiatedType&lt;/code> is a &lt;code>Function&lt;/code> or a &lt;code>Feature&lt;/code> typed by a &lt;code>Function&lt;/code>, then the &lt;code>result&lt;/code> of the &lt;code>InvocationExpression&lt;/code> is the &lt;code>result&lt;/code> of the invoked &lt;code>Function&lt;/code>. Otherwise, the &lt;code>result&lt;/code> is an instance of the &lt;code>instantiatedType&lt;/code> (essentially like a behavioral &lt;code>ConstructorExpression&lt;/code>).&lt;/p>&#xA;&#xA;not instantiatedType.oclIsKindOf(Function) and&#xA;not (instantiatedType.oclIsKindOf(Feature) and &#xA; instantiatedType.oclAsType(Feature).type->exists(oclIsKindOf(Function))) implies&#xA; ownedFeature.selectByKind(BindingConnector)->exists(&#xA; relatedFeature->includes(self) and&#xA; relatedFeature->includes(result))&#xA;TBD&#xA;instantiatedType.input->collect(inp | &#xA; ownedFeatures->select(redefines(inp)).valuation->&#xA; select(v | v &lt;> null).value&#xA;)&#xA;let parameters : OrderedSet(Feature) = instantiatedType.input in&#xA;input->forAll(inp | &#xA; inp.ownedRedefinition.redefinedFeature->&#xA; intersection(parameters)->size() = 1)&#xA;let features : OrderedSet(Feature) = instantiatedType.feature in&#xA;input->forAll(inp1 | input->forAll(inp2 |&#xA; inp1 &lt;> inp2 implies&#xA; inp1.ownedRedefinition.redefinedFeature->&#xA; intersection(inp2.ownedRedefinition.redefinedFeature)->&#xA; intersection(features)->isEmpty()))&#xA;not instantiatedType.oclIsKindOf(Function) and&#xA;not (instantiatedType.oclIsKindOf(Feature) and &#xA; instantiatedType.oclAsType(Feature).type->exists(oclIsKindOf(Function))) implies&#xA; result.specializes(instantiatedType)&#xA;specializes(instantiatedType)&#xA;instantiatedType.oclIsKindOf(Behavior) or&#xA;instantiatedType.oclIsKindOf(Feature) and&#xA; instantiatedType.type->exists(oclIsKindOf(Behavior)) and&#xA; instantiatedType.type->size(1)&#xA;ownedFeature->forAll(f |&#xA; f &lt;> result implies &#xA; f.direction = FeatureDirectionKind::_'in')"/>
2727
</eAnnotations>
2828
<eStructuralFeatures xsi:type="ecore:EReference" name="operand" upperBound="-1"
29-
eType="#//Expression" volatile="true" transient="true" derived="true" containment="true"/>
29+
eType="#//Expression" volatile="true" transient="true" derived="true" containment="true">
30+
<eAnnotations source="http://www.omg.org/spec/SysML"/>
31+
</eStructuralFeatures>
3032
</eClassifiers>
3133
<eClassifiers xsi:type="ecore:EClass" name="InstantiationExpression" abstract="true"
3234
eSuperTypes="#//Expression">

org.omg.sysml/src/org/omg/sysml/adapter/InvocationExpressionAdapter.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*******************************************************************************
22
* SysML 2 Pilot Implementation
3-
* Copyright (c) 2021-2025 Model Driven Solutions, Inc.
3+
* Copyright (c) 2021-2026 Model Driven Solutions, Inc.
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU Lesser General Public License as published by
@@ -21,11 +21,14 @@
2121

2222
package org.omg.sysml.adapter;
2323

24+
import org.eclipse.emf.common.util.EList;
25+
import org.omg.sysml.lang.sysml.Expression;
2426
import org.omg.sysml.lang.sysml.Feature;
2527
import org.omg.sysml.lang.sysml.Function;
2628
import org.omg.sysml.lang.sysml.InvocationExpression;
2729
import org.omg.sysml.lang.sysml.SysMLPackage;
2830
import org.omg.sysml.lang.sysml.Type;
31+
import org.omg.sysml.util.OperandEList;
2932
import org.omg.sysml.util.TypeUtil;
3033

3134
public class InvocationExpressionAdapter extends InstantiationExpressionAdapter {
@@ -39,6 +42,28 @@ public InvocationExpression getTarget() {
3942
return (InvocationExpression)super.getTarget();
4043
}
4144

45+
// Operand mechanism
46+
47+
/**
48+
* Xtext workaround:
49+
* "operand" is an additional property not in the normative abstract syntax, but added to the Ecore.
50+
* It contains a list of direct containment references to arguments of this InvocationExpression.
51+
* It allows for tractable parsing in Xtext of expressions with left-recursive syntax
52+
* (particularly operator expressions).
53+
*/
54+
protected EList<Expression> operand = null;
55+
56+
/**
57+
* Use a special OperandEList so that operands inserted into the list are automatically actually added
58+
* as owned features.
59+
*/
60+
public EList<Expression> getOperand() {
61+
if (operand == null) {
62+
operand = new OperandEList(getTarget());
63+
}
64+
return operand;
65+
}
66+
4267
// Implicit generalization
4368

4469
@Override

org.omg.sysml/src/org/omg/sysml/adapter/OwningMembershipAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public String createElementId() {
4848
OwningMembership target = getTarget();
4949

5050
Element ownedMemberElement = target.getOwnedMemberElement();
51-
if (!ElementUtil.isStandardLibraryElement(target) &&
51+
if (!ElementUtil.isStandardLibraryElement(target) && ownedMemberElement != null &&
5252
ElementUtil.isStandardLibraryElement(ownedMemberElement) &&
5353
ownedMemberElement.libraryNamespace() == ownedMemberElement) {
5454
String path = target.path();

org.omg.sysml/src/org/omg/sysml/delegate/setting/Element_elementId_SettingDelegate.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,10 @@ protected Object basicGet(InternalEObject owner) {
4242
public void set(InternalEObject owner, Object elementId) {
4343
ElementUtil.setElementIdOf((Element)owner, (String)elementId);
4444
}
45+
46+
@Override
47+
public boolean isSet(InternalEObject owner) {
48+
return true;
49+
}
4550

4651
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*******************************************************************************
2+
* SysML 2 Pilot Implementation
3+
* Copyright (c) 2026 Model Driven Solutions, Inc.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
* @license LGPL-3.0-or-later <http://spdx.org/licenses/LGPL-3.0-or-later>
19+
*
20+
*******************************************************************************/
21+
22+
package org.omg.sysml.delegate.setting;
23+
24+
import org.eclipse.emf.common.util.EList;
25+
import org.eclipse.emf.ecore.EStructuralFeature;
26+
import org.eclipse.emf.ecore.InternalEObject;
27+
import org.omg.sysml.lang.sysml.Expression;
28+
import org.omg.sysml.lang.sysml.InvocationExpression;
29+
import org.omg.sysml.util.ExpressionUtil;
30+
31+
public class InvocationExpression_operand_SettingDelegate extends BasicDerivedListSettingDelegate {
32+
33+
public InvocationExpression_operand_SettingDelegate(EStructuralFeature eStructuralFeature) {
34+
super(eStructuralFeature);
35+
}
36+
37+
@Override
38+
protected EList<Expression> basicGet(InternalEObject owner) {
39+
return ExpressionUtil.getOperandsOf((InvocationExpression)owner);
40+
}
41+
42+
}

org.omg.sysml/src/org/omg/sysml/util/ExpressionUtil.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.eclipse.emf.common.util.EList;
2929
import org.omg.sysml.adapter.ExpressionAdapter;
3030
import org.omg.sysml.adapter.FeatureReferenceExpressionAdapter;
31+
import org.omg.sysml.adapter.InvocationExpressionAdapter;
3132
import org.omg.sysml.lang.sysml.ConstructorExpression;
3233
import org.omg.sysml.lang.sysml.DataType;
3334
import org.omg.sysml.lang.sysml.Element;
@@ -188,4 +189,8 @@ public static boolean isConstructorResult(Type type) {
188189
((Feature)type).getOwningFeatureMembership() instanceof ReturnParameterMembership;
189190
}
190191

192+
public static EList<Expression> getOperandsOf(InvocationExpression expression) {
193+
return ((InvocationExpressionAdapter)getExpressionAdapter(expression)).getOperand();
194+
}
195+
191196
}

0 commit comments

Comments
 (0)