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 06:59  |
Eclipse User |
|
|
|
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 07:02] by Moderator
|
|
| |
Re: Cannot add stereotypes when launching the QVTo transform programmatically from Java [message #1741854 is a reply to message #1741285] |
Tue, 30 August 2016 04:04  |
Eclipse User |
|
|
|
Hi
When executing QVTo from Java, the Java code generated from the UML metamodel is used to create/modify models. This code enforces that a stereotype can only be applied to a model element if it has a) a proper container, and b) the corresponding profile has been applied to the container element. This is a sort of business logic of the UML metamodel, certainly not a misbehavior of QVTo. When running in debug mode, the generated Java code is not used and, therefore, the constraint does not apply.
Kind regards
Christopher
|
|
|
Goto Forum:
Current Time: Wed Jul 23 22:03:03 EDT 2025
Powered by FUDForum. Page generated in 0.02800 seconds
|