Change in Helper/Mapping behaviour from QVTO 3.2.2 to 3.3.0 [message #1270193] |
Wed, 12 March 2014 16:47 |
Gunnar Teege Messages: 5 Registered: March 2014 |
Junior Member |
|
|
Hi,
I have been hit by a changed behaviour of mappings in chained in-place transformations from QVTO 3.2.2 to 3.3.0.
I implemented a complex in-place transformation on Ecore models as a sequential chain of simpler in-place transformations. Sometimes, a simple transformation adds model parts which will be removed again by later transformations in the chain. If implemented using nested mappings problems arise beginning with QVTO 3.3.0. However, am not sure whether this is due to my misunderstanding the concept of mappings in in-place transformations. Here is the detailed description of the problem (simplified as much as possible for demonstration purposes):
In a library "LibAnno" (see attached files) I implemented the function "removeAnno" removing EAnnotation details as a mapping and used that in another mapping "setAnno" for replacing EAnnotation details by first removing and then adding them. I have two in-place transformations "Test1Trans" and "Test2Trans" which simply replace at all classes for all EAnnotations with source "Anno" all details with key "initval" by a detail with the same key and value "test1" or "test2", resp. When I apply the transformations one at a time to a test model Examp.ecore with one Class, one EAnnotation and one existing detail with key "initval" all works fine. Now I have another transformation "Chain" which applies both transformations sequentially to the same in-memory model.
In QVTO 3.2.2 (Juno) this also works fine, the result is an EAnnotation with the single detail with value "test2". In QVTO 3.3.0 (in Kepler) and 3.4.0 (in Luna) the same transformation results in an EAnnotation with two details with values "test1" and "test2". It seems that the "test1" detail which has been added by the first transformation could not be removed by the second transformation.
When I replace the mapping "removeAnno" by a handler "hremoveAnno" with the same body it works fine also in 3.3.0 and 3.4.0.
My questions are:
- is this a desired behaviour which has been corrected from 3.2.2 to 3.3.0 or is it a bug?
- I found other cases where a similar problem occurs for nested mappings which add model objects. Again the problem disappears when using helpers instead. However, the QVT 1.1 specification says in 8.2.1.12: "However it is illegal to create or update object instances within a helper operation except for pre-defined types like sets, tuples, and for intermediate properties." I create EStringToStringMapEntry objects, so this should not work at all!?
- what are the exact differences between mappings and helpers and when should I use which one?
- In the specification I found the concept of intermediate data in QVTO, but that seems not to be supported in the implementation (at least not in 3.2.2). Are there other means to remove in a single transformation data which has been created in the same transformation?
Please help me to better understand the situation.
Gunnar
|
|
|
Re: Change in Helper/Mapping behaviour from QVTO 3.2.2 to 3.3.0 [message #1270705 is a reply to message #1270193] |
Thu, 13 March 2014 11:00 |
Sergey Boyko Messages: 171 Registered: July 2009 |
Senior Member |
|
|
Gunnar Teege wrote on Wed, 12 March 2014 12:47Hi,
I have been hit by a changed behaviour of mappings in chained in-place transformations from QVTO 3.2.2 to 3.3.0.
...
In QVTO 3.2.2 (Juno) this also works fine, the result is an EAnnotation with the single detail with value "test2". In QVTO 3.3.0 (in Kepler) and 3.4.0 (in Luna) the same transformation results in an EAnnotation with two details with values "test1" and "test2". It seems that the "test1" detail which has been added by the first transformation could not be removed by the second transformation.
When I replace the mapping "removeAnno" by a handler "hremoveAnno" with the same body it works fine also in 3.3.0 and 3.4.0.
My questions are:
- is this a desired behaviour which has been corrected from 3.2.2 to 3.3.0 or is it a bug?
- I found other cases where a similar problem occurs for nested mappings which add model objects. Again the problem disappears when using helpers instead. However, the QVT 1.1 specification says in 8.2.1.12: "However it is illegal to create or update object instances within a helper operation except for pre-defined types like sets, tuples, and for intermediate properties." I create EStringToStringMapEntry objects, so this should not work at all!?
- what are the exact differences between mappings and helpers and when should I use which one?
- In the specification I found the concept of intermediate data in QVTO, but that seems not to be supported in the implementation (at least not in 3.2.2). Are there other means to remove in a single transformation data which has been created in the same transformation?
Hi Gunnar,
The reason of the changing of behavior is that in QVTo 3.2.2 each of the transformation being instantiated uses individual trace pool. This was corrected for QVTo 3.3.0 with https://bugs.eclipse.org/bugs/show_bug.cgi?id=392153.
So the answer to the first question is 'yes'. It's desired behavior.
About mappings and helpers.
Execution semantics of mappings is described in QVTO specification (http://www.omg.org/spec/QVT/1.1/PDF/) section "8.2.1.15 MappingOperation" part "Execution Semantics". In short during invocation of mapping operation the trace pool is checked and mapping is not executed in case it's invoked on the same object with the same parameters. So in your case the invocation of 'removeAnno()' mapping which is initiated in Test2Trans was skipped.
Helpers are different in that they don't use traces. Also QVTo relaxes restriction on helpers so it's possible to create and update any objects by means of them.
I suggest either to redesign scripts or to replace mappings in LibAnno with helpers like follows:
helper ENamedElement :: setAnno(aname: String, k : String, v: String) {
self.removeAnno(aname, k);
self.eAnnotations->select(source = aname)->first().details += object EStringToStringMapEntry { key := k; value := v; };
return
}
helper ENamedElement :: removeAnno(aname: String, k : String) {
self.eAnnotations->select(source = aname)->forEach(a) {
a.details := a.details->select(key != k);
}
}
Btw, I didn't quite understand logic in 'removeAnno()'. To me it should looks like:
helper ENamedElement :: removeAnno(aname: String, k : String) {
self.eAnnotations->select(source = aname)->forEach(a) {
a.details := Set{}
}
}
Regards,
Sergey.
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.01832 seconds