The Eclipse Modelling Framework (EMF) supports model-driven engineering by providing a simple object-oriented modelling language for modelling data, a code generator for producing corresponding Java classes, and tools and runtime support for building views and editors for the data.
When building data-oriented application, you will find that some code is obviously specific for the domain, some is domain-specific but following coding patterns that make the coding pretty trivial and some is completely generic. For instance, suppose you are writing a form-based application for personell data. This will include
- writing classes for OrgUnit, Person and Role and providing get, set, add and remove methods for accessing and mutator the structure of OrgUnit, Person and Role instances
- implementing validation for attributes like name (no digits or special characters) and date of birth (no employee is 200 years old), as well as structural validation, e.g. every OrgUnit must have a Person with a manager Role
- ensuring consistency, e.g. that if a Person belongs to an OrgUnit, both objects refer to each other, and if a Person is removed from an OrgUnit, none of them refer to the other
- supporting the UI by making the domain objects observable, i.e. provide a mechanism to listen for changes
- selecting form elements based on attribute types and multiplicity
- triggering appropriate validation during editing
- persisting the data, perhaps in a file using XML or JSON format, or in a database
The accessor and mutator methods are trivial, once you know the attribute and association names and multiplicities. The validation code is domain specific, but how it is used by the UI isn't. Consistency of such opposite relations is difficult to code, but always follow the same patterns. Observability is trivial usage of coding patterns. Form element selection is rule-based, with a few options pr. type. Serializing (saving) and parsing (loading) data is a systematic and well-understood process.
We see that only part of the code is domain-specific, but it will be entangled with other code. When writing code by hand, you combine domain-specific and knowledge of coding conventions and patterns. The idea behind EMF, and model-driven development in general, is to separate the domain knowledge from the coding knowledge. The domain knowledge is captured in a domain model, while the coding knowledge (conventions, patterns, architecture, ...) is part of the framework and tools, using a combination of code generation and generic and so-called reflective code. EMF and related projects supports the following out-of-the-box:
- generate classes with accessor and mutator methods
- prevents creation of illegal or inconsistent object structures
- a validation mechanism that report which standard and custom constraints have been violated
- generic serialisation of domain data, using various popular formats
- generic and custom editors for your domain data
This relieves the developer from a lot of tedious work, but requires strong modelling skills and an understanding of how the framework utilises the model. Once mastered, it provides opportunities for developing with greater agility, efficiency and quality.
Ecore - EMF's modelling language
The core of EMF is an object-oriented modelling language called Ecore, and a supporting runtime. Ecore can be thought of as a subset of UML class diagrams (without the graphical notation), that is big enough to support basic domain modelling and small enough to allow for an efficient and lean framework. Ecore supports classes with attributes (properties of simple types), associations (references to other modelled classes) and operations, and multiple inheritance.
For more, see our Ecore page.
Ecore models may be edited using different tools and syntaxes. EMF itself provides a tree-based editor and an XML-based format (mostly for serialisation e.g. to files), EMFJSON provides a JSON format, Ecore tools (based on Sirius) provides a diagram notation and Xcore a textual syntax similar to Java classes. However, all support the same abstract language of classes, attributes, associations, operations and inheritance and any Ecore-supporting tool may use the resulting Ecore model.
For more, see our page on Editing Ecore models.
A plethora of other tools and frameworks utilise Ecore models to provide important and time-saving functionality, either part of the Eclipse Modelling project or the surrounding eco-system.
Genmodel - generating Java code
To turn an Ecore model into executable Java code, you need to configure a generator model called genmodel and run EMF's code generator. A default genmodel is provided automatically, so the only thing you normally need to do is name the Java package (prefix) of the generated Java classes. The generator may generate Java classes corresponding directly to the Ecore classes, like OrgUnit and Person. If your Ecore classes include operations, you will need to add custom code to the generated classes (methods stubs).
In addition to domain classes, you may generate an Eclipse-based editor for your model, which you can install into Eclipse to make it easier to edit your domain data.
For more, see our Genmodel page.
Validation - checking your domain data
An Ecore model will to a certain extent constrain the structure of domain objects you can create, e.g. based on the multiplicity of attributes and association. However, not all such constraints are considered hard in the sense that they are enforced by the generated classes. E.g. if an attribute's multiplicity has a lower bound of two, it will always be possible to add only one value. Instead, you may ask EMF to validate your model, and a set of diagnostic objects will tell which (if any) constraints are violated. You may add your own custom validation rules, e.g. to limit the range of integer values or characters in a String, or ensure more structural constraints are met, like an OrgUnit always having a Person with a manager Role. The generated editor will automatically use the validation mechanism to indicate violated constraints, so you can avoid illegal domain data.
For more, see our Validation page.
Persistance - storing your data
Being able to store domain data is fundamental to any application, and there are many choices for persisting Ecore-based data. EMF provides XML-based persistance of any legal structure of domain objects to file, and other projects supports other formats, e.g. EMFJSON supports JSON, and ESON a more human-friendly JSON-like syntax. There are lots of ways of tweaking the XML format used by default, or customise how the generated code handles persistance, e.g. switch to JSON or a completely custom format. In the latter case, you can implement the serialiser and parser by hand or use DSL frameworks like Xtext and EMFText to generate them from a grammar.
For more, see our Serialization page.
If you prefer persisting to a database, Teneo supports mapping Ecore models to database tables and relations (so-called Object-Relation Mapping (ORM)) using Hibernate. The CDO project also supports several relational databases. If you prefer NoSQL storage, EMFJSON supports the increasingly popular MongoDB.
Editing your data - generic and custom editors
Although you can generate a complete editor for you domain data, you will find it cumbersome to have to regenerate and reinstall it, to create and edit domain data, e.g. to provide sample data for testing. Instead you may use a so-called reflective editor, which provides generic editing support for any Ecore model without code generation. You just indicate for which model you want to create and edit data, and the editor will let you create domain objects, edit their attribute values and assemble them into object structures within the constraints of your model. This allows you to test your model immediately without generating code, e.g. instantiate domain object corresponding to a scenario and use it as initial state for test cases.
If you choose to use the generated editor as a basis for your own, custom editor, you typically will want to provide support for undo and redo. Both the generic and generated editors have primitive set/unset and add/remove operations with undo/redo support that work for any model. You can also implement custom, domain-specific operations and still have EMF handle undo and redo for you, by recording how your domain objects changes. Validation is integrated, so you can alert the user if an operation results in an invalid state.
While the editor support provided by EMF will give you functionally complete editors, they are not usable/suitable for most end-users. Better editors can of course be developed by hand, but several frameworks allow you to make good editors without a lot of coding. The EMF Forms project allows you to build a custom, form-based GUI for your domain data without coding. Instead you compose your form from layouts and editing widgets and configure how they operate on the underlying domain data. The EMF Client Platform (ECP) provides a more complete (and complex) application development framework based on the same ideas. If you prefer a diagram notation for your data, combined with some form support, or advanced tables, you can use the Sirius framework.
For more, see our page on Editing Ecore model instances.