Home » Modeling » QVT-OML » Cannot add stereotypes when launching the QVTo transform programmatically from Java(I provide a minimal example to try out. Any help on how to make it work?)
Cannot add stereotypes when launching the QVTo transform programmatically from Java [message #1741285] |
Wed, 24 August 2016 10:59 |
Matteo M. Messages: 40 Registered: May 2012 |
Member |
|
|
Hi all,
I have a QVTo transform that operates on an 'inout' UML model. The transformation adds UML artifacts to an existing UML model and applies them SysML stereotypes. It's invoked programmatically from Java code. In my test case, I use a right-click menu in the run-time instance, see the attached minimal example projects to try out, test.m2m, test.executor and TestSandboxModel.zip (place this one in the workspace for the runtime instance). My environment is Eclipse Modeling Tools Version: Neon Release (4.6.0) Build id: 20160613-1800.
The problem is that I'm not able to apply stereotypes to model elements. More specifically, after using
element.applyStereotype(stereotype);
to apply a stereotype to an element in QVTo, the following assertion fails
assert fatal (element.isStereotypeApplied(stereotype));
The attached example project (TestSandboxModel.zip) is a simple SysML model with a 'Block' and a 'FlowPort' in its root element (TestSandboxModel.zip). For quick reference, here's the QVTo transform, that adds a Port to the Class in the model and applies the 'FlowPort' stereotype to it.
modeltype UML uses 'http://www.eclipse.org/uml2/5.0.0/UML';
transformation SimpleUmlIncrementalMod(inout uml:UML);
property umlModel = uml.rootObjects()![Model];
property FlowPortStereotype = umlModel.getAppliedProfiles().ownedStereotype![name = 'FlowPort'];
main()
{
log('SimpleUmlIncrementalMod Transformation Started');
log('');
// get the class
var clz := umlModel.allSubobjectsOfKind(Class)![Class];
// create new port
var prt := object Port {name := 'xyz';};
// add it to the class
clz.ownedAttribute += prt;
// apply stereotype
applyStereotypeAndCheck(prt, FlowPortStereotype);
log('');
log('Transformation ended.');
}
helper applyStereotypeAndCheck(inout element : Element, in stereotype : Stereotype)
{
assert fatal (element.isStereotypeApplicable(stereotype))
with log('Stereotype ' + stereotype.qualifiedName + ' is not applicable to element ' + element.repr());
var xx := element.applyStereotype(stereotype);
log(' Returned ecore::EObject repr() is ' + xx.repr());
assert fatal (element.isStereotypeApplied(stereotype))
with log('Stereotype ' + stereotype.qualifiedName + ' hasnt been applied to element ' + element.repr());
log(' Applied the stereotype ' + stereotype.qualifiedName);
log('');
}
And here's is the Java code that calls the transform executor.
package test.executor;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.m2m.qvt.oml.BasicModelExtent;
import org.eclipse.m2m.qvt.oml.ExecutionContextImpl;
import org.eclipse.m2m.qvt.oml.ExecutionDiagnostic;
import org.eclipse.m2m.qvt.oml.ModelExtent;
import org.eclipse.m2m.qvt.oml.TransformationExecutor;
import org.eclipse.m2m.qvt.oml.util.Log;
import org.eclipse.m2m.qvt.oml.util.WriterLog;
import org.eclipse.papyrus.sysml.portandflows.PortandflowsPackage;
import org.eclipse.uml2.uml.UMLPackage;
public class SimpleUmlIncrementalModExecutor {
public static void run(String path)
{
// Refer to an existing transformation via URI
URI transformationURI = URI.createURI("platform:/plugin/test.m2m/transforms/SimpleUmlIncrementalMod.qvto");
//
// metamodels
EPackage.Registry registry = new EPackageRegistryImpl(EPackage.Registry.INSTANCE);
UMLPackage theUMLPackage = (UMLPackage)EPackage.Registry.INSTANCE.getEPackage(UMLPackage.eNS_URI);
PortandflowsPackage thePortandflowsPackage=(PortandflowsPackage)EPackage.Registry.INSTANCE.getEPackage(PortandflowsPackage.eNS_URI);
registry.put(theUMLPackage.getNsURI(), theUMLPackage);
registry.put(thePortandflowsPackage.getNsURI(), thePortandflowsPackage);
// create executor for the given transformation
TransformationExecutor executor = new TransformationExecutor(transformationURI, registry);
//
// define the transformation inout
// Remark: we take the objects from a resource, however
// a list of arbitrary in-memory EObjects may be passed
ResourceSet resourceSet = new ResourceSetImpl();
EList<EObject> inOutObjects = resourceSet
.getResource(URI.createFileURI(path),true)
.getContents();
//
// create the inout extent with its initial content
ModelExtent inout = new BasicModelExtent(inOutObjects);
//
// setup the execution environment details ->
// configuration properties, logger, monitor object etc.
OutputStreamWriter outStream = new OutputStreamWriter(System.out);
Log log = new WriterLog(outStream);
ExecutionContextImpl context = new ExecutionContextImpl();
context.setConfigProperty("keepModeling", true);
context.setLog(log);
//
// run the transformation assigned to the executor with the given
// input and output and execution context -> ChangeTheWorld(in, out)
// Remark: variable arguments count is supported
ExecutionDiagnostic result = executor.execute(context, inout);
//
// check the result for success
if(result.getSeverity() == Diagnostic.OK)
{
// This list contains all the objects from the initial ModelExtent, plus all the ones
// which were created during the QVTo transformations.
List<EObject> inOutObjects2 = inout.getContents();
resourceSet.getResource(URI.createFileURI(path),true)
.getContents().addAll(inOutObjects2);
try
{
resourceSet.getResource(URI.createFileURI(path),true)
.save(Collections.emptyMap());
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
// turn the result diagnostic into status and send it to error log
IStatus status = BasicDiagnostic.toIStatus(result);
Activator.getDefault().getLog().log(status);
}
}
}
Additional considerations:
- If I just execute the QVTo transform in standalone mode (using Run Configuration to configure the inout arg), it works.
- If i do not apply the 'FlowPort' stereotype --i.e., I remove/comment the applyStereotypeAndCheck(prt, FlowPortStereotype); in the QVTo transform-- the Port 'xyz' is added to the Class in both cases (standalone execution and programmatic invokation from Java)
- when the transform is invoked from Java and applyStereotypeAndCheck() is executed, the following happens:
- the stereotype seems to be correctly applied; this log message is displayed in the console
Returned ecore::EObject repr() is org.eclipse.papyrus.sysml.portandflows.internal.impl.FlowPortImpl@5df1ee9f (isConjugated: false, direction: inout)
- the 2nd assert statement fails, that checks for the actual stereotype application; I see the following log message:
ASSERT [fatal] failed at (SimpleUmlIncrementalMod.qvto:30) : Stereotype SysML::PortAndFlows::FlowPort hasnt been applied to element org.eclipse.uml2.uml.internal.impl.PortImpl@4d496696 (name: xyz, visibility: <unset>) (isLeaf: false) (isStatic: false) (isOrdered: false, isUnique: true, isReadOnly: false) (aggregation: none, isDerived: false, isDerivedUnion: false, isID: false) (isBehavior: false, isConjugated: false, isService: true)
Terminating execution...
org.eclipse.m2m.internal.qvt.oml.evaluator.QvtAssertionFailed: Stereotype SysML::PortAndFlows::FlowPort hasnt been applied to element org.eclipse.uml2.uml.internal.impl.PortImpl@4d496696 (name: xyz, visibility: <unset>) (isLeaf: false) (isStatic: false) (isOrdered: false, isUnique: true, isReadOnly: false) (aggregation: none, isDerived: false, isDerivedUnion: false, isID: false) (isBehavior: false, isConjugated: false, isService: true)
at SimpleUmlIncrementalMod::applyStereotypeAndCheck(SimpleUmlIncrementalMod.qvto:31)
at SimpleUmlIncrementalMod::main(SimpleUmlIncrementalMod.qvto:19)
...
Given that it works in standalone mode, I suppose it's due to how I call the transform programmatically from Java. Any hint?
Thank you in advance for your help.
--
Matteo
[Updated on: Wed, 24 August 2016 11:02] Report message to a moderator
|
|
| | |
Goto Forum:
Current Time: Wed Apr 24 15:46:43 GMT 2024
Powered by FUDForum. Page generated in 0.02758 seconds
|