Using Platform Resources as EReferences in GMF
In my GMF-based project, I wanted to have a model like so:
Thing
- type : XSDSimpleTypeDefinition
The idea behind this is that I could use a third-party XSD model as the target for the ‘type’ reference. This works fine if you are using XSD models that are in the same workspace as the current model/diagram; it will result in XMI such as
<type href="my.xsd#//foo" />
However, I wanted to also provide a predefined XSD as the initial source of possible types; this would be specified as part of the plugin environment. Ideally this would be achieved through namespaces (e.g. “http://openiaml.org/model/datatypes#MyDataType”), but I don’t know how to do this yet.
I managed to get the development .xsd loaded into the ResourceSet of the current plugin with the following code (dynamic template). This just emulates Load Resource, because in GMF you cannot Load Resource with a registered package (not that .xsds are registered packages).
(XXXCreateCommand)
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
XXX newElement = ModelFactory.eINSTANCE.createXXX();
Container owner = (Container) getElementToEdit();
owner.getXXXs().add(newElement);
// custom code starts here
URI uri = URI.createPlatformPluginURI("/org.openiaml.model/model/datatypes.xsd", false);
ResourceSet set = owner.eResource().getResourceSet();
set.getResource(uri, true);
// .. continues
}
This is fine, except that the serialised models were losing the path to the absolute .xsd:
<type href="../../../../plugin/org.openiaml.model/model/datatypes.xsd#//foo"/>
After a non-insignificant amount of time, I found that by adding the OPTION_URI_HANDLER option to the save options, you can modify how absolute URIs are deresolved (which is where they were being turned into relative URIs):
(XXXDiagramEditorUtil)
public static Map getSaveOptions() {
// ...
saveOptions.put(XMLResource.OPTION_URI_HANDLER, new MyURIHandler());
// ...
}
Finally, I could implement a URIHandler that would keep platform:/plugin/ URIs absolute, but force others to be relative:
<type href="platform:/plugin/org.openiaml.model/model/datatypes.xsd#//foo"/>
In fact, there is one already defined in EMF: URIHandlerImpl.PlatformSchemeAware.
This was then implemented as part of a dynamic template.
In EMF-generated editors
If you are using EMF/genmodel to generate your editors, you will need to add the following line to XXXEditor.doSave():
saveOptions.put(XMLResource.OPTION_URI_HANDLER, new URIHandlerImpl.PlatformSchemeAware());