Home » Modeling » EMF » How to access/set xsi:schemaLocation via API?
How to access/set xsi:schemaLocation via API? [message #1782855] |
Fri, 02 March 2018 14:20 |
Stefan John Messages: 17 Registered: March 2018 |
Junior Member |
|
|
Hi,
as the topic states I try to find a way to set the xsi:schemaLocation of EMF models when serializing them to XMI. The application for this is, that I have to save models to a common location, thereby invalidating the original schemaLocation which contains the relative path to their .ecore file.
Currently, I use:
Map<Object,Object> options = new HashMap<Object,Object>();
options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
resource.save(options)
So, generating the schemaLocation attribute is not a problem. But I can't find a way to change its content.
As a side note:
I would dislike to use a file or platform URI to directly link to the .ecore file.
Best wishes,
Stefan
|
|
| |
Re: How to access/set xsi:schemaLocation via API? [message #1783058 is a reply to message #1782963] |
Wed, 07 March 2018 10:08 |
Stefan John Messages: 17 Registered: March 2018 |
Junior Member |
|
|
Thank you for your advice so far, Ed!
Unfortunately, I did not work a lot with extensions in Eclipse, yet. So, I am not aware of how these might be used to dynamically register a meta model in the registry of a running Eclipse (which I believe would be a requisite for making use of the "http:/.." nsURIs in our use case).
I should give a bit more information about the application (MDEOptimiser, maybe you've heard of it).
Given an Eclipse project with a meta model (as .ecore), an instance (with an "http:/.." nsURI and a relative schemaLocation pointing to the .ecore) and some configuration files, the application performs a search based optimisation of the instance model. The app can be run in batch mode, i.e., multiple optimisations runs can be performed one application run.
The optimisation results (optimised instance models) are written to a separate experiments folder in the original Eclipse project, with a separate sub-folder for each run. Afterwards, the folder structure in the project will look like this:
project
--- input
--- metaModel.ecore
--- instanceModel.xmi
--- results
--- run1
--- optimisedModel.xmi
---run2
--- optimisedModel.xmi
The user should now be able to open the optimised models with the Sample Reflective Ecore Editor. Obviously, the schemaLocation of the results does not point to the meta model anymore. The "http:/.." nsURI doesn't help me either because the meta model is not loaded in the registry after the app finished.
The easiest way to allow opening of the optimised models would have been to adapt their relative schemaLocation.
If the extension solution you had in mind still fits this scenario, could you probably elaborate on this a bit more or give me a hint on how this might work?
Best wishes,
Stefan
|
|
| |
Re: How to access/set xsi:schemaLocation via API? [message #1783134 is a reply to message #1783074] |
Thu, 08 March 2018 12:14 |
Stefan John Messages: 17 Registered: March 2018 |
Junior Member |
|
|
Hi Ed,
sorry for the confusion. Upon your reply, I spent quite some time fiddling around with different ways of creating, loading, changing and saving resources and realized that I still have missed to give you necessary information.
The result models are not created from scratch by the application. If that would be the case, I could register the ecore file with the correct relative path (see code below).
In our application, the result models are generated by inplace model transformations applied to the input model. For that reason, the result models contain the same relative schemaLocation path as the input model.
In my example above, the input model would have a schemaLocation with the relative path metaModel.ecore (the meta model is in the same directory). The resulting optimised models will carry the same schemaLocation. However, in order to load them properly, the relative path should be ../../input/metaModel.ecore.
If you still see some misconceptions on my side regarding the use of EMF, feel free to shove me to the right direction.
Best wishes,
Stefan
EDIT:
The code below shows a bad way to solve the problem. Refer to attached file of my next post for a better solution and an example of the problem.
Minimal working example for creating a result model with correct relative schemaLocation:
public class Example {
public static void main(String[] args) {
ResourceSet rs = new ResourceSetImpl();
Map<String, Object> map = rs.getResourceFactoryRegistry().getExtensionToFactoryMap();
map.put("ecore", new EcoreResourceFactoryImpl());
map.put("xmi", new XMIResourceFactoryImpl());
String basePath = new File("results/run1").getAbsolutePath() + File.separatorChar;
URI baseUri = URI.createFileURI(basePath);
rs.setURIConverter(new ExtensibleURIConverterImpl() {
@Override
public URI normalize(URI uri) {
if (uri.isFile() && uri.isRelative() && baseUri!=null) {
return uri.resolve(baseUri);
} else {
return super.normalize(uri);
}
}
});
URI ecoreUri = URI.createFileURI("../../input/metaModel.ecore");
Resource r = rs.getResource(ecoreUri, true);
EPackage metamodel = (EPackage)r.getContents().get(0);
rs.getPackageRegistry().put(metamodel.getNsURI(), metamodel);
EClassifier classmodel = metamodel.getEClassifier("ClassModel");
EObject modelroot = metamodel.getEFactoryInstance().create((EClass)classmodel);
URI outputPath = URI.createFileURI("offspring.xmi");
Resource resource = rs.createResource(outputPath);
resource.getContents().clear();
resource.getContents().add(modelroot);
Map<Object,Object> options = new HashMap<Object,Object>();
options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
try {
resource.save(options);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
[Updated on: Fri, 09 March 2018 15:01] Report message to a moderator
|
|
| | | |
Re: How to access/set xsi:schemaLocation via API? [message #1783246 is a reply to message #1783146] |
Fri, 09 March 2018 14:54 |
Stefan John Messages: 17 Registered: March 2018 |
Junior Member |
|
|
Your comments made me dig deeper into the internals and code of EMF than I had planned before. This took me quite a while but I am sure the return of investment will be worth it.
Using absolute paths, for all resources really solved my problem. I wasn't aware of the fact, that EMF is able to resolve the correct relative schemaLocations in that case.
I also agree that a working example in this context should be provided as an archive. The file appended to this post contains an Eclipse project with executable classes for the discussed problem as well as two solutions to it. I deleted the file added to the last post to avoid confusion.
In my defense, I need to admit that up until now I mainly used Henshin which wraps a lot of the EMF way of creating resources. Actually, the code above is kind of a one-to-one copy of what is done in Henshin (which is a rather mature tool), so I didn't challenge it too much. I will, however, raise a follow up question on the Henshin mailing list to see whether or not action has to be taken.
To my knowledge, using the custom URIConverter shown in my last post all relative URIs will be resolved to absolute URIs before a resource is serialized/deserialized. What I did not know is that the XMLHelper (which resolves the schemaLocation) never seems to get in touch with the URIConverter.
Thanks to both of you! I highly appreciate your commitment to the forum. Nice to have such prominent people in a domain help others out.
Best wishes,
Stefan
|
|
|
Goto Forum:
Current Time: Mon Sep 23 19:19:12 GMT 2024
Powered by FUDForum. Page generated in 0.03248 seconds
|