Как получить относительные пути в модели трассировок при программном выполнении преобразования ATL через EMFTVM?
Рассмотрим базовое преобразование ATL Families2Persons, пропустив его через EMFTVM и получив трассировки, как описано в документации .
-- @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
)
}
Я опустил вспомогательные функции для экономии места, но не изменил их по сравнению с учебным примером.
Когда я запустил преобразование с использованием среды Eclipse, все работало нормально, и я получил ожидаемую результирующую модель и трассировки. Ниже приведен фрагмент файла трассировки.xmi, созданного после его запуска.
<links>
<sourceElements name="s" defaultFor="/">
<object href="../sample-Families.xmi#/0/@father"/>
</sourceElements>
<targetElements name="t">
<object href="../person-emftvm.xmi#/0"/>
</targetElements>
</links>
Пытаясь выполнить то же преобразование программно (также адаптируя код Java из документации ) , я получил тот же результат модели, но моя модель трассировок включает абсолютный путь вместо относительного пути, как в предыдущем примере. Фрагменты ниже:
Java-код:
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());
}
}
Выдержка из трассировки:
<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>
Как я могу получить один и тот же результат для трассировок, выполняемых через Eclipse и программно? Я понимаю, что проблема в том, что моя среда Eclipse знает о моей рабочей области, но я не знаю, как настроить свой Java-код на аналогичное поведение.
я пробовал
- Изменить на
createURI()
-> Ошибка компиляции - Различные параметры XMLResource в
save()
метод -> Не эффективен - Передайте прямой мой «относительный путь» к
createFileURI()
вместо добавления его к текущему местоположению файла Java (см. методresourceURI()
в коде) -> Файл не найден
1 ответ
Я предполагаю, что проблема в том, как вы программно загружаете свои модели. В настоящее время вы используете файловые URI. Я предполагаю, что ATL, установленный в вашем текущем запущенном Eclipse, работает в основном с URI «платформа:/ресурс». И, вероятно, при сериализации модели трассировки EMF определяет, что оба ресурса находятся недалеко друг от друга, и поэтому предпочитает сериализацию с относительными URI.
Поэтому я думаю, что исправление зависит от того, будет ли ваш код автономным Java-приложением или встроен в Eclipse. В последнем случае может сработать простая загрузка моделей с помощью «platform:/resource». Конечно, вам придется найти какой-то способ разместить файлы в рабочей области рабочего экземпляра. Если первое, я думаю, вам, возможно, придется поиграть с org.eclipse.emf.ecore.resource.URIConverter вашего ResourceSet.