Как получить относительные пути в модели трассировок при программном выполнении преобразования 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-код на аналогичное поведение.

я пробовал

  1. Изменить наcreateURI()-> Ошибка компиляции
  2. Различные параметры XMLResource вsave()метод -> Не эффективен
  3. Передайте прямой мой «относительный путь» кcreateFileURI()вместо добавления его к текущему местоположению файла Java (см. методresourceURI()в коде) -> Файл не найден

1 ответ

Я предполагаю, что проблема в том, как вы программно загружаете свои модели. В настоящее время вы используете файловые URI. Я предполагаю, что ATL, установленный в вашем текущем запущенном Eclipse, работает в основном с URI «платформа:/ресурс». И, вероятно, при сериализации модели трассировки EMF определяет, что оба ресурса находятся недалеко друг от друга, и поэтому предпочитает сериализацию с относительными URI.

Поэтому я думаю, что исправление зависит от того, будет ли ваш код автономным Java-приложением или встроен в Eclipse. В последнем случае может сработать простая загрузка моделей с помощью «platform:/resource». Конечно, вам придется найти какой-то способ разместить файлы в рабочей области рабочего экземпляра. Если первое, я думаю, вам, возможно, придется поиграть с org.eclipse.emf.ecore.resource.URIConverter вашего ResourceSet.

Другие вопросы по тегам