I have a problem with resolving cross references. In more details:
I have one resource in which I hold two types of EObjects. Each of types has an ID property (one of the attributes is an ID) so it means they will be referenced from other resources with path and ID as a fragment. Now for different object type I set same ID value. Of course I get validation marker and warning but I can save a file without problem.
Now from another resource, I have a cross reference to one of types described above. Objects are assigned as elements of EcoreEList. Now when I try to open this resource I get exception because EcoreEList try to resolve cross references and it assumes there is only one object with this ID (problem is in EcoreEList class, method protected EObject resolve(int index, EObject eObject)).
I know IDs should be unique but sometimes it is impossible to force a user to enter unique IDs (forbid saving file with duplicate IDs is not the best solution from user point of view).
I found out that I have this problem especially inside ECrossReferenceEList when it tries to resolve objects which belongs to it via proxy. I thought that maybe customizing this implementation can fix this problem (I can check type of list element and compare with resolved one). However, I do not want to customize each class which has multiple cross reference which are contained in ECrossReferenceEList. Is it possible to do it on core or genmodel level to have it more generic?
That's why I'm not generally a big fan of IDs that are under user control. It's clear the user should be forced to make them unique, and if they don't, it clearly will always lead to problems. I would suggest something more like specializing the resource implementation as I mentioned above (to add type information to the actual ID used while saving without changing the actual value in the model). Alternatively you can use a save option such as org.eclipse.emf.ecore.xmi.XMLResource.OPTION_RESOURCE_HANDLER to implement org.eclipse.emf.ecore.xmi.impl.BasicResourceHandler.preSave(XMLResource, OutputStream, Map<?, ?>) to correct any problem (make IDs unique) that the user refuses to correct. Another possible approach is to specialize the property descriptor for the ID features so that when the ID is displayed to the user the "type prefix/suffix/decoration" is stripped and is added back in automatically when the user enters the value.
I followed your approach with customizing Resource getEObjectByID(String id) and getURIFragment(EObject eObject). It works correctly but now, in case of duplicates (means the wrong type is returned for given ID) I return null so the cross reference is not resolved. I am going to change it - the solution I want to implement is to search in whole resource content and check object type and id and return the correct one. But searching the whole content will definitelly have an impact on performance. Is there any way to get all EObject with given ID? Map intrinsicIDToEObjectMap contains only one object because of ID as a key.
No, the only way to get all objects with a given ID is the second half of the getEObjectByID method, i.e., the only way is to walk the tree. Of course during the tree walk you can build multiple maps or reuse the intrinsic map but with keys that encode the type. This is the only place where you must visit the whole tree and have an opportunity to build a map or maps to avoid repeatedly walking the whole tree...
Thank you for remarks - I was able to do some fixes. However, during implementation, I found some maps like idToEObjectMap or eObjectToIDMap. How they can be used (because in my case they are always empty)?
idToEObjectMap or eObjectToIDMap are very useful IF you want to exploit or take control of the xmi:id allocation. xmi:id values really must be locally (within the file) unique. The maps are populated when a resource with explicit xmi:id's is loaded.
EMF has a default policy using moderately readable hierarchical names that has the benefits of avoiding the need for xmi:id declarations at the expense of potentially long xmi:idref values that are intolerant of non-trivial manual XMI file editing.
You can use an alternate policy by populating the maps yourself during the XMISaveImpl activities.
xmi:ids should not be confused with 'UML' IDs. An xmi:id is not part of the model; it is a model serialization detail. A model stored in an OO database might not use xmi:ids at all.