由于 XMI 无法正确加载容器而加载序列化的 Ecore 模型
Loading serialized Ecore Model as XMI fails to load containments correctly
我正在内存中动态创建 Ecore 模型的实例,将其序列化为 XMI,然后用户可能会在我的应用程序运行期间修改它。因此,我随后反序列化 XMI,并将其与我仍保留在内存中的先前模型版本进行比较。
这样做时,模型中的包含引用似乎丢失了。假设底层 Ecore-Model 看起来像这样:它有一个 class State
和一个 class Transition
,而 Transition
包含在 [=13= 中] 通过名为 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>
现在,当检查我在内存中的模型版本时,一切都符合预期并在 Transition-object returns 上调用 eContainer()
它包含的相应 State-object。但是当对反序列化的 XMI 模型实例执行相同的操作,eContainer()
returns NULL.
当单步执行调试器并查看相应的 XMIResource
对象时,我可以看到相同的结果:eContainer-属性 对于反序列化 XMIResource 的转换对象为 NULL,但正确设置为我记得的那个。
所以看起来收容措施在 serialization/deserialization 期间丢失了。我的序列化看起来像这样:
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
});
所以:为什么我反序列化的 XMIResource 的 eContainer()
-call 总是 returns NULL,但在我内存中的 XMIResource 上调用时表现正常?
非常感谢:)
我自己解决了:
错误是,我也自己添加了包含的 EObject(因此另外通过它们的 container-object 将它们隐式添加到资源中)。
在将创建的 EObject 添加到资源之前简单地检查它是否有容器,然后在最后序列化解决了所有问题。
我正在内存中动态创建 Ecore 模型的实例,将其序列化为 XMI,然后用户可能会在我的应用程序运行期间修改它。因此,我随后反序列化 XMI,并将其与我仍保留在内存中的先前模型版本进行比较。
这样做时,模型中的包含引用似乎丢失了。假设底层 Ecore-Model 看起来像这样:它有一个 class State
和一个 class Transition
,而 Transition
包含在 [=13= 中] 通过名为 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>
现在,当检查我在内存中的模型版本时,一切都符合预期并在 Transition-object returns 上调用 eContainer()
它包含的相应 State-object。但是当对反序列化的 XMI 模型实例执行相同的操作,eContainer()
returns NULL.
当单步执行调试器并查看相应的 XMIResource
对象时,我可以看到相同的结果:eContainer-属性 对于反序列化 XMIResource 的转换对象为 NULL,但正确设置为我记得的那个。
所以看起来收容措施在 serialization/deserialization 期间丢失了。我的序列化看起来像这样:
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
});
所以:为什么我反序列化的 XMIResource 的 eContainer()
-call 总是 returns NULL,但在我内存中的 XMIResource 上调用时表现正常?
非常感谢:)
我自己解决了: 错误是,我也自己添加了包含的 EObject(因此另外通过它们的 container-object 将它们隐式添加到资源中)。 在将创建的 EObject 添加到资源之前简单地检查它是否有容器,然后在最后序列化解决了所有问题。