Jump to: navigation, search

MMT/QVTo/New and Noteworthy/Luna

< MMT

Eclipse QVT Operational New and Noteworthy items for the Luna 3.4.0 release.

Milestone 1

The milestone was completed on Friday, August 23, 2013


Enhancements

410470 Now parser allows to apply a qualifier on the transformation declaration.
Snippet:

blackbox transformation bug410470;


392429 Now module's properties don’t require explicit initialization.
With the fix now it’s possible to declare module's properties like the following:

property prop : EObject;
main() {
assert fatal (prop = null);
}


400720 Now intermediate classes that are inherited from ordinary classes satisfy to oclIsKindOf() check.
With the fix now it’s possible to use .oclIsKindOf() call on the instance of intermediate class which is inherited from ordinary class:

intermediate class C extends EPackage{};
intermediate class D extends C, EClass{};
 
main() {
	var c : C = object D {};
	assert fatal (c.oclIsKindOf(EPackage));
	assert fatal (c.oclIsKindOf(EClass));
	assert fatal (c.oclIsTypeOf(D));
}


314443 Imperative collect expression 'object' shorthand is supported now.
Snippet:

mapping inout EClass::addAttributes() {
	eStructuralFeatures := Sequence { 1 .. 5 }->object(i) EAttribute {
			name := "attribute" + i.repr();
		};	
}


269744 Now AssertionFailed exception carries the assert log message.
In case the assertion failed exception is raised with a log message, using

  assert fatal (false) with log("A message")

the exception stack trace carries the message:

Terminating execution...
org.eclipse.m2m.internal.qvt.oml.evaluator.QvtAssertionFailed: Fatal assertion failed : A message
	at script::main(script.qvto:10)


404647 Now ImperativeOCL mutable collections (List and Dict) are supported for mapping context type.
Snippet:

mapping inout List(Real) :: m() : EClass {
	self->add(5.0);
	name := self->sum().toString();
}
 
mapping inout Dict(String,Real) :: m() : EClass {
	self->put("5", 5.0);
	name := self->sum().toString();
}


414407 Quick Outline is now supported (Ctrl + O) in QVT editor.
Quick outline.png


274105 Chaining of imperative iterator shortcuts is supported now.
Snippet:

main() {
	srcModel.objects()->xselect(EPackage).subobjects()[EClass][name != "Fam1"][name != "Pers1"]->sortedBy(name) -> map m09();
	srcModel.objects()[EPackage].subobjects()[EClass][name != "Fam1"][name != "Pers1"]->sortedBy(name) -> map m10();
	srcModel.objects()[EPackage].subobjects()[EClass]![name = "Fam1"]->sortedBy(name) -> map m11();
 
	srcModel.objects()->xselect(EPackage)->name[e | e != "aaa"] -> map m12();
	srcModel.objects()->xselect(EPackage)->name![e | e = "aaa"] -> map m13()->sortedBy(name);
	srcModel.objects()->xselect(EPackage)->collectselect(i; res= i.name | res != "aaa") -> map m14();
	srcModel.objects()->xselect(EPackage)->collectselectOne(i; res= i.name | res = "aaa") -> map m15()->sortedBy(name);


414363 Now warning is generated for using of '=' where ':=' is intended.
Snippet:

mapping EClass::foo2atombar () : atom:EClass, bar:EClass
{
	init {atom.name /*<warn>*/=/*</warn>*/ "2";}
 
	atom.name /*<warn>*/=/*</warn>*/ "2";
	object atom:EClass {name /*<warn>*/=/*</warn>*/ "1"};
	object bar: {name /*<warn>*/=/*</warn>*/ "2"};
	object EPackage {name /*<warn>*/=/*</warn>*/ "2"};
	Sequence{1,2}->object(x) EClass {name /*<warn>*/=/*</warn>*/ "nn";};
	Sequence{1,2}->xcollect(x | object EClass {name /*<warn>*/=/*</warn>*/ "nn";});
}


Bugs

411477 Now obtaining additional module attributes during the semantic analysis does not cause performance degradation. This mostly affects transformations which heavily use extension.


410511 Now debug/non-debug execution is fully consistent for the case when ULM models with applied stereotypes are processed.


294127 Now QVTo helper with the tuple return type allows ‘null’ assignment on their parts.
Snippet:

helper createTuple() : a : String, b : Integer {
	a := null; -- null value of a tuple part now does not cause runtime exception
	b := 10;
}
 
main() {
	var t:= createTuple();
}


272869 It’s disallowed for library to extend transformation. The following code now yields validation errors:

library  LibraryModule extends /*<error>*/TransformationModule/*</error>*/;


268636 Explicit instantiation of library module is not allowed by QVTo specification. The following code now yields validation errors:

intermediate class my_cl extends /*<error>*/LibraryModule/*</error>*/ {
}
intermediate property EClass::aa : /*<error>*/LibraryModule/*</error>*/;
main() {
	var my_var : /*<error>*/LibraryModule/*</error>*/;
	var x:List(/*<error>*/LibraryModule/*</error>*/);
 
	var v := LibraryModule::xxx();
}


413130 Validation of Tuple variable initialization was improved.


392155 Contextless operations are now not prefixed with the context type 'OclVoid' in Outline View.
New outline.png


413131 'null' value in initialization of Tuple type is now correctly handled. With the fix it is possible now to assign Tuple parts ‘null’ value:

main() {
	var t0: Tuple(name : String, size : Integer);
	t0 = Tuple { name = null, size = 10};
	var t1: Tuple(name : String, size : Integer) = Tuple { name = null, size = 10};
}


414555 Cloning of intermediate properties which are defined in the accessed transformations is supported now.


415322 QVTo launch configuration now allows to select parameterless transformations.


414472 Implicit initialization of variables of Tuple type is supported now.
Snippet:

main() {
	var t: Tuple(seq : Sequence(String), size : Integer, t : Tuple(name : String, size : Integer));
 
	assert fatal (t.seq != null);
	assert fatal (t.seq->isEmpty());
	assert fatal (t.size = 0);
	assert fatal (t.t.name = "");
	assert fatal (t.t.size = 0);
}

Milestone 2

The milestone was completed on Friday, October 04, 2013


Enhancements

416584 Multiple transformation/library declarations in a single file are supported now.
Snippet:

transformation T2(in inModel : Ecore, out outModel : Ecore) 
	extends T1
	extends T3
{
	main() {
		new T1(inModel, outModel).transform();
	}
}
 
transformation T1(in inModel : Ecore, out outModel : Ecore) 
	access T3
{
	configuration property prop : String;
	main() {
		new T3().transform();
	}
}
 
transformation T3() 
{
	configuration property prop2 : String;
	property prop3 = 123;
	main() {
	}
}


417751 An imperative "if-then-else" statement is supported now.
Snippet:

main() {
	// evaluation check
	var ii = 5;
	var count = 0;
 
	if (ii > 0)
		if (ii <= 5)
			count := count + 1
		elif (ii > 5)
			log("")
	;
	if (true)
		if (true)
			object EClass {}
		else
			object EClass {};
}


415029 It’s possible now to use Dictionary as the type for intermediate properties.
Snippet:

intermediate property EClass::test1 : Dict(Integer, Integer);
 
main() {
	var e = object EClass{};
	assert fatal(e.test1->size() = 0);
	e.xmap test();
	assert fatal(e.test1->get(1) = 1);
}
mapping inout EClass::test() {
	self.test1->put(1,1);
}


Bugs

401521 Now compiler yields error in case when iteration variable is already defined.
Snippet:

mapping List(Real) :: m(i:Integer) : EClass {
	var d = self->collect(/*<error>*/i/*</error>*/| i);
}


417996 Initialization of module properties now leverages logic used for initialization of properties of intermediate classes.
Snippet:

property p1 : Dict(Integer, Integer);
property p2 : List(Integer);
property p3 : Tuple(name : String, size : Integer);
property p4 : Sequence(Integer);
main() {
	assert fatal(p1->size() = 0);
	assert fatal(p2->size() = 0);
	assert fatal(p3.name = "");
	assert fatal(p4->size() = 0);
}


417779 Now QVTo correctly handles the case when ‘inout’ EMF model physically consists of several packages that are split between different files.


Milestone 3

The milestone was completed on Friday, November 15, 2013


Enhancements

419299 QVTo now supports exceptions (TryExp, CatchExp, RaiseExp, user exceptions definition are supported).
Snippet:

exception ExcA {}
exception ExcB {}
exception ExcExtAB extends ExcA, ExcB {}
main() {
	// 'AssertionFailed' exception
	try {
		assert fatal (false) with log("NPE");
	} 
	except (ex:AssertionFailed) {
		var exLog := ex.getArgument();
	};
	try {
		raise "NPE";
	} 
	except (ex:AssertionFailed) {
		var exLog := "assertion " + ex.getArgument();
	}
	except (ex:Exception) {
		var exLog := ex.getArgument();
	};
	try {
		try {
			raise ExcExtAB;
		}	
		except (ExcA){
		};
	}	
	except (ExcExtAB){
	};
}


301134 Now ‘xmap’ raises an exception if the ‘when’-clause doesn't hold. In other words when mapping is called in strict execution mode (by means of ‘xmap’ keyword) and precondition evaluates to 'false' these results in ‘AssertionFailed’ exception.
Snippet:

main() {
	try { 
		object EClass{}.xmap test();
	}
	except (ex:AssertionFailed) {
	};
}
mapping inout EClass::test()
	when {false}
{}


Bugs

414616 Now compiler validates and reports unknown identifiers in incorrect xcollect-like constructions.
Snippet:

    /*<error>*/Dict{"name"="dd"}-> foo_reject(i|EPackage)/*</error>*/;
    /*<error>*/srcModel.objects()[EPackage] -> foo_reject(i|EPackage)/*</error>*/;


415209 Now .deepClone() call on a List instance returns Sequence.
Snippet:

var c60 : Sequence(OclAny) := list.clone(); -- shorthand for collect
var c61 : Sequence(OclAny) := list->xcollect(clone());
var c62 : Sequence(OclAny) := list->clone(); -- shorhand for xcollect
var c63 : Sequence(EClass) := list->xselect(true);
var c64 : Sequence(EClass) := list[true]; -- shorthand for xselect
var c65 : EClass := list->selectOne(true);
var c66 : EClass := list![true]; -- shorthand for selectOne
var c67 : Sequence(OclAny) := list->collectselect(i;res=i.clone()|res.oclIsKindOf(EClass));
var c68 : Sequence(EClass) := list->clone()[EClass]; -- shorhand for collectselect
var c69 : OclAny := list->collectselectOne(i;res=i.clone()|res.oclIsKindOf(EClass));
var c70 : EClass := list->clone()![EClass]; -- shorhand for collectselectOne


415661 QVTo evaluator now correctly handles ‘invalid’ bounds of a collection range.
Snippet:

var bound : Integer = invalid;
var range : Set(Integer) = Set{1 .. bound};
assert fatal (range->size().oclIsInvalid());

415310 Now adding of ‘invalid’ to a Collection produces ‘invalid’ result in turn (according to OCL specification).


Snippet:

var seq : Sequence(EClass) = object Sequence(EClass) {};
seq := seq->including(invalid);
assert fatal (seq->size().oclIsInvalid());


323915 Now uncaught runtime exceptions within a java black-box operation yields QVTo exception.


414619 Now comparison of values of non-conforming types produces an error.
Snippet:

main() {
	var b:Boolean;
 
	b := /*<error>*/(helper_Int() != helper_String())/*</error>*/;
	b := /*<error>*/(helper_Int() <> helper_String())/*</error>*/;
	b := /*<error>*/(helper_Int() = helper_String())/*</error>*/;
	b := /*<error>*/Tuple { name = 1, size = 10} = Tuple { name = 'bob', size = 10}/*</error>*/;
 
	if /*<error>*/(object EClass{} != "foo")/*</error>*/ then
	{}
}
helper helper_String() : String {
	return "1";
}
helper helper_Int() : Integer {
	return 1;
}


224094 Now an instance of OclVoid (null) is correctly handled by collections of List type.
Snippet:

var c1 := Sequence {null, null};
assert fatal (c1->size() = 2);
assert fatal (c1->includes(null));
 
var c6 : List(OclAny) := List {null, null};
assert fatal (c6->size() = 2);
assert fatal (c6->includes(null));


Milestone 4

The milestone was completed on Friday, December 20, 2013


Enhancements

267917 Now QVTo handles configuration property for all of collection types (List, Dict, Set, OrderedSet, Bag, Sequence).
Snippet:

 
configuration property optionsDict1 : Dict(String, String);  // b=b1, c=c1, a=a1
configuration property optionsSet    : Set(Real);          // 1.0, 1.1, 1.2
configuration property optionsList    : List(String);       // foo, bar
configuration property nestedDict1  : Dict(String, Sequence(String)); // [a\\a=[a, b], a\,a=[b, c], a\[\[a=[b, c]]


420970 Now QVTo supports additional meta model conditions. Section 8.1.2 'Model Types' of the QVT specification defines additional meta model conditions, i.e. restrictions on the set of valid input models using the 'where' keyword. In case when ‘where’ condition evaluates to ‘false’ QVTo throws ‘AssertionFailed’ exception.
Snippet:

modeltype ECORE1 uses "http://www.eclipse.org/emf/2002/Ecore"
	where {self.objectsOfType(EPackage)->size()>=1; self.objectsOfType(EClass)->size()>=0};


Bugs

390088 Now ResolveIn operations are correctly performed for contextless mappings which are imported from another module.


403440 Now resolveoneIn(...) invocations correctly handle override mappings in extending module.


415024 Now compiler validates and forbids re-assignment of Tuple value (maintaining the read-only behavior of Tuple instance).
Snippet:

test := Tuple {a = 1, b = 2};
/*<error>*/test.b/*</error>*/ := 3;


413391 Validation of property initialization expressions was enhanced.
Snippet:

property pa = /*<error>*/Tuple(a:String)/*</error>*/;
property pb = /*<error>*/Integer/*</error>*/;
property pd = /*<error>*/EClass/*</error>*/;
main() {
	var a = /*<error>*/Tuple(a:String)/*</error>*/;
	var b = /*<error>*/Integer/*</error>*/;
	var d = /*<error>*/EClass/*</error>*/;
}


Milestone 5

The milestone was completed on Friday, January 31, 2014


Enhancements

392156 Now compiler does not require source for invocation of resolve..(). This is explicitly mentioned in QVT specification v1.2 – “The source object is optional. When no source object is provided, this expression inspects all the targets created or updated by all mapping operations irrespective of the source objects.”
Snippet:

main() {
	var o := object EPackage{}.map toClass();
 
	var x1 : Sequence(EObject) = resolve(EObject);
	var x2 : EObject = resolveone(EObject);
	var x3 : Sequence(EObject) = invresolve(EObject);
	var x4 : EObject = invresolveone(EObject);
}


424086 Now 'when' clause of MappingOperation is defined by means of <expression_block>. Thus multiple expressions are allowed inside it.
Snippet:

mapping EClass::toEClass1() : EClass
when {
	not self._abstract;
	not self.interface;
	self.oclIsTypeOf(ecore::EClass);
	self.resolve(ecore::EClass)->any(true).oclIsUndefined();
	self.eAttributes->isEmpty()	
}
{}


424740 QVTo now supports BlockExp.

BNF:

  <block_exp> ::= (<object_exp> | <do_exp> | <switch_exp>)
  <do_exp> ::= 'do' <expression_block>

Notation:
The notation uses the do keyword followed by braces to delimit the list of expressions. However, when used within the following control expressions: if, switch, compute, and for expressions the do keyword can be skipped.

  do {} // executes the body and returns null
  if name.startswith("_") then {} else null endif // do keyword being skipped


Snippet:

main() {
	do {
		var i := 1;
		assert fatal (i = 1)
	};
	do {
		var i := 2;
		assert fatal (i = 2)
	};
}


418961 Now QVTo compiler supports implicit coercion of Sequence type to List type and vice versa.
Snippet:

  var l1 : List(EClass);
  var s1 : Sequence(EClass);
 
  l1 := s1;  -- shortcut to 's1 := l1->asSequence()'
  s1 := l1;  -- shortcut to 'l1 := s1->asList()'

Since we always obtain a new instance of corresponding collection then we won't face the situation that "allows the left-hand to change what the right-hand thinks is unchanging".
Snippet:

main() {
	var list : List(EClass) := Sequence {object EClass{}};
	var coll : Sequence(EClass) := List {object EClass{}};
	list := coll;
	coll := list;
	list->testSequenceContext()->add(object EClass{});
}
helper Sequence(EClass)::testSequenceContext() : List(EClass) {
	return self
}


289982 QVTo now supports the concrete syntax definition of blackbox libraries.

Blackbox library concrete syntax definition is supported, so the user can define a library with plain operation signature declarations. It is resolvable in workspace at development time thus allowing all importers to compiler properly. The implementation Java class is resolved at runtime, when it can be executed.

Implementation details:

  • It is not possible to match a QVTo constructor to a Java constructor, because the constructed object is already passed as parameter. However, it is now possible to match a QVTo constructor to a contextual Java method.
  • Currently trace records are stored after the execution of a blackbox mapping, such that resolving is possible.
  • The usage of blackbox mappings as both inherited and merged mappings is prohibited. This is because a blackbox mapping requires the result to be still uninitialized when executing.
  • Any inherited mappings from blackbox mappings is also prohibited. This is because a blackbox mapping is executed as a whole, and thus does not support the insertion of inherited mappings between init and population. Merged mappings for blackbox mappings are supported, though.
  • Since a disjunctive mappings can be optionally set as blackbox (depending on whether a body is specified), a combination of blackbox and disjuncts can not be prohibited. However, in this case, the disjunctive selection will be performed as usual (no delegation to a Java method).


Snippet:

// QVTo library source
blackbox helper echoFromSimpleJavaLibrary(s : String) : String;


// plugin.xml
<extension point="org.eclipse.m2m.qvt.oml.javaBlackboxUnits">
   <library class="org.eclipse.m2m.tests.qvt.oml.bbox.SimpleJavaLibrary" />
</extension>


// Java source 
public class SimpleJavaLibrary {
	public String echoFromSimpleJavaLibrary(String str) {
		return str;
	}
}


Bugs

424359 Now QVTo plug-in ‘org.eclipse.m2m.qvt.oml.editor.ui’ has no dependencies on JDT.


422267 Issue with 'already exists' warning that appeared for any output model in QVTo launch configuration was fixed.


422315 Now ImperativeIterateExp always produces an instance of Sequence type.
Snippet:

var _coll := List{object EClass{name:='n'}};
 
var collect_s     : Sequence(EClass) := _coll.clone().oclAsType(EClass); -- shorthand for collect
var xcollectt     : Sequence(EClass) := _coll->xcollect(clone().oclAsType(EClass));
var xcollectt_s   : Sequence(EClass) := _coll->clone().oclAsType(EClass); -- shorhand for xcollect
var xselectt      : Sequence(EClass) := _coll->xselect(true);
var xselectt_s    : Sequence(EClass) := _coll[true]; -- shorthand for xselect
var collsell      : Sequence(EClass) := _coll->collectselect(i;res=i.clone().oclAsType(EClass)|true);
var collsell_s    : Sequence(EClass) := _coll->clone()[EClass]; -- shorhand for collectselect


424912 Validation of disjunctive mappings which have operation body was enhanced.
Snippet:

mapping mm1() : EPackage disjuncts m2,m3;
 
mapping mm2() : EPackage disjuncts m2,m3
{}
 
mapping mm3() : EPackage disjuncts m2,m3
{  // comments
}
 
mapping mm4() : EPackage disjuncts m2,m3
/*<warn>*/{
init{}
}/*</warn>*/
 
mapping mm6() : EPackage disjuncts m2,m3
/*<warn>*/{
	object result : {}
}/*</warn>*/


Milestone 6

The milestone was completed on Friday, March 14, 2014


Enhancements

424584 QVTo now supports 'out' parameters (according to MappingParameter definition the list of possible values of direction kind are: 'in', 'inout' and 'out'). Due to the semantics of 'out' parameters, the following restrictions are in place:

  • argument for 'out' parameter must be l-values;
  • 'out' parameter cannot be assigned to outside 'init' section;
  • value of 'out' parameter are ignored when trying to resolve a mapping from trace;
  • argument must be of exactly the same types as types of respective 'out' parameters.


Snippet:

main() {
	// --------- out: null, abstract
	var contTest1 = new EClass();
	var outTest1 :EClassifier = null;
	var resTest1 = contTest1.map m1(outTest1, "1: ");
	assert fatal (contTest1.name = "1: self_name");
	assert fatal (outTest1.name  = "1: out_name");
	assert fatal (resTest1.name  = "1: result_name");
 
	// --------- out: non-null
	var outTest2 :EClass = new EClass();
	var resTest2 = contTest1.map m2(outTest2, "2: ");
	assert fatal (contTest1.name = "2: self_name / 1: self_name");
	assert fatal (outTest2.name  = "2: out_name / 1: self_name");
	assert fatal (resTest2.name  = "2: result_name");
}
mapping inout EClass :: m1(out outParam : EClassifier, in prefix:String) : EClass {
	init {
		outParam := new EClass();
	}
	self.name := prefix + "self_name";
	outParam.name := prefix + "out_name";
	name := prefix + 'result_name';
}
mapping inout EClass :: m2(out outParam : EClass, in prefix:String) : EClass {
	init {
		outParam := new EClass();
	}
	outParam.name := prefix + "out_name / " + self.name;
	self.name := prefix + "self_name / " + self.name;
	name := prefix + 'result_name';
}


428551 Now QVTo supports XCore models natively. Complete list of recognized model file extensions: ".ecore", ".xcore", ".emof", ".oclinecore".


Bugs

400233 QVTo Java black-box libraries now correctly resolve of modeled parameterized types (EMF parameterized classifiers).
Snippet:

// model.ecore
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="generics" nsURI="http://www.eclipse.org/m2m/qvt/oml/generics"
    nsPrefix="generics">
  <eClassifiers xsi:type="ecore:EClass" name="GenericCls">
    <eTypeParameters name="E">
      <eBounds eClassifier="#//MyNumber"/>
    </eTypeParameters>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="values" upperBound="-1">
      <eGenericType eTypeParameter="#//GenericCls/E"/>
    </eStructuralFeatures>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EDataType" name="MyNumber" instanceClassName="java.lang.Number"/>
</ecore:EPackage>


// Java with EMG generics
public class AnnotatedJavaLibrary {
	@Operation (kind=Kind.QUERY)
	public GenericCls<?> getGenericClsWildcard() {
		GenericCls<Integer> genericCls = GenericsFactory.eINSTANCE.<Integer>createGenericCls();
		genericCls.getValues().add(1);
		return genericCls;
	}
 
	@Operation (kind=Kind.QUERY)
	public GenericCls<Integer> getGenericClsInteger() {
		GenericCls<Integer> genericCls = GenericsFactory.eINSTANCE.<Integer>createGenericCls();
		genericCls.getValues().add(1);
		return genericCls;
	}
}


// QVTo library
blackbox query getGenericClsWildcard() : GenericCls;
blackbox query getGenericClsInteger() : GenericCls;


386115 Now for dynamically getting a value by invoking eGet on a multi value reference, the result of OclAny type can be cast to collection type.
Snippet:

// XMI instance
<?xml version="1.0" encoding="ASCII"?>
<model:Container xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:model="http://www.example.org/model" xsi:schemaLocation="http://www.example.org/model model.ecore">
  <contains label="1" single="//@contains.1" multi="//@contains.1 //@contains.2"/>
  <contains label="2"/>
  <contains label="3"/>
</model:Container>


// QVTo transformation
main() {
	var feature := EReference.allInstances()->any(name = 'contains');
	var root := input.rootObjects()![Container];
 
	var dynCall := root.oclAsType(EObject).eGet(feature).oclAsType(Collection(OclAny));
	assert fatal (dynCall->size() = 3);
}


427348 Now QVTo properly makes a copy of mutable collections (List and Dict) when storing trace record. Thus instances of List and Dict types passed as the mapping arguments are always treated as a DataType values.


428309 Now QVTo correctly handles cases when the stereotyped classifier is moved between different extents.


428316 Now Element::deepClone() call correctly copies multi-valued intermediate properties.
Snippet:

intermediate property qvto::expressions::ImperativeOperation::ctxMap2 : Dict(List(qvto::expressions::VarParameter), qvto::expressions::VarParameter);
intermediate property qvto::expressions::ImperativeOperation::ctxTuple : Tuple(obj : qvto::expressions::VarParameter, val : List(qvto::expressions::VarParameter));
main()
{
	var operation := object qvto::expressions::ImperativeOperation { name:= 'testOperation' };
	operation.context := object qvto::expressions::VarParameter { name := 'testContext'; ctxOwner := operation };
	operation.ctx := operation.context;
	operation.ctxSequence += operation.context;
	operation.ctxMap->put(operation.context.name, operation.context);
 
	var l := List{operation.context};
	operation.ctxMap2->put(l, operation.context);
	operation.ctxTuple := Tuple{obj = operation.context, val = l};
 
 
	var operationCopy := operation.deepclone().oclAsType(qvto::expressions::ImperativeOperation);
 
	var keyCopy = operationCopy.ctxMap2->keys()->flatten()->first(); 
	assert fatal (keyCopy = operationCopy.context);
	assert fatal (operationCopy.ctxMap2->get(List{keyCopy}) = operationCopy.context);
	assert fatal (operationCopy.ctxTuple.obj = operationCopy.context);
	assert fatal (operationCopy.ctxTuple.val = operationCopy.ctxMap2->keys()->asSequence()->first());
}


428618 Now QVTo correctly handles initialization of variables of Collection type with the concrete collection instances.
Snippet:

var c : Collection(String);
assert fatal (c = null);
 
c := Sequence{"a"};
c += "b";
assert fatal (c = Sequence{"a", "b"});
assert fatal (c <> Set{"a", "b"});
 
c := Set{"a"};
c += "b";
assert fatal (c = Set{"a", "b"});
assert fatal (c <> Sequence{"a", "b"});


428325 Performance of QVTo evaluation was improved for MappingOperations with parameters. Now trace records are cached not only for the MappingOperation context but also for their parameters.


428610 QVTo now provides a cache for transformations presented in Launch configuration. In case of large-scale transformations, this increases the responsiveness of the "Run Configurations" dialog drastically.


424896 Visibility of constructor's declarations was corrected. Thus now constructors are available for the initialization of transformation's properties.
Snippet:

constructor EClass::EClass(newName:String)
{
	name := newName;
}
 
property outProp1 :EClass = new EClass("a");
property outProp2 :EClass = new EClass(123);
 
constructor EClass::EClass(intVal:Integer)
{
	name := "noname";
}


429449 Functionality of UI action “Run->Transformation...” was restored.


Milestone 7

The milestone was completed on Friday, May 09, 2014


Enhancements

427237 Now QVTo supports concrete syntax of blackbox modules. For operational transformations, the blackbox flag "indicates that the whole transformation is opaque: no entry operation and no mapping operations are defined." Thus such transformation has only a signature and does not declare any operations at all. And such transformation basically enables import via "access" from another transformation.
Snippet:

// Java source
	@Operation(contextual = false, kind = Kind.TRANSFORMATION)
	public void blackboxTransformation(JavaModelInstance in, JavaModelInstance out, Integer prop) {
		EPackage rootPackage = EcoreFactory.eINSTANCE.createEPackage();
		out.getExtent().addObject(rootPackage);
	}
 
// QVTo source
blackbox transformation blackboxTransformation (in e : Ecore, out o : Ecore);
configuration property prop : Integer;


425069 Now QVTo handles operations defined for OclVoid type.
Snippet:

main() {
 
	var c : EClass = null;
	var res1 = c.map m();
	assert fatal (res1.name = oclVoidID);
 
	var res2 = null.map m();
	assert fatal (res1 = res2);
}
 
mapping EClass :: m() : EClass {
	name := eClassID;
}
mapping OclVoid :: m() : EClass {
	name := oclVoidID;	
}
mapping OclAny :: m() : EClass {
	name := oclAnyID;	
}


391289 Now QVTo builder can be cancelled. Thus any QVTo build can be interrupted at any point (via UI or via progress monitor passed to TransformationExecutor API).


431082 Interface of org.eclipse.m2m.qvt.oml.ExecutionContext class was extended to support IProgressMonitor as a progress monitor. So that execution of QVTo script which is performed by means of TransformationExecutor API can be controlled in a fine grained manner.


397398 Now QVTo supports "where" clause for the mapping declaration.
Snippet:

main() {
 
	var msg := "";
	try {
		map m1();
	}
	except (e:AssertionFailed) {
		msg := e.getArgument();
	};
	assert fatal (msg = "Postcondition failed in mapping 'm1'");
}
 
mapping m1() : EClass
when { true }
where { false }
{}


430164 QVTo maintains compatibility with Eclipse Juno by using Java reflection to invoke Eclipse Kepler specific API.


370098 Maximum depth of QVTo evaluation stack now is controlled by means of org.eclipse.m2m.qvt.oml.util.ISessionData class. Default value is equal to 1000.
Snippet:

org.eclipse.m2m.qvt.oml.ExecutionContext ctx = new ExecutionContextImpl();
ctx.getSessionData().setValue(QVTEvaluationOptions.EVALUATION_MAX_STACK_DEPTH, 100);


Bugs

430030 PSFs for QVTo project were provided. They are published at eclipse.org: http://projects.eclipse.org/projects/modeling.mmt.qvt-oml/developer


425634 Validation of target variable type inside ResolveInExp was enhanced.
Snippet:

main() {
	var p0 = resolveoneIn(m1, EClass);
	var p2 = resolveoneIn(m1, EClassifier);
	var p4 = resolveoneIn(m1, /*<warn>*/EPackage/*</warn>*/);
 
	var p8 = resolveoneIn(m2, /*<warn>*/EPackage/*</warn>*/);
}
 
abstract mapping m1() : EClassifier {}
abstract mapping m2() : EClass {}


432786 Type inference rules for resolveIn() operations were enhanced.
Snippet:

main() {
	var p1 : EClassifier = resolveoneIn(m1);
}
 
mapping m1() : EClassifier {
	init { result := object EClass{} }
}


319078 Now QVTo correctly handles creation of transformation project outside Eclipse workspace.


433585 Now QVTo does not require ‘return’ expression for the helper/query without a return type (similar to a Java void method).
Snippet:

query q1() {
	var v := 1;
}


433919 Lookup of additional attributes was optimized in QVTo evaluator. This gives substantial increase in performance when looking up attributes in case of deep extension hierarchies.


433985 Unnecessary recursion was removed when collecting additional attributes. This gives substantial increase in performance for transformations with large number of EClassifier and module hierarchies.


433292 QVTo now correctly performs resolve..() calls on ‘null’ source.
Snippet:

main() {
 
	var c0 : EClass = object EClass {};
	var c1 : EClass = c0.map EClass2EClass(); -- mapping executed, trace recorded for 'c0'
 
	var c2 : EClass = null;
	var c3 : EClass = c2.map EClass2EClass(); -- mapping not executed, no trace recordered for 'c2'
 
	var c4 : EClass = c2.resolveone(EClass);
 
	assert fatal (c4 <> c1);
	assert fatal (c4 = null);
}
 
mapping EClass :: EClass2EClass() : EClass {}


315153 Now instances of Dict type are correctly saved in QVTo trace.


Milestone RC1

The milestone was completed on Friday, May 23, 2014


Enhancements

432969 QVTo offers API for contributing 3rd-party visitor decorators.
Snippet:

ExecutionContextImpl context = new ExecutionContextImpl();
context.getSessionData().setValue(QVTEvaluationOptions.VISITOR_DECORATORS, myDecoratorsList);
TransformationExecutor executor = new TransformationExecutor(transformationURI);
ExecutionDiagnostic result = executor.execute(context);


326871 QVTo provides a way to add blackbox java libraries in standalone environment.
Snippet:

// Java source
@Module(packageURIs={"http://www.eclipse.org/emf/2002/Ecore"})
public class StandaloneBBoxModule {
	public String echoFromBBoxModule(String str) {
		return str;
	}
}
-- Main.qvto
import org.eclipse.m2m.tests.qvt.oml.bbox.StandaloneBBoxModule; 
 
main() {
	assert fatal (echoFromBBoxModule('test') = 'test');
}

Bugs