Home » Modeling » EMF » Collecting XMI files backing an entire EMF Model
Collecting XMI files backing an entire EMF Model [message #892025] |
Tue, 26 June 2012 17:08  |
Eclipse User |
|
|
|
I need a sanity check. I have a large EMF model that is backed by an XMI (file) implementation. I have a simple classes that, given the root node, walks the entire model tree and collect the XMI files that back those objects.
I'm looking for the fastest way to do this. My implementation seems way too slow. Instead of posting my solution, I'm looking for examples as to how anyone would do this. My only requirement is that I collect EVERY XMI file that makes up my model.
Thanks in advance,
Vinny
|
|
| | |
Re: Collecting XMI files backing an entire EMF Model [message #892244 is a reply to message #892201] |
Wed, 27 June 2012 09:34   |
Eclipse User |
|
|
|
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
Vinny,<br>
<br>
Comments below.<br>
<br>
<div class="moz-cite-prefix">On 27/06/2012 1:53 PM, Vinny Vallarine
wrote:<br>
</div>
<blockquote cite="mid:jses8c$gjv$1@xxxxxxxxe.org" type="cite">But
I still need to traverse through to get to each file, correct? <br>
</blockquote>
Yes, you need to visit all reachable objects.<br>
<blockquote cite="mid:jses8c$gjv$1@xxxxxxxxe.org" type="cite">Below
is my current implementation. It works 100% of the time but I
think I have extra looping and/or wasted processing going on. I'm
just not sure where. I'd appreciate a quick look. Again, this
"lookup" needs to follow all possible paths from the top level
node, both containment and non-containment. So, in summary, is
this logic the most efficient way to build a list of files that
back my entire EMF model?
<br>
<br>
<br>
/**
<br>
* Recursive method that will traverse down an EObjects containment
and/or
<br>
* non containment objects and add all the EObject's URI file paths
to the
<br>
* file name list this class is managing.
<br>
* * NOTE: !!!This method is recursive!!!
<br>
* * @param object
<br>
* The EObject root node starting point
<br>
*/
<br>
private void addContentFiles(final EObject object){
<br>
<br>
if (object != null) {
<br>
<br>
//recurse for all of this object's containment references
<br>
for (EObject containedRefs : object.eContents()) {
<br>
this.addContentFiles(containedRefs, monitor);
<br>
}
<br>
</blockquote>
If you used eAllContents, you could avoid the need for recursion.<br>
<blockquote cite="mid:jses8c$gjv$1@xxxxxxxxe.org" type="cite">
<br>
//recurse for all of this object's containment references
<br>
for (EObject nonContainedRefs : object.eCrossReferences())
{
<br>
this.addContentFiles(nonContainedRefs, monitor);
<br>
}
<br>
</blockquote>
You might want a content tree many times this way.<br>
<blockquote cite="mid:jses8c$gjv$1@xxxxxxxxe.org" type="cite">
<br>
String fileName = null;
<br>
if (object.eIsProxy() && (object instanceof
InternalEObject)) {
<br>
</blockquote>
There's no need for the second guard. All EObjects <b>must </b>implement
InternalEObject.<br>
<blockquote cite="mid:jses8c$gjv$1@xxxxxxxxe.org" type="cite">
fileName = ((InternalEObject) object).eProxyURI().toFileString();
<br>
</blockquote>
It's not generally good to assume it's a file: URI; maybe that's
okay in your case.<br>
<blockquote cite="mid:jses8c$gjv$1@xxxxxxxxe.org" type="cite">
} else {
<br>
if ((object.eResource() != null) &&
(object.eResource().getURI() != null)) {
<br>
fileName =
object.eResource().getURI().toFileString();
<br>
}
<br>
}
<br>
<br>
if (fileName != null) {
<br>
//WE FOUND A NEW FILE, ADD IT TO OUR LIST FOR USE LATER
<br>
myRunningFileList.add(fileName);
<br>
} }
<br>
}
<br>
</blockquote>
I'm not sure the significance of starting with a specific object.
In general an EObject might have an eContainer(); wouldn't you want
to visit that? Did you look at what EcoreUtil.resolveAll does for a
resource set? Assuming you start with a single object in your
resource set, that method will yield a resource set containing all
reachable resources.<br>
<br>
Failing that, you'd be better to add a guard so that you don't visit
the same object more than once. I.e., a set of visited objects and
only if add returns true do you visit it.<br>
<br>
</body>
</html>
|
|
| |
Re: Collecting XMI files backing an entire EMF Model [message #892265 is a reply to message #892253] |
Wed, 27 June 2012 10:24   |
Eclipse User |
|
|
|
Vinny,
Comments below.
On 27/06/2012 3:58 PM, Vinny Vallarine wrote:
> We've implemented an "Export" feature which, among other things,
> creates a file archive of the XMI files that back the EMF model. The
> significance of starting with a specific object is that the user can
> 'export' at any level of our model hierarchy. If the model hierarchy,
> e.g., looks like A contains B contains C refers to D, the user could
> export at "B" so I'd have to pull in the backing files for object B, C
> and D.
> Couple more questions: 1. What did you mean by "You might want a
> content tree many times this way"?
Sorry I mean "walk" not "want".
> 2. Can I avoid, all together, calling eCrossReferences()? I figured I
> had to get at all the non contained references?
No, you'd want to know about D, so you just visit cross references. But
you might visit D more than once, in general, and you walk the whole
content tree below D so all that extra visiting could be expensive.
What if D is contained by E? Wouldn't you need to visit E as well given
that E might reference F which could be in another resource you'd not
reach otherwise?
>
>
|
|
| | | |
Re: Collecting XMI files backing an entire EMF Model [message #892599 is a reply to message #892552] |
Thu, 28 June 2012 12:50  |
Eclipse User |
|
|
|
Vinny,
Comments below.
On 28/06/2012 5:31 PM, Vinny Vallarine wrote:
> I think I can simplify via:
>
> public void addAllContentFiles(EObject eObject,
> IProgressMonitor monitor) throws
> InterruptedException {
>
>
> if (!this.objectsAlreadyVisited.add(eObject)) {
> return;
> }
>
> //SAVE THE FILE THAT BACKS THIS OBJECT
> this.saveFile(eObject);
Presumably you're making sure to collect all the resources so you only
save each resource once...
>
> for (EObject containedObject : eObject.eContents()) {
> this.addAllContentFiles(containedObject, monitor);
> }
>
> for (EObject innerEObject : eObject.eCrossReferences()) {
> this.addAllContentFiles(innerEObject, monitor); //????
> }
> }
>
> My questions: 1. Any obvious missteps?
> 2. Do I need to recursively call myself for each crossReference? Note
> the "????" in the code
You'd not save referenced resources without this recursive call, right?
And you want to save resources referenced from this cross reference's
resource too, presumably, right?
>
> PS: I know this has turned into a mini code review but it is helping,
> and I do appreciate it.
>
|
|
|
Goto Forum:
Current Time: Thu Jul 17 06:55:29 EDT 2025
Powered by FUDForum. Page generated in 0.70590 seconds
|