From 00a0d16ee2c79aa6f45c2f27d888ea28acd32287 Mon Sep 17 00:00:00 2001
From: Philip Makedonski <makedonski@cs.uni-goettingen.de>
Date: Thu, 11 Jan 2024 20:40:35 +0100
Subject: [PATCH] + location expressions for parameter bindings (meta-model,
 constraints)

+ (partial?) scoping support
---
 .../mts/tdl/scoping/TDLScopeProvider.java     | 84 +++++++++++++++++++
 .../model/tdl-constraints.ocl                 |  6 +-
 .../org.etsi.mts.tdl.model/model/tdl.ecore    | 11 ++-
 .../org.etsi.mts.tdl.model/model/tdl.genmodel |  2 +
 4 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/plugins/org.etsi.mts.tdl.common/src/org/etsi/mts/tdl/scoping/TDLScopeProvider.java b/plugins/org.etsi.mts.tdl.common/src/org/etsi/mts/tdl/scoping/TDLScopeProvider.java
index dff9d411..5d444f4d 100644
--- a/plugins/org.etsi.mts.tdl.common/src/org/etsi/mts/tdl/scoping/TDLScopeProvider.java
+++ b/plugins/org.etsi.mts.tdl.common/src/org/etsi/mts/tdl/scoping/TDLScopeProvider.java
@@ -383,10 +383,50 @@ public class TDLScopeProvider extends AbstractDeclarativeScopeProvider {
 						return scope;
 					} else if (dataElement == null) {
 						//TODO: use more widely! Will save a lot of the code in here...
+						//if reduction?
+						if (context.eContainer().eContainer() instanceof ParameterBinding) {
+							//TODO: use newly introduced resolveParameterType?
+							EList<MemberReference> reduction = ((ParameterBinding)context.eContainer().eContainer()).getReduction();
+							if (reduction.size() > 0) {
+								if (reduction.get(reduction.size()-1).getMember() == null) {
+									DataType dataType = ((ParameterBinding)reduction.get(reduction.size()-1).eContainer()).getParameter().getDataType();
+									if (dataType instanceof StructuredDataType) {
+										IScope scope = Scopes.scopeFor(((StructuredDataType)dataType).allMembers());
+										return scope;
+									} else if (dataType instanceof CollectionDataType) {
+										DataType itemType = ((CollectionDataType)dataType).getItemType();
+										if (itemType instanceof StructuredDataType) {
+											IScope scope = Scopes.scopeFor(((StructuredDataType) itemType).allMembers());
+											return scope;
+										}
+									}
+								} else {
+									DataType dataType = reduction.get(reduction.size()-1).getMember().getDataType();
+									if (dataType instanceof StructuredDataType) {
+										IScope scope = Scopes.scopeFor(((StructuredDataType)dataType).allMembers());
+										return scope;
+									} else if (dataType instanceof CollectionDataType) {
+										DataType itemType = ((CollectionDataType)dataType).getItemType();
+										if (itemType instanceof StructuredDataType) {
+											IScope scope = Scopes.scopeFor(((StructuredDataType) itemType).allMembers());
+											return scope;
+										}
+									}
+									IScope scope = Scopes.scopeFor(((StructuredDataType) dataType).allMembers());
+									return scope;
+								}
+							}
+						}
 						DataType resolvedDataType = ((DataElementUse)context.eContainer()).resolveDataType();
 						if (resolvedDataType instanceof StructuredDataType) {
 							IScope scope = Scopes.scopeFor(((StructuredDataType)resolvedDataType).allMembers());
 							return scope;
+						} else if (resolvedDataType instanceof CollectionDataType) {
+							DataType itemType = ((CollectionDataType)resolvedDataType).getItemType();
+							if (itemType instanceof StructuredDataType) {
+								IScope scope = Scopes.scopeFor(((StructuredDataType) itemType).allMembers());
+								return scope;
+							}
 						} else if (resolvedDataType == null) {
 //							DataType resolvedContextDataType = null;
 //							if (context.eContainer().eContainer() instanceof DataElementUse) {
@@ -404,6 +444,12 @@ public class TDLScopeProvider extends AbstractDeclarativeScopeProvider {
 						
 //					IScope scope = Scopes.scopeFor(dataElement.eContents());
 //					return scope;
+				} else if (context.eContainer() instanceof ParameterBinding) {
+					DataType pdt = ((ParameterBinding)context.eContainer()).getParameter().getDataType();
+					if (pdt instanceof StructuredDataType) {
+						IScope scope = Scopes.scopeFor(((StructuredDataType) pdt).allMembers());
+						return scope;
+					}
 				} else if (context.eContainer() instanceof LiteralValueUse) {
 					DataType resolvedDataType = ((LiteralValueUse)context.eContainer()).resolveDataType();
 					if (resolvedDataType instanceof StructuredDataType) {
@@ -412,6 +458,43 @@ public class TDLScopeProvider extends AbstractDeclarativeScopeProvider {
 					}
 				}
 			} else if (context instanceof MemberReference) {
+				if (context.eContainer() instanceof ParameterBinding) {
+					//TODO: use newly introduced resolveParameterType?
+					if (((ParameterBinding)context.eContainer()).getReduction().indexOf(context)>0) {
+						EObject targetContext = ((ParameterBinding)context.eContainer()).getReduction().get(((ParameterBinding)context.eContainer()).getReduction().indexOf(context)-1);
+						if (((MemberReference)targetContext).getMember()!=null) {
+							if (((MemberReference)targetContext).getMember().getDataType() instanceof StructuredDataType) {
+								IScope scope = Scopes.scopeFor(((StructuredDataType)((MemberReference)targetContext).getMember().getDataType()).allMembers());
+								return scope;
+							} else if (((MemberReference)targetContext).getMember().getDataType() instanceof CollectionDataType) {
+								DataType itemType = ((CollectionDataType)((MemberReference)targetContext).getMember().getDataType()).getItemType();
+								if (itemType instanceof StructuredDataType) {
+									IScope scope = Scopes.scopeFor(((StructuredDataType) itemType).allMembers());
+									return scope;
+								}
+							}
+						} else if (((MemberReference)targetContext).getCollectionIndex() != null) {
+							DataType dataType = ((ParameterBinding)targetContext.eContainer()).getParameter().getDataType();
+							if (dataType instanceof StructuredDataType) {
+								IScope scope = Scopes.scopeFor(((StructuredDataType) dataType).allMembers());
+								return scope;
+							} else if (dataType instanceof CollectionDataType) {
+								DataType itemType = ((CollectionDataType)dataType).getItemType();
+								if (itemType instanceof StructuredDataType) {
+									IScope scope = Scopes.scopeFor(((StructuredDataType) itemType).allMembers());
+									return scope;
+								}
+							}
+						}
+					} else {
+						DataType pdt = ((ParameterBinding)context.eContainer()).getParameter().getDataType();
+						if (pdt instanceof StructuredDataType) {
+							IScope scope = Scopes.scopeFor(((StructuredDataType) pdt).allMembers());
+							return scope;
+						}
+					}
+				} 
+				if (context.eContainer() instanceof DataUse) {
 				if (((DataUse)context.eContainer()).getReduction().indexOf(context)>0) {
 					EObject targetContext = ((DataUse)context.eContainer()).getReduction().get(((DataUse)context.eContainer()).getReduction().indexOf(context)-1);
 					if (((MemberReference)targetContext).getMember()!=null) {
@@ -452,6 +535,7 @@ public class TDLScopeProvider extends AbstractDeclarativeScopeProvider {
 						
 					}
 				} 
+				}
 				if (context.eContainer() instanceof DataInstanceUse) {
 					if (((DataInstanceUse)context.eContainer()).getDataInstance() instanceof StructuredDataInstance) {
 						DataInstance dataInstance = ((DataInstanceUse)context.eContainer()).getDataInstance();
diff --git a/plugins/org.etsi.mts.tdl.model/model/tdl-constraints.ocl b/plugins/org.etsi.mts.tdl.model/model/tdl-constraints.ocl
index 440da939..79a60574 100644
--- a/plugins/org.etsi.mts.tdl.model/model/tdl-constraints.ocl
+++ b/plugins/org.etsi.mts.tdl.model/model/tdl-constraints.ocl
@@ -288,7 +288,8 @@ context DataUse
 context ParameterBinding
   -- Matching data type
   inv ParameterBindingTypes ('The provided \'DataUse\' shall conform to the \'DataType\' of the referenced \'Parameter\'.' + self.toString()):
-        self.dataUse.resolveDataType().conformsTo(self.parameter.dataType)
+        self.dataUse.resolveDataType().conformsTo(self.resolveParameterType())
+        or self.dataUse.oclIsKindOf(SpecialValueUse)
   
 
   -- Use of a 'StructuredDataInstance' with non-optional 'Member's
@@ -303,6 +304,7 @@ context MemberReference
   -- Collection index expressions for collections only
   inv CollectionIndex ('If the type of the related \'DataUse\' is not \'CollectionDataType\' then the collectionIndex shall be undefined. ' + self.toString()):
         self.collectionIndex.oclIsUndefined()
+              or self.container().oclIsTypeOf(ParameterBinding) --and self.container().oclAsType(ParameterBinding).resolveDataType().oclIsKindOf(CollectionDataType)
               or self.container().oclAsType(DataUse).resolveDataType().oclIsKindOf(CollectionDataType)
   
 
@@ -1088,7 +1090,7 @@ context TestDescriptionReference
               self.componentInstanceBinding->one(c |
                   c.formalComponent = b.formalComponent or c.actualComponent = b.actualComponent))
   
-
+ 
   -- Compatible test configurations 
   inv CompatibleConfiguration ('The \'TestConfiguration\' of the referenced (invoked) \'TestDescription\' shall be compatible with the \'TestConfiguration\' of the referencing (invoking) \'TestDescription\' under the provided \'ComponentInstanceBinding\'s between the \'ComponentInstance\'s of the \'TestConfiguration\'s of referenced and referencing \'TestDescription\'s. ' + self.toString()):
         self.componentInstanceBinding->isEmpty()
diff --git a/plugins/org.etsi.mts.tdl.model/model/tdl.ecore b/plugins/org.etsi.mts.tdl.model/model/tdl.ecore
index 9ddbac7d..bcb804f9 100644
--- a/plugins/org.etsi.mts.tdl.model/model/tdl.ecore
+++ b/plugins/org.etsi.mts.tdl.model/model/tdl.ecore
@@ -208,10 +208,17 @@
         eType="#//MemberReference" containment="true"/>
   </eClassifiers>
   <eClassifiers xsi:type="ecore:EClass" name="ParameterBinding" eSuperTypes="#//Element">
+    <eOperations name="resolveParameterType" eType="#//DataType">
+      <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot">
+        <details key="body" value="&#x9;&#x9;&#x9;&#xA;&#x9;            &#x9;if (self.reduction->isEmpty()) then&#xA;&#x9;                &#x9;self.parameter.dataType&#xA;&#x9;            &#x9;else &#xA;&#x9;            &#x9;&#x9;if (self.reduction->last().member.oclIsUndefined()) then&#xA;&#x9;            &#x9;&#x9;&#x9;if (self.reduction->last().collectionIndex.oclIsUndefined()) then&#xA;&#x9;                &#x9;&#x9;&#x9;self.parameter.dataType&#xA;&#x9;            &#x9;&#x9;&#x9;else&#xA;&#x9;            &#x9;&#x9;&#x9;&#x9;self.parameter.dataType.oclAsType(CollectionDataType).itemType&#xA;&#x9;            &#x9;&#x9;&#x9;endif &#xA;&#x9;            &#x9;&#x9;else &#xA;&#x9;                &#x9;&#x9;self.reduction->last().member.dataType&#xA;&#x9;            &#x9;&#x9;endif&#xA;&#x9;                endif&#xA;&#x9;                "/>
+      </eAnnotations>
+    </eOperations>
     <eStructuralFeatures xsi:type="ecore:EReference" name="dataUse" lowerBound="1"
         eType="#//DataUse" containment="true"/>
     <eStructuralFeatures xsi:type="ecore:EReference" name="parameter" lowerBound="1"
         eType="#//Parameter"/>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="reduction" upperBound="-1"
+        eType="#//MemberReference" containment="true"/>
   </eClassifiers>
   <eClassifiers xsi:type="ecore:EEnum" name="UnassignedMemberTreatment">
     <eLiterals name="undefined"/>
@@ -691,7 +698,7 @@
   <eClassifiers xsi:type="ecore:EClass" name="PredefinedFunctionCall" eSuperTypes="#//DynamicDataUse">
     <eOperations name="resolveDataType" eType="#//DataType">
       <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot">
-        <details key="body" value="self.function.returnType"/>
+        <details key="body" value="&#xA;&#x9;                if not self.function.returnType.oclIsUndefined() then&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&#x9;self.function.returnType&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;else &#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&#x9;self.actualParameters.resolveDataType()->asOrderedSet()->first()&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;endif&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;"/>
       </eAnnotations>
     </eOperations>
     <eStructuralFeatures xsi:type="ecore:EReference" name="function" lowerBound="1"
@@ -804,7 +811,7 @@
   <eClassifiers xsi:type="ecore:EClass" name="DataElementUse" eSuperTypes="#//DataUse">
     <eOperations name="resolveDataType" eType="#//DataType">
       <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot">
-        <details key="body" value="&#xA;                if (not self.dataElement.oclIsUndefined()) then&#xA;                    if (self.dataElement.oclIsKindOf(DataType)) then&#xA;                        self.dataElement.oclAsType(DataType)&#xA;                    else&#xA;                        if (self.dataElement.oclIsKindOf(DataInstance)) then&#xA;                            self.dataElement.oclAsType(DataInstance).dataType&#xA;                        else &#xA;                            if (self.dataElement.oclIsTypeOf(FormalParameter)) then&#xA;                                self.dataElement.oclAsType(FormalParameter).dataType&#xA;                            else &#xA;                                if (self.dataElement.oclIsTypeOf(Function)) then&#xA;                                    self.dataElement.oclAsType(Function).returnType&#xA;                                else&#xA;                                    null&#xA;                                endif&#xA;                            endif &#xA;                        endif&#xA;                    endif&#xA;                else &#xA;                    if (self.container().oclIsTypeOf(MemberAssignment)) then&#xA;                        self.container().oclAsType(MemberAssignment).member.dataType&#xA;                    else &#xA;                        if (self.container().oclIsTypeOf(ParameterBinding)) then&#xA;                            self.container().oclAsType(ParameterBinding).parameter.dataType&#xA;                        else&#xA;                            if (self.container().oclIsTypeOf(CollectionDataInstance)) then&#xA;                                self.container().oclAsType(CollectionDataInstance).dataType.oclAsType(CollectionDataType).itemType&#xA;                            else&#xA;                                if (self.container().oclIsTypeOf(DataElementUse)) then&#xA;                                    self.container().oclAsType(DataElementUse).resolveDataType().oclAsType(CollectionDataType).itemType&#xA;                                else&#xA;                                    if (self.container().oclIsTypeOf(DataInstanceUse)) then&#xA;                                        self.container().oclAsType(DataInstanceUse).resolveDataType().oclAsType(CollectionDataType).itemType&#xA;                                    else&#xA;                                        null&#xA;                                    endif&#xA;                                endif&#xA;                            endif&#xA;                        endif&#xA;                    endif&#xA;                endif&#xA;                "/>
+        <details key="body" value="&#xA;                if (not self.dataElement.oclIsUndefined()) then&#xA;                    if (self.dataElement.oclIsKindOf(DataType)) then&#xA;                        self.dataElement.oclAsType(DataType)&#xA;                    else&#xA;                        if (self.dataElement.oclIsKindOf(DataInstance)) then&#xA;                            self.dataElement.oclAsType(DataInstance).dataType&#xA;                        else &#xA;                            if (self.dataElement.oclIsTypeOf(FormalParameter)) then&#xA;                                self.dataElement.oclAsType(FormalParameter).dataType&#xA;                            else &#xA;                                if (self.dataElement.oclIsTypeOf(Function)) then&#xA;                                    self.dataElement.oclAsType(Function).returnType&#xA;                                else&#xA;                                    null&#xA;                                endif&#xA;                            endif &#xA;                        endif&#xA;                    endif&#xA;                else &#xA;                    if (self.container().oclIsTypeOf(MemberAssignment)) then&#xA;                        self.container().oclAsType(MemberAssignment).member.dataType&#xA;                    else &#xA;                        if (self.container().oclIsTypeOf(ParameterBinding)) then&#xA;                        &#x9;self.container().oclAsType(ParameterBinding).resolveParameterType()&#xA;                        else&#xA;                            if (self.container().oclIsTypeOf(CollectionDataInstance)) then&#xA;                                self.container().oclAsType(CollectionDataInstance).dataType.oclAsType(CollectionDataType).itemType&#xA;                            else&#xA;                                if (self.container().oclIsTypeOf(DataElementUse)) then&#xA;                                    self.container().oclAsType(DataElementUse).resolveDataType().oclAsType(CollectionDataType).itemType&#xA;                                else&#xA;                                    if (self.container().oclIsTypeOf(DataInstanceUse)) then&#xA;                                        self.container().oclAsType(DataInstanceUse).resolveDataType().oclAsType(CollectionDataType).itemType&#xA;                                    else&#xA;                                        null&#xA;                                    endif&#xA;                                endif&#xA;                            endif&#xA;                        endif&#xA;                    endif&#xA;                endif&#xA;                "/>
       </eAnnotations>
     </eOperations>
     <eStructuralFeatures xsi:type="ecore:EAttribute" name="unassignedMember" eType="#//UnassignedMemberTreatment"/>
diff --git a/plugins/org.etsi.mts.tdl.model/model/tdl.genmodel b/plugins/org.etsi.mts.tdl.model/model/tdl.genmodel
index 0893cc65..b086084b 100644
--- a/plugins/org.etsi.mts.tdl.model/model/tdl.genmodel
+++ b/plugins/org.etsi.mts.tdl.model/model/tdl.genmodel
@@ -135,6 +135,8 @@
     <genClasses ecoreClass="tdl.ecore#//ParameterBinding">
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference tdl.ecore#//ParameterBinding/dataUse"/>
       <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference tdl.ecore#//ParameterBinding/parameter"/>
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference tdl.ecore#//ParameterBinding/reduction"/>
+      <genOperations ecoreOperation="tdl.ecore#//ParameterBinding/resolveParameterType"/>
     </genClasses>
     <genClasses ecoreClass="tdl.ecore#//Action">
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute tdl.ecore#//Action/body"/>
-- 
GitLab