Загрузка сериализованной модели Ecore, так как XMI не может правильно загрузить защитную оболочку

Я динамически создаю экземпляр модели Ecore в памяти, сериализую его как XMI, а затем пользователь может изменить его во время выполнения моего приложения. Затем я десериализую XMI и сравниваю его с версией предыдущей модели, которая все еще хранится в памяти. При этом ссылки на сдерживание внутри моей модели, кажется, теряются. Предположим, что базовая модель Ecore-Model выглядит так: она имеет класс State и класс Transition, тогда как Transition содержится в State через ссылку на включение с именем transition с кардинальностью 0..*. Таким образом, простой сериализованный XMI экземпляра модели может выглядеть так:

<?xml version="1.0" encoding="ASCII"?>
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:designmodel="http://www.example.org/designmodel">
  <designmodel:State xmi:id="0f359d4a-5154-462c-90aa-e125197cdb6d" name="Ready">
    <transition href="#7880aa8f-1e86-42e0-a212-e91326292d31"/>
  </designmodel:State>
  <designmodel:Transition xmi:id="7880aa8f-1e86-42e0-a212-e91326292d31" name="switchToWaiting"/>
</xmi:XMI>

Теперь, когда я проверяю версию модели, которая у меня есть в памяти, все происходит так, как ожидалось, и вызов eContainer() для объекта Transition возвращает соответствующий объект State, в котором он содержится. Но когда вы делаете то же самое для десериализованного экземпляра модели XMI, eContainer() возвращает НУЛЕВОЙ.

Проходя через отладчик и глядя на соответствующие объекты XMIResource, я вижу то же самое: свойство eContainer имеет значение NULL для объекта Transition для десериализованного XMIResource, но правильно установлено для того, который я храню в памяти. Таким образом, похоже, что вложения теряются во время сериализации/десериализации. Сериализация у меня выглядит так:

ResourceSet savingResSet = new ResourceSetImpl();
savingResSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());

XMIResource savingRes = (XMIResource) savingResSet.createResource(URI.createFileURI(outputPath), null);
savingRes.getDefaultSaveOptions().put(XMIResource.OPTION_KEEP_DEFAULT_CONTENT, Boolean.TRUE);


//adding the generated elements to the resource
generatedDesignmodelElements().forEach(e -> {
    if(e != null) {
        savingRes.getContents().add(e);
        savingRes.setID(e, UUID.randomUUID().toString());
    }
});

//saving it
try {
    savingRes.save(Collections.EMPTY_MAP);
} catch (IOException e) {
    e.printStackTrace();

Десериализация просто так:

ResourceSet resSet = new ResourceSetImpl();      
resSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
    XMIResource updatedModel =(XMIResource)resSet.getResource(URI.createFileURI(sourcePath), true);

//iterating over the objects directly contained in the resource (so all State- and Transition-objects get reached here, since they are root objects themselves)
updatedModel.getContents().forEach(updatedModelElement -> {
    System.out.println(updatedModelelement + updatedModelElement.eContainer()); //this is always NULL
});

Итак: почему этот eContainer()-вызов всегда возвращает NULL для XMIResource, который я десериализовал, но ведет себя правильно при вызове XMIResource, который у меня есть в памяти?

Большое спасибо :)


person Akustiker    schedule 20.07.2019    source источник


Ответы (1)


Я решил это самостоятельно: ошибка заключалась в том, что я также добавил содержащиеся EObjects сами по себе (в дополнение к тому, что они неявно добавляются к ресурсу через их объект-контейнер). Простая проверка того, есть ли у созданного EObject контейнер, прежде чем добавлять его в ресурс, который я затем сериализую в конце, решил все.

person Akustiker    schedule 21.07.2019
comment
Хорошо, что вы отправили ответ с решением! Вы также можете принять свое собственное решение, чтобы другим было легче увидеть, что проблема решена. - person Lii; 26.07.2019