pythonuuideclipse-emf

Get UUID from a EMF/XMI resource using PyEcore


I have an XMI file serialized in a Java/EMF program. Now, I need to read it using PyEcore, and I want to set the UUID and then retrieve it back while iterating over the resource.

This is my current code:

from os import path as osp
from pathlib import Path

#PyEcore
from pyecore.resources import URI

xmi_path = osp.join(RESOURCES_PATH, 'models', 'my_model.xmi')
m_resource = resource_set.get_resource(URI(xmi_path))
m_resource.use_uuid = True
#save resource with UUIDs at temporary directory
m_resource.save(output=URI(osp.join(RESOURCES_PATH, 'models', 'temp', 'my_model_uuid_version.xmi')))


for obj in m_resource.contents[0].eAllContents():
    obj_type= obj.eClass.name
    #obj_uuid = What should I do here?
    #print(obj_uuid)

I looked at the documentation but found nothing. I tried to "guess" some possibilities, like getID(), obj.eGet('xmi_uuid'), but everything failed. Due to the lazy loading, dir(obj) doesn't give me any tips either.

Below is a part of the file successfully saved at "models/temp/my_model_uuid_version.xmi" (it means it's not a problem on the first part of the code). The original (Java) version was created with URI fragments instead of the id.

<?xml version='1.0' encoding='UTF-8'?>
<emf.modeling.test:Root xmlns:xmi="http://www.omg.org/XMI" xmlns:emf.modeling.test="emf.modeling.test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmi:id="2def7906-85ad-4852-ad4b-a4db577a14c6" xmi:version="2.0">
  <regions xmi:id="b4b7b97c-9549-4700-b51c-cc3a68166a71">
    <vertices xsi:type="emf.modeling.test:Entry" xmi:id="a7ca20d5-c2bb-4ff9-a8f6-c9c53e496a83">
      <out xmi:id="6f0a5530-14a0-41fa-91de-681df25f9aff" target="f1bfedb7-41a7-4582-b736-71f804ffe65d"/>
    </vertices>
    <vertices xsi:type="emf.modeling.test:State" xmi:id="f1bfedb7-41a7-4582-b736-71f804ffe65d" incomingTransitions="6f0a5530-14a0-41fa-91de-681df25f9aff 59290d7f-032c-460c-a158-f4ed83dcdaba 3aa3a4ea-f7fc-495f-aaec-d7b957bc9c86 4c4264ff-1cdb-45e8-bdc4-289f23aa668d 94b5a479-f5aa-4de5-b5e5-93b61a676af7 b979f49a-bb16-43b0-abee-2808653d7342 6270c0fd-6e8a-4667-bde9-d77636e60762 7014ca4f-fa00-4ea0-abf4-772bab9f6f1e 58b0e66e-73e7-4c0c-9b7b-4ba319ec7350 ecc020db-7c64-4cc8-9b9e-d29b6692c799 e04b9856-8b90-4d6c-a64b-14173cd72e8c dd54139d-32eb-4374-abb3-115d6d53cd61 a10a2db2-9a0c-47bd-8b77-307f8a21ed15">
      <out xmi:id="c06a3aeb-e86b-4dec-837e-d28f92cb7ef9" target="582156e7-c756-462d-aaaa-f9348d96813d"/>
      <out xmi:id="a70aec31-886f-477e-9c25-b641341e52c4" target="d609bdde-e299-40d1-84f5-104fd975a287"/>
    </vertices>
    <!--...more vertices-->
  </regions>
</emf.modeling.test:Root>

Solution

  • The way PyEcore handles uuids there is to set a special attribute _internal_id on each elements after serialization. To retrieve the uuid set by the resource, you can then transform your code this way:

    from os import path as osp
    from pathlib import Path
    
    #PyEcore
    from pyecore.resources import URI
    
    xmi_path = osp.join(RESOURCES_PATH, 'models', 'my_model.xmi')
    m_resource = resource_set.get_resource(URI(xmi_path))
    m_resource.use_uuid = True
    #save resource with UUIDs at temporary directory
    m_resource.save(output=URI(osp.join(RESOURCES_PATH, 'models', 'temp', 'my_model_uuid_version.xmi')))
    
    
    for obj in m_resource.contents[0].eAllContents():
        obj_type= obj.eClass.name
        obj_uuid = obj._internal_id
        print(obj_uuid)
    

    The way EObjects reacts to dir(...) is tweaked, so that's why you cannot find directly this kind of low level information there. If you want to see the internal of an object, knowing that you'll have way more information than what you need, you can use obj.__dict__. This will give you a glimpse of the internal mechanic of PyEcore, and you'll see the _internal_id attribute there also.

    This is something that is not documented as it's not really a classical use of the library, even in EMF Java, it's not really a situation that comes so often. I should write something for it though...