Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 352958

Summary: org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv needs to override org.eclipse.ocl.ecore.EcoreEvaluationEnvironment.createTuple(EClassifier, Map<EStructuralFeature, Object>) for TupleTypes with Dictionaries or Lists
Product: [Modeling] QVTo Reporter: Nicolas Rouquette <nicolas.f.rouquette>
Component: EngineAssignee: Project Inbox <mmt-qvt.operational-inbox>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P3 CC: christopher.gerking, ed
Version: unspecified   
Target Milestone: 3.0   
Hardware: Macintosh   
OS: All   
Whiteboard:
Bug Depends on: 352964    
Bug Blocks:    
Attachments:
Description Flags
Proposed patch to OCL and QVTO (R3 maintenance)
none
Revised patch
none
mylyn/context/zip
none
3rd patch, the fix seems to work as intended.
none
mylyn/context/zip none

Description Nicolas Rouquette CLA 2011-07-24 16:16:53 EDT
Currently, the QVTO Editor supports defining a tuple type with dictionaries or lists; e.g.:

Tuple(a : Dict(String, String))

However, at runtime, it is currently not possible to create an instance of such tuple; i.e.:

var t : Tuple(a : Dict(String, String)) = Tuple{a=Dict{}}; // triggers IllegalArgumentException

The IllegalArgumentException comes from the inherited EcoreEvaluationEnvironment.createTuple() method from OCL which does not know about QVTO's collections -- Lists and Dictionaries.

The problem stems from org.eclipse.ocl.util.CollectionUtil.createNewCollection() which does not know how to handle QVTO's Dict or List types.
This operation is used in two places in OCL's EcoreEvaluationEnvironment: createTuple() (public) and coerceValue (private).

The fix would require making coerceValue in OCL protected so that we can override it in QVTO.
Comment 1 Nicolas Rouquette CLA 2011-07-24 18:57:54 EDT
Created attachment 200248 [details]
Proposed patch to OCL and QVTO (R3 maintenance)

This bug is quite problematic for us at JPL.
I have developed this proposed patch.
Is this something that can be incorporated into the maintenance builds for Helios?
Comment 2 Nicolas Rouquette CLA 2011-07-24 21:51:18 EDT
Created attachment 200249 [details]
Revised patch

This revised patch works in my environment.
That is, it is possible to do things like:

var t : Tuple(a=Dict(String,String), b=List(Sequence(String))) 
 = Tuple{a=Dict{}, b=List{}};

Can this patch be incorporated in the Helios maintenance builds?
Comment 3 Nicolas Rouquette CLA 2011-07-24 21:51:20 EDT
Created attachment 200250 [details]
mylyn/context/zip
Comment 4 Nicolas Rouquette CLA 2011-07-27 07:25:28 EDT
Well, I found that the proposed patch isn't enough!

With EcoreEvaluationEnvironemnt.coerceValue protected, we can override it in QvtOperationalEvaluationEnv; however the EcoreEvaluationEnvironment.coerceValue method uses a private UMLReflectionImpl.INSTANCE object to determine what kind of OCL collection corresponds to an EClassifier according to the multiplicity range, uniqueness and ordering meta-properties. 

To make matters worse, there are in fact two UMLReflection mechanisms:

1) qvt.oml.stdlib.QVTUMLReflection -- this is the mechanism that QvtEnvironmentBase.getUMLReflection() provides
2) ocl.ecore.internal.UMLReflectionImpl -- this is a hardcoded mechanism used privately in EcoreEvaluationEnvironment.getCollectionKind

Since this is QVTO.... it seems that the first one is what we should be using instead of OCL's legacy UMLReflection mechanism -- (it seems to me that the OCL UMLReflection mechanism should be in org.eclipse.ocl.uml, not org.eclipse.ocl.ecore)
But, there is a problem to access the QVTUMLReflection!

The QvtOperationalEvaluationEnv.coerceValue method does not have access to the QVTUMLReflection object because QvtOperationalEvaluationEnv extends OCL's EcoreEvaluationEnvironment, not QVTO's QvtEnvironmentBase where QVTOUMLReflection is publicly accessible via QvtEnvironmentBase.getUMLReflection()

That is, the QvtOperationalEvaluationEnv / EcoreEvaluationEnvironment is completely unaware of the existence of QvtEnvironmentBase / EcoreEnvironment.
The proposed strategy is to add an entry in the QvtOperationalEvaluationEnv's binding map to retrieve the QvtEnvironmentBase object from which it will be possible to retrieve the QVTUMLReflection object to determine 
what type to coerce a value to. The qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.execute(OperationalTransformation) method seems appropriate as the place to put this new binding.

- Nicolas.
Comment 5 Nicolas Rouquette CLA 2011-07-28 22:35:31 EDT
Created attachment 200577 [details]
3rd patch, the fix seems to work as intended.

The idea to save a reference to the QvtEnvironmentBase object
so that QVTO can do UML-style coersions and constructions is sound.
The problem is is the details where we have to setup this extra reference and not loose it.

The previous patch was saving this reference in the outermost place in the execution of a QVTO transformation; however, it turned out that eventually, the reference would be lost.

It turns out that there are indeed two ways in which the QvtOperationalEvaluationEnv object is created; the second is more subtle.

So far, here are the two places where the extra environment reference is set.

1) qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.execute(OperationalTransformation) 
2) qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.visitInstantiationExp(InstantiationExp)

This 3rd patch seems to be OK on a non-trivial QVTO test.
Comment 6 Nicolas Rouquette CLA 2011-07-28 22:35:37 EDT
Created attachment 200578 [details]
mylyn/context/zip
Comment 7 Christopher Gerking CLA 2014-03-23 07:26:18 EDT
Works for me.
Comment 8 Ed Willink CLA 2014-03-23 07:50:19 EDT
(In reply to Christopher Gerking from comment #7)
> Works for me.

What works?

No patch/the first patch/the second patch.

-----

The saving of mutable types nested within immutable types is unsound. In my QVT traceability paper (http://www.eclipse.org/mmt/qvt/docs/ICMT2014/QVTtraceability.pdf) I conclude that OCL needs a Map type which would then allow QVTo to change List/Dict into Sequence/Map when extending immutable types.
Comment 9 Christopher Gerking CLA 2014-03-23 08:15:22 EDT
Without any patch. The code snippet above does not produce an IllegalArgumentException.