Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Storing EClass in a Hashmap, loading package from a file vs. from memory
Storing EClass in a Hashmap, loading package from a file vs. from memory [message #421124] Sat, 26 July 2008 13:05 Go to next message
Thomas Rheker is currently offline Thomas RhekerFriend
Messages: 8
Registered: July 2009
Junior Member
Hi,

i have a similar problem as addressed in
news://news.eclipse.org:119/enmkp5$i3p$1@utils.eclipse.org.

I want to transform an emf model to a gxl graph. To handle duplicate
class names in subpackagages I construct a HashMap<EClass, String>
storing which EClass corresponds to which String. Normally, the String
is just EClass.getName().
Now I have the problem that the EClass of an Object in the model does
not exactly correspond to that of the same EClass stored in the Hashmap,
so it returns null. This is probably a problem of how I load the
resource storing my model instance as opposed to the EPackage. I used to
load the meta model EPackage explicitly from the .ecore and it worked,
but now I load it using EPackage.Registry.INSTANCE.getEPackage(nsUri);

Some code fragments below.

How I load the model resource:
resource = EMFRESOURCESET.getResource(fileURI, true);

Where EMFRESOURCESET was constructed like that:

static ResourceSet createEmfResourceSet() {
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap()
.put("ecore", new EcoreResourceFactoryImpl());
resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap()
.put(Resource.Factory.Registry.DEFAULT_EXTENSION, new
XMIResourceFactoryImpl());
return resourceSet;
}

How I used to load the EPackage:

public static Resource loadEcoreResourceFromFile(String pathToFile) {
File file = new File(pathToFile);
if (!file.exists())
System.out.println("No file!");
URI fileURI = URI.createFileURI(file.getAbsolutePath());
Resource resource;
resource = null;
try {
resource = EMFRESOURCESET.getResource(fileURI, true);
} catch (Exception e) {
e.printStackTrace();
}
EPackage ecorePackage = (EPackage) resource.getContents().get(0);
EMFRESOURCESET.getPackageRegistry().put(ecorePackage.getNsUR I(),
ecorePackage);
return resource;
}

And then
EPackage ecorePackage = (EPackage) ecoreResource.getContents().get(0);


How I get the EPackage now:
EObject model = emfInstance.getContents().get(0);
String nsUri = model.eClass().getEPackage().getNsURI();
EPackage ecorePackage2 = EPackage.Registry.INSTANCE.getEPackage(nsUri);

I then iterate through the classes in the package using
TreeIterator<EObject> iter = ePackage.eAllContents();

And add any EClasses found to my Hashmap:
if (eObject.getClass().getName() ==
"org.eclipse.emf.ecore.impl.EClassImpl") { EClass eClass = (EClass)
eObject;
classNameMap.put(eClass, eClass.getName());


Something seems to be wrong here too, because there are also different
classes in the Hashmap when I loaded the EPackage differently. In both
cases one is missing, but not the same one.

Any help is welcome, I would be happy to at least understand why my
program does not work.

Greetings,
Thomas
Re: Storing EClass in a Hashmap, loading package from a file vs. from memory [message #421127 is a reply to message #421124] Sun, 27 July 2008 16:21 Go to previous messageGo to next message
Marcelo Paternostro is currently offline Marcelo PaternostroFriend
Messages: 602
Registered: July 2009
Senior Member
Hi Thomas,

Let me see if I can help ;-)

In EMF, you can see the ResourceSet as the context in which a given
EObject is uniquely represented in memory. In other words, if there is
a file containing eObjects (with, for example, books of the Library
model or eClasses from Ecore), each object in such a file is loaded once
and only once in the context of a ResourceSet. On the other hand, I can
have 2+ representations of such objects in memory if I load them via
different resource sets, without any resource set at all (doing
something like new XMLResourceImpl(URI).load()), or if I create them
"dynamically" executing a piece of Java code.

With that in mind, it is easy to understand what is going on. When you
loaded an ePackage from its serialized form, EMFRESOURCESET has its own
"in memory" representation of the eClasses. The global package
registry, on the other hand, was probably populated by the init() method
located in the generated package impl (which is executed the first time
you access the eINSTANCE constant available in the ePackage interface).
So the eClass object representing Node in 'classNameMap' is not "==" to
the one representing Node in the package registry.

Perhaps you will get better results by using a specific approach to
compute the key of the map. Something like the code below (it may
require some small tweaks to handle nested EPackages)

public static void main(String[] args)
{
//Create map
Map<URI, String> classNameMap = new HashMap<URI, String>();

//Load the EPackage from code and registers it to the global registry
<GeneratedPackage>.eINSTANCE.getClass();

// Creates the ResourceSet
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap().put(
"ecore", new EcoreResourceFactoryImpl());
resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap().put(
Resource.Factory.Registry.DEFAULT_EXTENSION, new
XMIResourceFactoryImpl());

// Load a ePackage from a file
URI fileURI = URI.createFileURI("C:\\yourecorefile\\model.ecore");
Resource resource = resourceSet.getResource(fileURI, true);
EPackage loadedEPackage = (EPackage)resource.getContents().get(0);

// Populates the map using the instances loaded from the ecore file
for (Iterator<EObject> i = loadedEPackage.eAllContents(); i.hasNext();)
{
EObject loadedEObject = i.next();
if (loadedEObject instanceof EClass)
{
EClass loadedEClass = (EClass)loadedEObject;
classNameMap.put(getClassURI(loadedEClass), loadedEClass.getName());
}
}

// Traversing the registered ePackage
EPackage registeredEPackage =
EPackage.Registry.INSTANCE.getEPackage(loadedEPackage.getNsU RI());
for (Iterator<EObject> i = registeredEPackage.eAllContents();
i.hasNext();)
{
EObject registeredEObject = i.next();
if (registeredEObject instanceof EClass)
{
String className =
classNameMap.get(getClassURI((EClass)registeredEObject));
if (className != null)
System.out.println("Found an eClass: " + className);
}
}

System.out.println("Done");
}

private static URI getClassURI(EClass eClass)
{
return
URI.createURI(eClass.getEPackage().getNsURI()).appendFragmen t(eClass.getName());
}


Cheers,
Marcelo



Thomas Rheker wrote:
> Hi,
>
> i have a similar problem as addressed in
> news://news.eclipse.org:119/enmkp5$i3p$1@utils.eclipse.org.
>
> I want to transform an emf model to a gxl graph. To handle duplicate
> class names in subpackagages I construct a HashMap<EClass, String>
> storing which EClass corresponds to which String. Normally, the String
> is just EClass.getName().
> Now I have the problem that the EClass of an Object in the model does
> not exactly correspond to that of the same EClass stored in the Hashmap,
> so it returns null. This is probably a problem of how I load the
> resource storing my model instance as opposed to the EPackage. I used to
> load the meta model EPackage explicitly from the .ecore and it worked,
> but now I load it using EPackage.Registry.INSTANCE.getEPackage(nsUri);
>
> Some code fragments below.
>
> How I load the model resource:
> resource = EMFRESOURCESET.getResource(fileURI, true);
>
> Where EMFRESOURCESET was constructed like that:
>
> static ResourceSet createEmfResourceSet() {
> ResourceSet resourceSet = new ResourceSetImpl();
> resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap()
> .put("ecore", new EcoreResourceFactoryImpl());
> resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap()
> .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new
> XMIResourceFactoryImpl());
> return resourceSet;
> }
>
> How I used to load the EPackage:
>
> public static Resource loadEcoreResourceFromFile(String pathToFile) {
> File file = new File(pathToFile);
> if (!file.exists())
> System.out.println("No file!");
> URI fileURI = URI.createFileURI(file.getAbsolutePath());
> Resource resource;
> resource = null;
> try {
> resource = EMFRESOURCESET.getResource(fileURI, true);
> } catch (Exception e) {
> e.printStackTrace();
> }
> EPackage ecorePackage = (EPackage) resource.getContents().get(0);
> EMFRESOURCESET.getPackageRegistry().put(ecorePackage.getNsUR I(),
> ecorePackage);
> return resource;
> }
>
> And then
> EPackage ecorePackage = (EPackage) ecoreResource.getContents().get(0);
>
>
> How I get the EPackage now:
> EObject model = emfInstance.getContents().get(0);
> String nsUri = model.eClass().getEPackage().getNsURI();
> EPackage ecorePackage2 = EPackage.Registry.INSTANCE.getEPackage(nsUri);
>
> I then iterate through the classes in the package using
> TreeIterator<EObject> iter = ePackage.eAllContents();
>
> And add any EClasses found to my Hashmap:
> if (eObject.getClass().getName() ==
> "org.eclipse.emf.ecore.impl.EClassImpl") { EClass eClass = (EClass)
> eObject;
> classNameMap.put(eClass, eClass.getName());
>
>
> Something seems to be wrong here too, because there are also different
> classes in the Hashmap when I loaded the EPackage differently. In both
> cases one is missing, but not the same one.
>
> Any help is welcome, I would be happy to at least understand why my
> program does not work.
>
> Greetings,
> Thomas
>
Re: Storing EClass in a Hashmap, loading package from a file vs. from memory [message #421147 is a reply to message #421127] Mon, 28 July 2008 15:53 Go to previous messageGo to next message
Thomas Rheker is currently offline Thomas RhekerFriend
Messages: 8
Registered: July 2009
Junior Member
Hi Marcelo,

thank you, your approach seems to work. I do not want to use the
..ecore-File at all, that was my real problem. My program has to run
generically for any meta model, though I can assume that the EPackage is
known at runtime.
What I now need to do is using the same (bidirectional) Hashmap to get
the EClass from the String in the map. How can I get the EClass from the
package using the ClassURI?

Greetings,
Thomas
Re: Storing EClass in a Hashmap, loading package from a file vs. from memory [message #421152 is a reply to message #421147] Mon, 28 July 2008 22:03 Go to previous message
Marcelo Paternostro is currently offline Marcelo PaternostroFriend
Messages: 602
Registered: July 2009
Senior Member
Hi Thomas,

Because you know that the format of the ClassURI is
<epackageNSURI>#<className>, you can do something like this:

URI classURI = getClassURI(...);
EPackage ePackage =
EPackage.Registry.INSTANCE.getEPackage(classURI.trimFragment ().toString());
if (ePackage != null)
System.out.println(ePackage.getEClassifier(classURI.fragment ()));

Cheers,
Marcelo

Thomas Rheker wrote:
> Hi Marcelo,
>
> thank you, your approach seems to work. I do not want to use the
> ..ecore-File at all, that was my real problem. My program has to run
> generically for any meta model, though I can assume that the EPackage is
> known at runtime.
> What I now need to do is using the same (bidirectional) Hashmap to get
> the EClass from the String in the map. How can I get the EClass from the
> package using the ClassURI?
>
> Greetings,
> Thomas
>
Previous Topic:[Teneo] Cascade delete problem
Next Topic:Persisting an EMF model in a non-EMF persistance model
Goto Forum:
  


Current Time: Fri Apr 26 20:38:40 GMT 2024

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

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

Back to the top