Home » Modeling » TMF (Xtext) » Efficiently getting EObjects of a particular type given only their parent Xtext+Sirius IProject
Efficiently getting EObjects of a particular type given only their parent Xtext+Sirius IProject [message #1859616] |
Tue, 20 June 2023 12:32 |
Matt Windsor Messages: 13 Registered: July 2022 |
Junior Member |
|
|
Hi all,
I'm working on a plugin that, as part of its feature set, needs to correlate data stored in EMF/Xtext modelling projects (on a language I'll call Bar here; Bar is an Xtext DSL with a Sirius6 representation) with data stored outside of the modelling workflow but still associated with the same Eclipse project. This means that, for instance, I need to get a list of all EObjects of type Foo from outside of any context where I already have a Resource or EObject; all I seem to have is the IProject. (I've seen a lot of people asking how to query EMF through an IProject, but they all seem to be trying to generate something; I don't think this use case is answered by generation?)
So far, I have Java17 code similar to this, where I'm using the internal textual-UI injector of language Bar to get myself the Xtext resource set provider, using that to get a resource set, and then... manually scraping through the files of the project to see if any look like they contain Bar models and feeding them into the resource set before I do an EMF query:
public class FooFinder {
private List<Foo> _result;
private ResourceSet _resourceSet;
public Result find(IProject project) throws CoreException, IOException {
_result = new ArrayList<>();
getResources(project);
fetchFoo();
return _result;
}
private void getResources(IProject project) throws CoreException, IOException {
if (project == null) {
return;
}
getResourceSet(project);
processContainer(project);
}
private void getResourceSet(IProject project) {
var inj = BarActivator.getInstance().getInjector(BarActivator.LANGUAGE_ID);
var prov = inj.getInstance(IResourceSetProvider.class);
_resourceSet = prov.get(project);
}
private void processContainer(IContainer container) throws CoreException, IOException {
for (var member : container.members()) {
if (member instanceof IContainer c) {
processContainer(c);
} else if (member instanceof IFile f) {
processFile(f);
}
}
}
private void processFile(IFile file) throws IOException {
if (!isBarFile(file)) {
return;
}
var uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
_resourceSet.getResource(uri, true);
}
private boolean isBarFile(IFile file) {
return file.getFileExtension().equals("bar"); // there is probably a better way of checking this
}
private void fetchFoo() {
for (var res : _resourceSet.getResources()) {
_result.addAll(EcoreUtil2.typeSelect(EcoreUtil2.eAllContentsAsList(res), Foo.class));
}
}
}
This works inasmuch as it retrieves the correct model data, but:
- it seems unidiomatic, and liable to be manually performing tasks that something in Xtext or Sirius should be taking care of;
- I've been advised that it is probably performing redundant loading and validation activities;
- this is especially true given that the Bar language has a Sirius view that will almost certainly be open when this query is run, and will likely already have some or all of the resources available;
- if I do this, how do I write back any changes I want to make to the models programmatically, given I've mostly abandoned any of the Xtext infrastructure on the way to getting these models?
Thanks,
~ Matt
[Updated on: Tue, 20 June 2023 12:39] Report message to a moderator
|
|
| |
Re: Efficiently getting EObjects of a particular type given only their parent Xtext+Sirius IProject [message #1859618 is a reply to message #1859617] |
Tue, 20 June 2023 14:00 |
Matt Windsor Messages: 13 Registered: July 2022 |
Junior Member |
|
|
Thanks for the reply!
I'd be performing queries based on matching them up with data from a database, for instance 'list all Foo such that there exists a Foobar in the database that references this Foo', then displaying the results to the user in various Eclipse/SWT views/dialogs, more specifically:
- the call to perform the query is coming from a Command from within the eclipse3 API stack (eg a button or menu item in some view), and isn't initiated by any action on the model;
- the database is exposed as an Eclipse service, which might make it visible at the Xtext side;
- I have access to the IProject, but not directly to the EObjects, Resources, or ResourceSets;
- there is a graphical view of part of the model available through Sirius, which I could try call into to try get to the EMF model, but not all of the things that I want to do will involve Sirius so that feels strange.
I expected I'd need to do the query at the Command level by pulling Foo out of the EMF model, transforming it into a form that can be sent to the database, then performing the query. If it's easier to somehow invoke a generator with a handle to the database, get it to generate the results of the query, then either scrape the generated files back into something I can present to the user (or just point the user to the generated files), I could look into that, though I'd prefer the workflow to be as in-Eclipse as possible.
|
|
| | | | |
Re: Efficiently getting EObjects of a particular type given only their parent Xtext+Sirius IProject [message #1859645 is a reply to message #1859625] |
Wed, 21 June 2023 08:35 |
Matt Windsor Messages: 13 Registered: July 2022 |
Junior Member |
|
|
Ok, sorry for the mangled message earlier. I tried writing a reply on my phone and only a small part of it saved.
Ed Willink wrote on Tue, 20 June 2023 16:37
This is not necessarily true. You have access to the current selection which via a derived ISelection will reference directly or indirectly an EObject from which you can navigate up to the ResourceSet and down to all the Foo's.
The plugin structure is perhaps unusual (and inherited, so I'm unsure how easily I can change it): the plugin that is going to be doing the querying isn't an Xtext editor, but instead it has a couple of bespoke views that are IProject-aware but only concerned with displaying and manipulating the database. There is also the Sirius viewpoint over the EMF/Xtext model, but the Xtext editor itself isn't likely to get used and I can't rely on it being visible.
The flow of data from the database end to the EMF/Xtext end is a little awkward: when the user creates Foo representations in Sirius, the plugin for the Sirius viewpoint calls Commands in the database plugin which create the database representation of a Foo, then scrapes the results to use when constructing the EMF representation of a Foo (so both ends get separate representations of the same data; one EMF, one POJO). Right now, there is no flow of EMF data into the database plugin -- I'd have presumed this means I can't rely on selections as these would usually just pick up the POJO version not the EMF version?
Since the EMF/Xtext end is aware of the database end, there might be a way of getting it to supply some handle to part of the model, but again I'm unsure how to do this.
Thanks!
|
|
| | | | |
Goto Forum:
Current Time: Mon Oct 07 20:43:52 GMT 2024
Powered by FUDForum. Page generated in 0.04362 seconds
|