Consider the basic ATL transformation Families2Persons, running it through EMFTVM and getting the traces as explained in the docs.
-- @atlcompiler emftvm
-- @path Families=/Test/Families.ecore
-- @path Persons=/Test/Persons.ecore
module Families2Persons;
create OUT: Persons, trace: Trace from IN: Families;
rule Member2Male {
from
s: Families!Member (not s.isFemale())
to
t: Persons!Male (
fullName <- s.firstName + ' ' + s.familyName
)
}
rule Member2Female {
from
s: Families!Member (s.isFemale())
to
t: Persons!Female (
fullName <- s.firstName + ' ' + s.familyName
)
}
I omitted the helper functions to save space, but I didn't change them compared with the tutorial example
When I ran the transformation using my Eclipse environment, everything worked fine and I got the result model and the traces as expected. Below is a snippet of the traces.xmi generated after running it.
<links>
<sourceElements name="s" defaultFor="/">
<object href="../sample-Families.xmi#/0/@father"/>
</sourceElements>
<targetElements name="t">
<object href="../person-emftvm.xmi#/0"/>
</targetElements>
</links>
Trying to run the same transformation programmatically (also adapting the Java code from the docs), I got the same model output, but my traces model includes the absolute path instead of the relative path like the previous example. Snippets below:
Java code:
public class RunTestTransformation {
public static String here = new File(".").getAbsolutePath();
public static URI resourceURI(String relativePath) {
return URI.createFileURI(here + relativePath);
}
public static void main(String[] args) throws IOException {
Map<String, Object> map = Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap();
map.put("xmi", new XMIResourceFactoryImpl());
map.put("ecore", new EcoreResourceFactoryImpl());
map.put("emftvm", new EMFTVMResourceFactoryImpl());
ExecEnv env = EmftvmFactory.eINSTANCE.createExecEnv();
ResourceSet rs = new ResourceSetImpl();
// Register the metamodels into resource set
EPackage FamiliesPkg = (EPackage) rs.getResource(resourceURI("/../Test/Families.ecore"), true).getContents()
.get(0);
EPackage.Registry.INSTANCE.put(FamiliesPkg.getNsURI(), FamiliesPkg);
EPackage PersonsPkg = (EPackage) rs.getResource(resourceURI("/../Test/Persons.ecore"), true).getContents()
.get(0);
EPackage.Registry.INSTANCE.put(PersonsPkg.getNsURI(), PersonsPkg);
// Load metamodels into execenv
Metamodel familiesMetaModel = EmftvmFactory.eINSTANCE.createMetamodel();
familiesMetaModel.setResource(rs.getResource(resourceURI("/../Test/Families.ecore"), true));
env.registerMetaModel("Families", familiesMetaModel);
Metamodel personsMetaModel = EmftvmFactory.eINSTANCE.createMetamodel();
personsMetaModel.setResource(rs.getResource(resourceURI("/../Test/Persons.ecore"), true));
env.registerMetaModel("Persons", personsMetaModel);
String relativeInputPath = "/../Test/sample-Families.xmi";
String relativeTracePath = "/../Test/traces.xmi";
String relativeOutputPath = "/../Test/persons.xmi";
// Load models
URI inputUri = resourceURI(relativeInputPath);
Model inModel = EmftvmFactory.eINSTANCE.createModel();
inModel.setResource(rs.getResource(inputUri, true));
env.registerInputModel("IN", inModel);
URI uriTrace = resourceURI(relativeTracePath);
Model traceOutModel = EmftvmFactory.eINSTANCE.createModel();
traceOutModel.setResource(rs.createResource(uriTrace));
env.registerOutputModel("trace", traceOutModel);
URI uriOut = resourceURI(relativeOutputPath);
Model outModel = EmftvmFactory.eINSTANCE.createModel();
outModel.setResource(rs.createResource(uriOut));
env.registerOutputModel("OUT", outModel);
// Load and run module
ModuleResolver mr = new DefaultModuleResolver("./../Test/emftvm/", rs);
TimingData td = new TimingData();
env.loadModule(mr, "Families2Persons");
td.finishLoading();
env.run(td);
td.finish();
// Save models
inModel.getResource().save(Collections.emptyMap());
traceOutModel.getResource().save(Collections.emptyMap());
outModel.getResource().save(Collections.emptyMap());
}
}
Output trace excerpt:
<links>
<sourceElements name="s" defaultFor="/">
<object href="file:/C:/Users/XXXX/./../Test/sample-Families.xmi#/0/@father"/>
</sourceElements>
<targetElements name="t">
<object href="file:/C:/Users/XXXX/./../Test/persons.xmi#/0"/>
</targetElements>
</links>
How can I get the same result for traces both running through Eclipse and programmatically? I can understand that the problem is that my Eclipse environment knows about my workspace, but I don't know how to configure my Java code to behave similarly.
I've tried
createFileURI()
by createURI()
-> Compilation errorsave()
method -> Not effectivecreateFileURI()
instead of appending it to the current Java file location (see method resourceURI()
in the code) -> File not foundI guess the issue is with how you are loading your models programmatically. Currently you are using file URIs. I guess ATL being installed in your current running Eclipse, works mostly with 'platform:/resource' URIs. And probably when serializing the trace model, EMF identifies that both Resources are not far from each other and thus prefers serializing with relative URIs.
So I think the fix depends on whether your code is supposed to be a standalone Java application or embedded in Eclipse. If the latter, then simply loading models with 'platform:/resource' might maybe work. Of course you will have to find some way to have your files into your running instance workspace location. If the former, I think you maybe have to play with the org.eclipse.emf.ecore.resource.URIConverter of your ResourceSet