QVT expressivity [message #1064432] |
Wed, 19 June 2013 05:00  |
Eclipse User |
|
|
|
Hi,
I wanted to ask some questions about the expressivity of QVT that seems to me to be a little bit limited compared to other M2M languages (I may be wrong):
1- In defining a domain, in QVT, it seems we can only select one object of one type (c: UML::Class) we cannot for example select all tuples (c1:UMLClass, c2:UMLClass) as a single domain. Of course we can declare two distinct domains for each element, but if we could make a first filtering on the (c1, c2) couples, we could reduce the number of candidate tuples for the rule. If we could write something like:
checkonly domain
source c1:UML::Class,
source c2:UML::Class:
{
...
when{
-- domain-level pre-condition
c1<>c2;
}
};
....
when{
-- relation-level pre-condition
}
2- All the examples from the QVT spec and from the MediniQVT tutorials use meta-models that are designed following a special pattern:
"the contained elements (for example classes) have a reference (myPackage) to the container (package)."
No example is given with a container that has a collection of references (non eOpposite) to its contained elements. How this is delt with in QVT?
Thanks
|
|
|
Re: QVT expressivity [message #1064437 is a reply to message #1064432] |
Wed, 19 June 2013 05:16   |
Eclipse User |
|
|
|
Hi Skander
IMHO you have hit on an area where the QVTr (and QVTc and QVTo)
specifications are at best vague. I think that an additional 'rooting'
condition needs to be available for specification by the invoking
context, and a much clearer semantics of collection matching is required.
I would tentatively expect that if you apply a transformation defined on
C=>D to a Collection(C) that the result will be a Collection(D).
In UMLX where I tried to support collection matching, you would specify
Collection(C)[2] as the input type so that the transformation would be
applied to all distinct permutations of two Cs.
I currently have student working on realizing a QVTr to qVTc to QVTu to
QVTm to QVTi to OCL to Java chain. I expect that the precision of
Collection matching is something that we get to in about a year's time.
Regards
Ed Willink
On 19/06/2013 11:00, Skander Turki wrote:
> Hi,
> I wanted to ask some questions about the expressivity of QVT that
> seems to me to be a little bit limited compared to other M2M languages
> (I may be wrong):
> 1- In defining a domain, in QVT, it seems we can only select one
> object of one type (c: UML::Class) we cannot for example select all
> tuples (c1:UMLClass, c2:UMLClass) as a single domain. Of course we can
> declare two distinct domains for each element, but if we could make a
> first filtering on the (c1, c2) couples, we could reduce the number of
> candidate tuples for the rule. If we could write something like:
>
> checkonly domain source c1:UML::Class,
> source c2:UML::Class:
> {
> ...
> when{
> -- domain-level pre-condition
> c1<>c2;
> }
> };
> ....
> when{ -- relation-level pre-condition
> }
>
> 2- All the examples from the QVT spec and from the MediniQVT tutorials
> use meta-models that are designed following a special pattern:
> "the contained elements (for example classes) have a reference
> (myPackage) to the container (package)."
> No example is given with a container that has a collection of
> references (non eOpposite) to its contained elements. How this is delt
> with in QVT?
>
>
> Thanks
>
|
|
|
|
|
|
|
|
|
|
Re: QVT expressivity [message #1782570 is a reply to message #1782566] |
Mon, 26 February 2018 10:05   |
Eclipse User |
|
|
|
Hi
QVT extends OCL so all opposites are always defined albeit implicitly. See http://www.eclipse.org/modeling/mdt/ocl/docs/publications/OCL2016Opposites/Opposites.pdf
In any QVTr you should be able to reference the opposite of parent.children as aChild.Parent.
In Eclipse QVTd the qualified navigation syntax is also supported so, IIRC, you can also do aChild.children[Parent]
----
You seem to be trying to use ATL syntax.
For simple unidirectional transformations, ATL is perhaps 25% more compact than QVTr lexically since it doesn't have the multi-directional when/where overhead. Instead it has the generally implicit resolveTemp to magically convert. resolveTemp, a horrible name, is great when it works, but confusing when it doesn't and then hard to use. For simple transformations ATL and QVTr are rather similar except that QVTr requires that all resolveTemp's are explicit when/where clauses.
ATL cannot handle arbitrarily complex transformations that require multiple passesdeclarativelt, e.g. pass1 constructTree, pass2 resolveReferences. A manual exposition as two passes and a non-declarative step to sequence the passes. QVTr can since it defines the final truth; how to get there is just an implementation problem, which for Eclipse QVTd involves local and global dependency analyses and partitioning relations into micro-mappings to synthesize the multiple passes automatically. This is demonstrated by the ATL2QVTr transformation that is work in progress.
----
Your earlier problem is soluble today by the declarative poke (syntax unchecked):
relation child2child {
domain left leftChild : Child { parent = leftParent; };
domain right rightChild : Child { parent = rightParent; };
when { parent2parent(leftParent, rightParent); }
}
After thinking about it, the imperative pull could be supported by:
relation parent2parent {
domain left leftParent: Parent{ children = leftChildren; };
domain right rightParent: Parent{ children = rightChildren; };
where { child2child(leftChildren, rightChildren); } -- this is not valid for QVT 1.3
}
It just requires the declared relation child2child(L,R) to be automatically available for an element-wise iteration of child2child(Collection(L),Collection(R)).
If you scan RelToCore in the QVT spec, you will find a couple of relations that iterate over child2child(L,R) within a children2children(Collection(L),Collection(R)). Clearly this could be a first class language capability. But it needs some careful thought to avoid unpleasant ambiguities when user collections are needed.
NB "where" is a dreadful keyword. It should be "then".
Regards
Ed Willink
|
|
|
Re: QVT expressivity [message #1782586 is a reply to message #1782570] |
Mon, 26 February 2018 12:24   |
Eclipse User |
|
|
|
RelToCore contains a lot of interesting examples. Especially ++ operator. I need time to examine it.
I'm trying to implement a minimal working example. Here is a test model:
<?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="model1">
<eClassifiers xsi:type="ecore:EClass" name="cls1">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="attr11"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="attr12"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="cls2">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="attr21"/>
</eClassifiers>
</ecore:EPackage>
Here is my first attempt:
import ECORE : 'http://www.eclipse.org/emf/2002/Ecore';
transformation Test(left:ECORE, right:ECORE)
{
top relation ClassToClass {
checkonly domain left lclass : EClass {
name = className : String{}
};
enforce domain right rclass : EClass {
name = className+'Copy'
};
}
top relation AttributeToAttribute {
lparent : ECORE::EClass;
rparent : ECORE::EClass;
checkonly domain left lattr : EAttribute {
-- eContainingClass is not changeable
-- eContainingClass = lparent,
eAttributes[EClass] = lparent,
name = attrName : String{}
};
enforce domain right rattr : EAttribute {
-- eContainingClass = rparent,
eAttributes[EClass] = rparent,
name = attrName+'Copy'
};
when {
ClassToClass(lparent, rparent);
}
}
}
EAttribute's eContainingClass is unsettable. So I try to refer to an owning class using eAttributes[EClass], and I get a syntax error. It seems that square brackes are not supported.
When I refer to an owning class using EClass I get the following error:
Ambiguous resolution:
Property : ecore::EStructuralFeature::EClass # ecore::EClass::eAllStructuralFeatures
Property : ecore::EAttribute::EClass # ecore::EClass::eAttributes
Property : ecore::EAttribute::EClass # ecore::EClass::eAllAttributes
Property : ecore::EAttribute::EClass # ecore::EClass::eIDAttribute
Here is my second attempt:
import ECORE : 'http://www.eclipse.org/emf/2002/Ecore';
transformation Test(left:ECORE, right:ECORE)
{
top relation ClassToClass {
attrList : OrderedSet(ECORE::EAttribute);
attrList2 : OrderedSet(ECORE::EAttribute);
checkonly domain left lclass : EClass {
name = className : String{},
eStructuralFeatures = attrList
};
enforce domain right rclass : EClass {
name = className+'Copy',
eStructuralFeatures = attrList2
};
where {
AttributeToAttribute(attrList, attrList2);
}
}
relation AttributeToAttribute {
checkonly domain left lattr : EAttribute {
name = attrName : String{}
};
enforce domain right rattr : EAttribute {
name = attrName+'Copy'
};
}
}
But it raise the following exception:
java.lang.UnsupportedOperationException
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.AbstractScheduleManager.addRegionError(AbstractScheduleManager.java:136)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.MappingAnalysis.getReferenceNode(MappingAnalysis.java:655)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.ExpressionAnalyzer.visitVariableExp(ExpressionAnalyzer.java:1020)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.ExpressionAnalyzer.visitVariableExp(ExpressionAnalyzer.java:1)
at org.eclipse.ocl.pivot.internal.VariableExpImpl.accept(VariableExpImpl.java:440)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.ExpressionAnalyzer.analyze(ExpressionAnalyzer.java:115)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.MappingAnalysis$QVTcoreExpressionAnalyzer.visitNavigationAssignment(MappingAnalysis.java:164)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.MappingAnalysis$QVTcoreExpressionAnalyzer.visitPropertyAssignment(MappingAnalysis.java:189)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.MappingAnalysis$AbstractQVTcoreExpressionAnalyzer.visitPropertyAssignment(MappingAnalysis.java:1)
at org.eclipse.qvtd.pivot.qvtcore.impl.PropertyAssignmentImpl.accept(PropertyAssignmentImpl.java:599)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.MappingAnalysis.analyzeAssignmentValues(MappingAnalysis.java:320)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.MappingAnalysis.analyze(MappingAnalysis.java:302)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.TransformationAnalysis.analyze(TransformationAnalysis.java:71)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.AbstractScheduleManager.analyzeTransformation(AbstractScheduleManager.java:212)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.QVTcoreScheduleManager.analyzeTransformation(QVTcoreScheduleManager.java:37)
at org.eclipse.qvtd.compiler.internal.qvtm2qvts.AbstractScheduleManager.analyzeTransformations(AbstractScheduleManager.java:219)
at org.eclipse.qvtd.compiler.AbstractCompilerChain$QVTm2QVTsCompilerStep.execute(AbstractCompilerChain.java:232)
at org.eclipse.qvtd.compiler.AbstractCompilerChain.qvtm2qvti(AbstractCompilerChain.java:568)
at org.eclipse.qvtd.compiler.QVTrCompilerChain.compileQVTrAS(QVTrCompilerChain.java:214)
at org.eclipse.qvtd.compiler.QVTrCompilerChain.compile(QVTrCompilerChain.java:204)
at org.eclipse.qvtd.debug.launching.QVTrLaunchConfigurationDelegate.buildForLaunch(QVTrLaunchConfigurationDelegate.java:78)
at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:917)
at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:801)
at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:1039)
at org.eclipse.debug.internal.ui.DebugUIPlugin$8.run(DebugUIPlugin.java:1256)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:60)
I'm using QVTd 0.15.0.v20180131-0705
|
|
|
|
Re: QVT expressivity [message #1782630 is a reply to message #1782624] |
Tue, 27 February 2018 04:48  |
Eclipse User |
|
|
|
Hi
I can't use eContainingClass, because it's marked changeable="false" in Ecore metamodel. So I get the following exception:
java.lang.IllegalArgumentException: The feature 'eContainingClass' is not a valid changeable feature
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eOpenSet(BasicEObjectImpl.java:1141)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDynamicSet(BasicEObjectImpl.java:1119)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDynamicSet(BasicEObjectImpl.java:1112)
at org.eclipse.emf.ecore.impl.EAttributeImpl.eSet(EAttributeImpl.java:327)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:1071)
at org.eclipse.ocl.pivot.internal.PropertyImpl.initValue(PropertyImpl.java:1681)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.BasicQVTiExecutor.internalExecuteSetStatement(BasicQVTiExecutor.java:413)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiIncrementalExecutor.internalExecuteSetStatement(QVTiIncrementalExecutor.java:348)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiEvaluationVisitor.visitSetStatement(QVTiEvaluationVisitor.java:538)
at org.eclipse.qvtd.pivot.qvtimperative.impl.SetStatementImpl.accept(SetStatementImpl.java:1074)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.BasicQVTiExecutor.internalExecuteMapping(BasicQVTiExecutor.java:324)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiEvaluationVisitor.visitMapping(QVTiEvaluationVisitor.java:412)
at org.eclipse.qvtd.pivot.qvtimperative.impl.MappingImpl.accept(MappingImpl.java:506)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.BasicQVTiExecutor.internalExecuteMappingCall(BasicQVTiExecutor.java:310)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiIncrementalExecutor.internalExecuteInvocation(QVTiIncrementalExecutor.java:245)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiIncrementalExecutor.access$0(QVTiIncrementalExecutor.java:242)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiIncrementalExecutor$InterpretedInvocationConstructor.internalExecuteInvocation(QVTiIncrementalExecutor.java:92)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiIncrementalExecutor$InterpretedInvocationConstructor.access$0(QVTiIncrementalExecutor.java:91)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiIncrementalExecutor$InterpretedInvocation.execute(QVTiIncrementalExecutor.java:111)
at org.eclipse.qvtd.runtime.internal.evaluation.AbstractIntervalInternal.flush(AbstractIntervalInternal.java:216)
at org.eclipse.qvtd.runtime.internal.evaluation.AbstractInvocationManagerInternal.flush(AbstractInvocationManagerInternal.java:96)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.BasicQVTiExecutor.internalExecuteTransformation(BasicQVTiExecutor.java:448)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.QVTiEvaluationVisitor.visitImperativeTransformation(QVTiEvaluationVisitor.java:387)
at org.eclipse.qvtd.pivot.qvtimperative.impl.ImperativeTransformationImpl.accept(ImperativeTransformationImpl.java:167)
at org.eclipse.ocl.pivot.internal.evaluation.AbstractEvaluationVisitor.visit(AbstractEvaluationVisitor.java:290)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.BasicQVTiExecutor.executeInternal(BasicQVTiExecutor.java:179)
at org.eclipse.qvtd.pivot.qvtimperative.evaluation.BasicQVTiExecutor.execute(BasicQVTiExecutor.java:175)
at org.eclipse.qvtd.debug.launching.QVTiLaunchConfigurationDelegate$1.run(QVTiLaunchConfigurationDelegate.java:113)
at org.eclipse.ocl.examples.debug.vm.utils.SafeRunner$SameThreadRunner.run(SafeRunner.java:31)
at org.eclipse.ocl.examples.debug.vm.utils.SafeRunner$1.run(SafeRunner.java:24)
at org.eclipse.ocl.examples.debug.vm.utils.ShallowProcess.run(ShallowProcess.java:40)
at org.eclipse.ocl.examples.debug.vm.utils.ShallowProcess.run(ShallowProcess.java:31)
at org.eclipse.qvtd.debug.launching.QVTiLaunchConfigurationDelegate$3.run(QVTiLaunchConfigurationDelegate.java:158)
at java.base/java.lang.Thread.run(Thread.java:844)
The following transformation doesn't work. I get the syntax error:
Multiple markers at this line
- mismatched input '[' expecting '='
- mismatched input 'eAttributes' expecting '}'
import ECORE : 'http://www.eclipse.org/emf/2002/Ecore';
transformation Test(left:ECORE, right:ECORE)
{
top relation ClassToClass {
checkonly domain left lclass : EClass {
name = className : String{}
};
enforce domain right rclass : EClass {
name = className+'Copy'
};
}
top relation AttributeToAttribute {
lparent : ECORE::EClass;
rparent : ECORE::EClass;
checkonly domain left lattr : EAttribute {
EClass[eAttributes] = lparent,
name = attrName : String{}
};
enforce domain right rattr : EAttribute {
EClass[eAttributes] = rparent,
name = attrName+'Copy'
};
when {
ClassToClass(lparent, rparent);
}
}
}
|
|
|
Powered by
FUDForum. Page generated in 0.07948 seconds