Home » Modeling » EMF » Handling references to XML datatypes uniformly
| Handling references to XML datatypes uniformly [message #1833222] |
Wed, 07 October 2020 04:48  |
Eclipse User |
|
|
|
Hello
I have a tool that loads an ecore file from the workspace and generates some text artifacts. I had some troubles processing some models and I have pinpointed my problem to the way that XML types (IDREF,..) are referenced in the ecore model.
After some debugging I have identified three different cases :
Case 1 The user edits the ecore file and uses Load Resourse + browse registered package to search for the xml type namesapace. The XML types package is loaded using a platform:/plugin/ URI and the types are referenced using an absolute URI :
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="metamodel" nsURI="http:://metamodel">
<eClassifiers xsi:type="ecore:EClass" name="A">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/XMLType.ecore#//IDREF"/>
</eClassifiers>
</ecore:EPackage>
Case 2 The user edits the ecore file and uses Load Resourse + browse target platform to search for the xml type namesapace. The XML types package is loaded using a platform:/resource/ URI and the types are referenced using a relative URI :
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="metamodel" nsURI="http:://metamodel">
<eClassifiers xsi:type="ecore:EClass" name="A">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType ../../org.eclipse.emf.ecore/model/XMLType.ecore#//IDREF"/>
</eClassifiers>
</ecore:EPackage>
Case 3 The ecore file is generated from an xml schema . The generated XML types package is loaded using the namespace URI and the types are referenced using an absolute nsURI :
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="metamodel" nsURI="http:://metamodel">
<eClassifiers xsi:type="ecore:EClass" name="A">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//IDREF"/>
</eClassifiers>
</ecore:EPackage>
I managed to handle all cases, but I would like to have some advice to know whether I am doing things properly.
The first question concerns loading of the model. The actual code that I wrote is the following :
// get the selected file
IFile selectedFile = ....
// load the metamodel
ResourceSet sandbox = new ResourceSetImpl();
sandbox.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore",new EcoreResourceFactoryImpl());
sandbox.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE);
URI metamodelURI = URI.createPlatformResourceURI(selectedFile.getFullPath().toString(),true);
System.out.println("........ selected model file : " + metamodelURI.toString());
EPackage metamodel = (EPackage) sandbox.getResource(metamodelURI,true).getContents().get(0);
doGenerate(metamodel, selectedFile.getParent()) ;
try {
selectedFile.getParent().refreshLocal(IResource.DEPTH_INFINITE,null);
} catch (CoreException e) {
throw new ExecutionException("Error refreshing workspace",e);
}
This handles correctly Case 1 and Case 3. But for Case 2 the relative URI reference is resolved to an absolute resource reference platform:/resource/org.eclipse.emf.ecore/model/XMLType.ecore#//IDREF that fails to load, and I end up with unresolved proxies. Because I am running from a plugin (not standalone) I was expecting some mapping from platform:/resource/<pluginid>/ to platform:/plugin/<pluginid>/ to be automagically registered (as it seems to be happening inside the ecore editor) but that is not evidently the case in my code.
After searching old posts and blogs, I solved the problem adding the following code
sandbox.getURIConverter().getURIMap().putAll(EcorePlugin.computePlatformURIMap(true));
This worked, but has the side effect of mapping some platform:/plugin/... URIs to physical archive:/... location URIs . which breaks some other unrelated parts of my tool that were expecting to handle only platform:/ URIs.
At the end I made it work, but the question is whether this is the recommended way to handle the mapping from platform:/resource/<pluginid>/ to platform:/plugin/<pluginid>/ inside an Eclipse plugin. Or is there some other simpler way (without the side effects) ?
I suppose this issue is not specific to XML types, and it can happen with any cross package references between ecore models, depending on how the target package is available in the workspace of my tool's user (installed, in the target platform or in the workspace) so I am looking for a generic solution (not one that works only for XML types).
The second question concern the best way to reference the XML types in the code. My tool have many special cases to handle XML types so I have a lot of code that looks like this :
EDataType eType = ....get the type of some loaded fetaure ...
if (eType.getEPackage().getNsURI().equals(XMLTypePackage.eNS_URI)) {
if (eType == XMLTypePackage.Literals.STRING) {
... special processing ...
}
}
Obviously this only works in Case 3 that uses the registered generated XML type package. For the other two cases the loaded datatype is one in my resource set and the identity (==) test fails. To make it work for the other cases, I finally end up comparing names :
if (eType..getName().equals(XMLTypePackage.Literals.STRING.getName())) {
}
The question is if there is some other, more efficient, way to compare two EDataType instances (possibly loaded from different resources) and decide that they represent the same logical classifier ?
Thanks in advance for the advice,
German Vega
|
|
| |
| Re: Handling references to XML datatypes uniformly [message #1833242 is a reply to message #1833235] |
Wed, 07 October 2020 09:45   |
Eclipse User |
|
|
|
Hi,
Quote:
Note that a platform:/plugin URI refers to the plugin in the running IDE, so if one really wants the one from the target platform, one must use the physical location of that jar because of course that could be a different version of the plugin than what's running in the IDE.
Ok, thanks for the clarification, now I understand the logic behind the URI mappings. I was doing this by trial and error, without much understanding, that is why I wanted to have some authoritative confirmation ;) .
My tools is usually used in combination with the ecore editor, so the important thing for me is to be sure that it will load exactly the same resources as the ecore editor would.
Thank you, again.
|
|
| | |
| Re: Handling references to XML datatypes uniformly [message #1833284 is a reply to message #1833254] |
Thu, 08 October 2020 08:12   |
Eclipse User |
|
|
|
Hi both Eds,
Just to share the point of view of some integrator-user of many wonderful eclipse (meta-) modeling technologies :)
I tend to agree with Ed Merks that is better to approach this issue as a reality that you have to face (the "same" metamodel may happen to exist in the running IDE, the workspace and the target platform) rather than as a problem or shortcoming of the framework that you have to workaround.
For the problem at hand, I wanted to have exactly the same environment as the ecore editor. The clarification of the subtle difference between installed plugin and target platform has been really enlightening for me. I found the solution of using relative URIs to reference the target platform metamodels very clever, as the reference may be resolved both inside the editor (mapping the platform:/resource/<pluginid> URIs to physical locations) and later in the running target platform (the relative URI simply resolve to an absolute platform:/plugin/<pluginid> URI) without modification.
I am glad there is public API (EcorePlugin.computePlatformURIMap) to recreate exactly the same context.
That being said, I can also imagine that if you want to make a tool (like the OCL interpreter, or the acceleo MTL interpreter) that works *simultaneously* 1) in the running modeling IDE referencing the metamodels using platform:/resource URIs and loading dynamic reflective instances, 2) in the running target platform (@Ed Willink, is that what you call post-genmodel ? ) referencing the metamodels using platform:/plugin URIs and loading generated class instances, and 3) in standalone mode, referencing the metamodels either using nsURI or platform:/plugin or physical location URIs and loading dynamic or generated instances (depending on how the classpath is setup and how the different ResourceSet registries and URI mappings are populated); the reality that you have to face may quickly become nightmarish, and the toolsmith may become a little schizophrenic ;)
I have used in the past the OCL StandaloneProjectMap (without understanding what it does) to integrate the OCL interpreter in my tools, and I think that Ed Willink did a great job allowing third-party tools, like mine, to effortlessly use the interpreter without much concern about how metamodels are referenced or loaded in the most common cases. It is only now, that I directly confronted this reality, that I start to understand the issues at hand.
I have also seen other projects (like QVT metamodel registry or Sirius model index) came up with other similar solutions (that I have used without really caring to understand how they work or why) , so one may wish to have some common mechanism at the EMF framework level to handle this. However, personally I see now that there are so many different environments and possibilities that is almost impossible to come up with a solution to fit all usecases. I think the EMF framework already have the extension mechanisms (package registries, URL mappings, etc) to implement any strategy one may imagine to resolve cross resource (meta-) model references, depending on the running environment, possibly unifying or normalizing resource access to avoid multiple in-memory copies of the "same" model, or whatever else one wants. So I really think is up to each tool project to clearly identify its requirements, well-document them and, if possible, package the solution in some reusable code (like the OCL StandaloneProjectMap) that others may reuse if it fits their needs
Best regards
|
|
|
| Re: Handling references to XML datatypes uniformly [message #1833311 is a reply to message #1833284] |
Thu, 08 October 2020 15:58  |
Eclipse User |
|
|
|
Hi
The UMLX then QVTd then OCL Metamodel Registry is dead and has not been shipped for at least two years. It provided a 'manual' capability to register metamodels for use in a dynamic context but only by those tools that knew to use it. It was rendered obsolete by MWE2's StandaloneSetup's demonstration that registrations could be discovered by scanning the classpath. This was the basis for OCL's StandaloneProjectMap. Similar functionality but in one direction only was added to EMF via the EcorePlugin's ExtensionProcessor.
While OCL's StandaloneProjectMap 'solves' the metamodel schizophrenia problem, it is not easy to configure and so I still find that I have a nasty metamodel schizophrenia issue to debug two or three times per year.
Recently I have been working on a declarative Serializer/Formatter for Xtext and encountered metamodel schizophrenia again and since within the context of Xtext and its non-standard ResourceSets, an OCL dependency and/or practice is clearly unacceptable. I failed to resolve the problem and had to resort to name equality and once again reflect on why this is all so hard. In https://bugs.eclipse.org/bugs/show_bug.cgi?id=567161#c8 I suggest that we actually have two different worlds. A post-genmodel Java world where all the metamodels should (appear to be) compiled Java and a pre-genmodel modeling world where all the metamodels should (appear to be) dynamically loaded. The bidirectional mapping capability of the OCL StandaloneProjectMap can support this but with a different configuration to fix up consistency of each world. The problems arise when an application is not uniquely in one world or the other and if it uses the genmodels with their modeling world references to for instance predict the method names of the Java artefacts.
After ten years fighting to defeat metamodel schizophrenia, I am wondering whether to embrace it and ensure that all code is schizophrenia tolerant; but it will then just be another variant of the ==/equals problem for Strings. Then I remember how difficult it will be to have an old and new variant of the 'same' EClass in memory at once. The OCL Pivot CompleteModel 'resolves' the problem by a UML-like merge, but that is yet another non-trivial activity that seems to create as many problems as it solves.
Regards
Ed Willink
|
|
|
Goto Forum:
Current Time: Fri Nov 07 08:33:50 EST 2025
Powered by FUDForum. Page generated in 0.06301 seconds
|