Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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 21:08 Go to next message
Vinny Vallarine is currently offline Vinny VallarineFriend
Messages: 9
Registered: June 2012
Junior Member
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 #892110 is a reply to message #892025] Wed, 27 June 2012 06:52 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30679
Registered: July 2009
Senior Member
Vinny,

If you load a resource into a resource set and use EcoreUtil.resolveAll,
at the end, the resource set will be populated with all resources that
can be transitively reached.

On 26/06/2012 11:08 PM, Vinny Vallarine wrote:
> 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 #892201 is a reply to message #892110] Wed, 27 June 2012 11:53 Go to previous messageGo to next message
Vinny Vallarine is currently offline Vinny VallarineFriend
Messages: 9
Registered: June 2012
Junior Member
But I still need to traverse through to get to each file, correct?

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?


/**
* Recursive method that will traverse down an EObjects containment and/or
* non containment objects and add all the EObject's URI file paths to the
* file name list this class is managing.
*
* NOTE: !!!This method is recursive!!!
*
* @param object
* The EObject root node starting point
*/
private void addContentFiles(final EObject object){

if (object != null) {

//recurse for all of this object's containment references
for (EObject containedRefs : object.eContents()) {
this.addContentFiles(containedRefs, monitor);
}

//recurse for all of this object's containment references
for (EObject nonContainedRefs : object.eCrossReferences()) {
this.addContentFiles(nonContainedRefs, monitor);
}

String fileName = null;
if (object.eIsProxy() && (object instanceof InternalEObject)) {
fileName = ((InternalEObject) object).eProxyURI().toFileString();
} else {
if ((object.eResource() != null) && (object.eResource().getURI() != null)) {
fileName = object.eResource().getURI().toFileString();
}
}

if (fileName != null) {
//WE FOUND A NEW FILE, ADD IT TO OUR LIST FOR USE LATER
myRunningFileList.add(fileName);
}
}
}
Re: Collecting XMI files backing an entire EMF Model [message #892244 is a reply to message #892201] Wed, 27 June 2012 13:34 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30679
Registered: July 2009
Senior Member
<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() &amp;&amp; (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) &amp;&amp;
(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 #892253 is a reply to message #892244] Wed, 27 June 2012 13:58 Go to previous messageGo to next message
Vinny Vallarine is currently offline Vinny VallarineFriend
Messages: 9
Registered: June 2012
Junior Member
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"?
2. Can I avoid, all together, calling eCrossReferences()? I figured I had to get at all the non contained references?

Re: Collecting XMI files backing an entire EMF Model [message #892265 is a reply to message #892253] Wed, 27 June 2012 14:24 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30679
Registered: July 2009
Senior Member
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 #892291 is a reply to message #892265] Wed, 27 June 2012 15:46 Go to previous messageGo to next message
Vinny Vallarine is currently offline Vinny VallarineFriend
Messages: 9
Registered: June 2012
Junior Member
Yes, I'd need to hit everything. Any glaring problems you see here (objectsAlreadyVisited is a HashSet):


public void addAllContentFiles(EObject eObject, IProgressMonitor monitor) throws InterruptedException {

final TreeIterator<EObject> iter = eObject.eAllContents();
while (iter.hasNext()) {

EObject nextEObject = (EObject) iter.next();
if (!this.objectsAlreadyVisited.add(nextEObject)) {
continue;
}

//SAVE THE FILE THAT BACKS THIS OBJECT
this.saveFile(nextEObject);

for (EContentsEList.FeatureIterator featureIterator = (EContentsEList.FeatureIterator) nextEObject.eCrossReferences().iterator(); featureIterator.hasNext()Wink {
EObject innerEObject = (EObject) featureIterator.next();
if (!this.objectsAlreadyVisited.add(innerEObject)) {
continue;
} else {
this.addAllContentFiles(innerEObject, monitor);
}
}
}
}
Re: Collecting XMI files backing an entire EMF Model [message #892325 is a reply to message #892291] Wed, 27 June 2012 17:47 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30679
Registered: July 2009
Senior Member
Vinny,

Comments below.

On 27/06/2012 5:46 PM, Vinny Vallarine wrote:
> Yes, I'd need to hit everything. Any glaring problems you see here
> (objectsAlreadyVisited is a HashSet):
>
>
> public void addAllContentFiles(EObject eObject, IProgressMonitor
> monitor) throws InterruptedException {
>
> final TreeIterator<EObject> iter = eObject.eAllContents();
> while (iter.hasNext()) {
>
> EObject nextEObject = (EObject) iter.next();
> if (!this.objectsAlreadyVisited.add(nextEObject)) {
> continue;
In this case, you probably want to call TreeIterator.prune so you don't
iterate over the whole subtree pointlessly.
> }
> //SAVE THE FILE THAT BACKS THIS OBJECT
> this.saveFile(nextEObject);
>
> for (EContentsEList.FeatureIterator featureIterator =
> (EContentsEList.FeatureIterator)
> nextEObject.eCrossReferences().iterator(); featureIterator.hasNext();) {
You don't make any use of the fact that this is a feature iterator so
you might as well iterate over eCrosssReferences with a for-each loop.
> EObject innerEObject = (EObject) featureIterator.next();
> if (!this.objectsAlreadyVisited.add(innerEObject)) {
> continue;
Hmmm... Wouldn't it be easier to guard the whole method once?
> } else {
> this.addAllContentFiles(innerEObject, monitor);
> }
> }
> }
> }
>
Re: Collecting XMI files backing an entire EMF Model [message #892552 is a reply to message #892325] Thu, 28 June 2012 15:31 Go to previous messageGo to next message
Vinny Vallarine is currently offline Vinny VallarineFriend
Messages: 9
Registered: June 2012
Junior Member
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);

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

PS: I know this has turned into a mini code review but it is helping, and I do appreciate it.

Re: Collecting XMI files backing an entire EMF Model [message #892599 is a reply to message #892552] Thu, 28 June 2012 16:50 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 30679
Registered: July 2009
Senior Member
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.
>
Previous Topic:my EMF model generated tests...
Next Topic:Design ideas for multiple editors/single resource
Goto Forum:
  


Current Time: Thu Dec 05 18:31:05 GMT 2019

Powered by FUDForum. Page generated in 0.02401 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top