Preparations
Install Eclipse 3.5 (Galileo) with all the modelling tools, that is the Galileo Eclipse Modeling Tools package. Additionally, we will need the OCL interpreter console, which can be installed using the MDT update site:http://download.eclipse.org/modeling/mdt/updates/releases/
The OCL console actually is an example, so you will have to install that specific example.
The Runtime Example
Let's assume a small IT company. The employees of that company develop software for other companies. Of course, they use models for that purpose! In order to better organize their work, they want to document who is working on what. That is, they want to assign certain task to developers. A task could be the implementation of a use case or writing a test case for a class. Let's see if we can use models for that...Company Model with EMF
First of all, we have to create a model describing the company. Let's start from scratch:- create a new project:
File / New / Project... / Eclipse Modeling Framework /Empty EMF project - create a new ecore diagram (we want to graphically design the model) in the newly created model folder: Right click on model folder and select
New / Other... / Ecore Tools / Ecore Diagram - enter the Domain file name::
company.ecore
and press Finish.
- The model is an instance of the ecore model, which is quite similar to class models in UML. All elements in ecore start with an "E", so it is EClass, EAttribute, or EString.
- The EType of the attribute
name
is EString. - The upper bound of all references is "*" (you can enter "-1", which actually is the same as "*").
- You will need a class containing all your elements later. In the example, the
Company
serves as a container. Make sure the Is Containment flag is set for the two referencesemployees
andskills
(see Fig. 1)
Company
class. There is a generic editor available, which can create an instance of a model (or its elements) directly without the need of code generation. All you need is the ecore model. This is how to activate it:- Close the ecore diagram
- Open the ecore model, this time use the Sample Ecore Model Editor. Usually, this editor is used if you double-click the ecore-file, but to be sure use the Open With... context menu entry.
- Select the
Company
class (the class, not the package!), and select Create Dynamic Instance... from its context menu. This is shown in Figure 2. - enter the File name:
Company.xmi
and press Finish. The instance will be created in the model folder. - edit the model instance using the context menus New Child of the elements in the model.
- edit the elements properties in the properties section of the editor, see Figure 3.
- Activate the console view and open the Interactive OCL console with the button on the left of the console, see Figure 4.
- Select an element in the editor, This selected element is the context of the OCL query.
- Enter your OCL query in the console (in the lower section of the OCL interpreter console). E.g. query the name of the selected element with
self.name
. The result will be displayed in the upper section of the OCL console as shown in Figure 5. We will demonstrate other queries later on.
Task Model with Xtext
Now that we have a model of our company, we want to assign tasks to the employees. We could create a new ecore model just as demonstrated above, but we want to try something new. So, let's try to not only create a model, but a text editor as well. For that, we will use Xtext. Based on a grammar, Xtext can create an ecore model and a text editor with nice features. The grammar is an annotated EBNF grammar, I do not want to go into the details here (otherwise it wouldn't be a q'n d-tutorial ;-) ). So, we have to create a new project and enter a grammar:- Create a new Xtext project:
File / New / Project... / Xtext /Xtext Project - SetMain project name, the Language name (to
de.feu.Tasks
), and the DSL-File extension (totasks
). - Open
Tasks.xtext
(this is the EBNF-like grammar) and enter your grammar according to Figure 6. Here is the grammer (for copy & paste):This grammar defines a container elementgrammar de.feu.Tasks with org.eclipse.xtext.common.Terminals import "http://www.eclipse.org/emf/2002/Ecore" as ecore import "platform:/resource/de.feu.company/model/company.ecore" as company generate tasks "http://www.feu.de/Tasks" Tasks : (developers+=Developers)* (domainmodels+=DomainModels)* (tasks+=Task)*; Developers : 'developer' importURI=STRING; DomainModels : 'domainmodel' importURI=STRING; Task: 'task' element=[ecore::EObject] 'by' developer=[company::Developer] ':' description=STRING;
Tasks
. Inside, we can "load" a list of developers and domain models. Eventually, tasks can be defined by assigning an element from a domain model (seeelement=[ecore::EObject]
) to a developer (developer=[company::Developer]
) and add a description of that task. - Save the gammar and generate the ecore model along with the text editor using the MWE-workflow. For that, select file
GenerateTasks.mwe
and run the workflow via its context menu Run As / MWE Workflow
- In Xtext, a model is called a DSL. Experts like to use different names for "model", sometimes it's cooler to call a model "meta-model" (or, even cooler, "meta-meta-model"), sometimes they call it "domain specific language", abbreviated with a nice TLA (three letter acronym): DSL. Of course, there are good (and sometimes not so good) reasons for doing so, but usually it's easier to simply call a model a model (and an "instance of a model" an "instance of a model") .
- The grammar shown in Figure 6 actually uses a lot of nice Xtext features and you will have to read the Xtext documentation for details. I only want to explain one thing here, which is a little bit advanced. You can import existing models into the grammar (
import ...
). In the example, we import the ecore model and our previously created company model. We import these models in order to be able to define inter-model references later on. OurTask
element will refer to anelement
, which can be anyecore::EObject
, and thedeveloper
is to one developer defined in our company model (company::Developer
). EMF supports inter-model-references, and Xtext generated editors support that feature as well! Theimport
statements in our grammar only import the models, but later on we want to actually import existing model instances. For that, we need theimportURI
feature of Xtext to define what instance to import in our actual task model instance.
- Select the
company.ecore
file and choose New / Other... / Eclipse Modeling Framework / EMF Generator Model from its context menu. Use the suggested file name, select Ecore Model in the next wizard page. Then, press Load in the next page, and eventually Finish on the last wizard page. This creates a generator model, which basically adds some information to the original ecore model which is necessary in order to actually generate code (e.g., the name of the plugins and so on). We do not want to change anything here, but we still need that model. - In that model, select the very first element (
Company
) and select Generate All from its context menu (see Figure 7).
Work with Multiple Models
Now that we have generate a lot of code, we want to use the newly created tools. Start a new Eclipse runtime instance (e.g. by selecting Run As / Eclipse Application from a project context menu) and do the following:- Create a new project (in the runtime instance):
File / New / Project... / General /Project - Select the project and choose from its context menu:
New / Other... / Example EMF Model Creation Wizard / Company Model
This activates our previously generated editor (and a wizard) for creating a company model instance. We can edit a company instance just as we did it with the generic editor. In the wizard, select the Model ObjectCompany
and then create a new company as shown in Figure 8. (Don't forget to save the model ;-) ). - Now, create a new file (File / New / File) inside the project and call it
project.tasks
. The Xtext generated editor is opened automatically and we can now edit the task model instance. - In order to "simulate" a project, we create a simple UML use case model. Simply create a new use case diagram via File / New / Other... / UML 2.1 Diagrams / Use Case Diagram, give it a name (e.g.
project_usecase
) and draw some use cases, a sample is shown in Figure 9. - Switch back to
project.tasks
and "import" our company model and the sample use cases. Add a task using content assist (Ctrl-Space) just as shown in Figure 10. Just play around, add three or four tasks in order to be able to follow the next steps. - Just as at the beginning, we want to execute some OCL queries on our model, but this time on our
project.task
model instance. For OCL, we always need a context, but unfortunately we cannot select a context (or model element) in the text editor. So we have to reopen theproject.task
with the generic EMF editor: Choose from its context menu Open With / Other... / Generic EMF Form Editor. You will now see the very same model as in the text editor, but this time you see a tree-based version of the model. - Open the OCL console just as above, select an element (here
Tasks
) and enter a query. For example, we want to know how much tasks are assigned to a specific developer:self.tasks->select(developer.name='Jens')->size()
. You can see that in Figure 11
Conclusion
IMHO it is impressing what you can do with all these cool Eclipse modelling tools, without writing a single line of (Java) code. We saw how to- create an EMF ecore model with the Ecore Tools diagram editor
- open the same ecore model with the Generic EMF Form Editor
- create instances of a model without the need to generate code and without starting a new runtime instance, using the "Create Dynamic Instance" feature (and the generic EMF editor again)
- generate a text editor and a model without a single line of Java code with Xtext
- generate a tree based editor and a Java based model implementation with EMF
- create a UML diagram with the UML Tools diagram editor
- query your models with OCL from the OCL project
Warning: Thin Ice!
While it is very easy to do impressive things (with the help of a tutorial), it is very hard to get into all these frameworks and tools. There are a lot of traps hidden everywhere! Just two examples from the tutorial:- In the Xtext grammar we used here, the ecore model was imported (see Fig. 6). I tried the very same using the UML2 model, and I got a weird error when generating the code (actually I couldn't generate in that case).
- A NullPointer-Exception is thrown (you can see that in the console of the original Eclipse instance) when opening the
project.tasks
file with the Generic EMF Form Editor. Fortunately it still is possible to select an element (for the OCL query), but it's a little bit weird.