RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Discover the Eclipse Modeling Framework (EMF) and Its Dynamic Capabilities : Page 2

Given a model, EMF can generate Java source code that will allow you to create, query, update, serialize, deserialize, validate, and track changes to instances of your models. EMF provides an efficient reflective API and allows you to work with dynamic, non-generated, models.

Using Dynamic EMF Capabilities
In general, if you have models at development time, it is typically best to generate Java code because in this case your application will use less memory and provide faster access to data (using either the generated or the reflective API). While generating Java code serves a need for most applications, this might not always be the case. You might need to process data without requiring the availability of generated implementation classes. For example, you might not know at development time the model of the data you will be processing, making generated Java code a poor option.

Dynamic, i.e., non-generated, classes can be created at runtime in several ways. Let's start by creating a company model programmatically using the Ecore API. The company model describes a company that has a name and departments. Each department is identified by a number and has employees. Each employee has a name. The code below shows an Ecore metamodel that corresponds to this model.

EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
EcorePackage ecorePackage = EcorePackage.eINSTANCE;

// create an Company class
EClass companyClass = ecoreFactory.createEClass();

// create company name
EAttribute companyName = ecoreFactory.createEAttribute();

//create an Employee class
EClass employeeClass = ecoreFactory.createEClass();

//add a name attribute to an Employee class
EAttribute employeeName = ecoreFactory.createEAttribute();

//create a Department class
EClass departmentClass = ecoreFactory.createEClass();

//add department identification number
EAttribute departmentNumber = ecoreFactory.createEAttribute();

//department class can contain reference to one or many employees
EReference departmentEmployees = ecoreFactory.createEReference();

// specify that it could be one or more employees

// company can contain reference to one or more departments
EReference companyDepartments = ecoreFactory.createEReference();

//create a package that represents company
EPackage companyPackage = ecoreFactory.createEPackage();

Using the reflective API you can create and initialize an instance of your model:

// get company factory
EFactory companyFactory = companyPackage.getEFactoryInstance();

// using the factory create instance of company class and 
// set company name
EObject company = companyFactory.create(companyClass);
company.eSet(companyName, "MyCompany");

// create an instance of employee class
EObject employee = companyFactory.create(employeeClass);
//using reflective API initialize name of employee
employee.eSet(employeeName, "John");

// create an instance of department class
EObject department = companyFactory.create(departmentClass);
department.eSet(departmentNumber, new Integer(123));
//add "John" to department
// add the department to the company

Serializing and Deserializing Data
To serialize your model instances, you need to put a root object of your instance model into a resource. The EMF org.eclipse.emf.ecore.resource.Resource interface represents a physical storage location (such as file or URL) and provides methods to serialize and load data. Each resource is stored in a ResourceSet, which represents a collection of resources that have been created and loaded together, allowing for references among them. In particular, a ResourceSet keeps track of which resources have been loaded and makes sure that no resource in a ResourceSet is loaded twice.

Because EMF is capable of dealing with multiple model sources, e.g., XML Schema, it is also important to specify which resource implementation should be used for (de)serializing your data. Normally, when you invoke the ResourceSet.createResource(URI) method, it queries the Resource.Factory.Registry to look up a factory that is registered for that URI and uses it to create an appropriate resource implementation. Therefore, before you (de)serialize your data ensure that you register the appropriate resource factory implementation. EMF provides several Resource.Factory implementations:

  • For XML data use org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl.
  • For XMI data use org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl.
  • For Ecore models use org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl.
With these EMF resources in your toolbox, you can use this code to serialize your data:

// create resource set and resource 
ResourceSet resourceSet = new ResourceSetImpl();

// Register XML resource factory
new XMIResourceFactoryImpl());

Resource resource = resourceSet.createResource(URI.createFileURI("c:/temp/company.xmi"));
// add the root object to the resource
// serialize resource – you can specify also serialization
// options which defined on org.eclipse.emf.ecore.xmi.XMIResource
The serialized form of the company.xmi is:

<?xml version="1.0" encoding="ASCII"?>
<company:Company xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:company="http:///com.example.company.ecore" name="MyCompany">
  <department number="123">
    <employees name="John"/>
During deserialization, the namespace URIs of XML data are used to locate the required Ecore packages (which describe the model for your instance documents). Therefore, before you attempt to load any model, ensure that you register the namespace URI for each Ecore package your documents will be using:

// register package in local resource registry
resourceSet.getPackageRegistry().put(companyPackage.getNsURI(), companyPackage);
// load resource 
It is also important to notice the difference between local and global package (EPackage.Registry.INSTANCE) and resource factory (Resource.Factory.Registry.INSTANCE) registries. The global registry is static and therefore any application during lifetime of JVM can access the global registry and possibly overwrite it. To ensure that your registrations do not overwrite global registrations and vice versa, it is typically better to use local resource set registry.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date