Last updated on 2014-09-05
I am creating a new editor for the Object-Process Methodology Modeling language. Since at the same time I am learning both EMF and GEF, it seems a good opportunity to share what I learn.
This first tutorial will describe how to create an EMF model. You may ask why I am using EMF and not writing my own plain-vanilla model? there is no simple answer to this, except that EMF seems to include a large amount of build-in functionality that will reduce the time it takes me to develop the editor (although the learning curve is pretty tough), such as persistency and notifications. The tutorial was done on eclipse “Helios Service Release 2” (which you can download here) and includes EMF and GEF plugins that you can download from the platform.
Well, let’s get to work.
- The first step is to create an empty EMF project using the provided eclipse wizard:
- The second page of the wizard lets you decide the project’s name. Since this is a project for my PhD, and I am creating a model of OPM, this name seems to fit just right.
Your workspace should now contain the project, which includes a “model” directory where the EMF model files will be added.
- We now create the Ecore model. Select the “model” directory, right click and select “New->Other…” and search for “Ecore Model” in the wizard.
Clicking “Next” lets us select the name of the Ecore file, and its location. My model will be called “opm” (for obvious reasons).
Press “Finish”, there is no need for more settings. Your eclipse workbench should look something like this:
- Now comes the easy part :-). Understanding many of the nuts and bolts of defining an Ecore model that matched my requirements took me the best part of a week (maybe I’m dumb… but I’m not a liar). Since the complete OPM model is a bit complex to describe in only one tutorial (and you would get tired of reading so much), I will create a smaller “example” model which will provide us with all of the needed functionality to create the GEF editor. But enough of my mumblings, let’s get to work. Double click on the first item in the editor and the second row will show a purple square with empty text – this is the model package. Before I continue, it is important to know that most of the properties in the Ecore model are edited using the properties editor that comes with eclipse, so keep this in mind. In my case I set the package’s properties as follows:
- Name: opm
- Ns Prefix: opm
- Ns URI: http://www.vainolo.com/phd/opm
I read last week what was the exact meaning of these properties, but I kinda forgot… but these values should work for now. If I find their meaning I’ll add it to the end of the tutorial. So now my package looks like this:
- Now we have to populate the Ecore package. Ecore is kind of an OO modeling language, having classes and enums, attributes and references (and some other things which will not be used here). I will be adding 4 classes to my model:
- ObjectProcessDiagram: the diagram container where diagram elements are drawn. Also known as OPD.
- OPMObject: one of the two basic OPM “things” (if you are interested, you can read more about OPM here).
- OPMProcess: the second basic “thing” of OPM.
- OPMLink: a relation between to “things” in an OPD.
for now I will not use OO inheritance since it complicates things and for a small model it is not necessary. If (or when) my model gets larger, OPMObject and OPMProcess will probably inherit from a common OPMThing, and when more link types are added, there will probably be need for an OPMLink abstract class, but for now, this is it. So here we go. Right-click on the Ecore package and select “New Child”->”EClass” as shown below:
This adds a new entry below the package of the Ecore model. The properties of the EClass are shown in the properties view. The first class I will define is the ObjectProcessDiagram class, getting the following result:
Easy, right? now repeat 4 more times for the OPMObject, OPMProcess and OPMLink class. You should have now the following Ecore model:
- The next step is to add attributes to the EClasses. Right click on the OPMObject EClass and select “New Child”->”EAttribute”:
A new node is added below OPMObject. It should be selected and the properties view should be open to edit the attribute’s properties. You must at least set the name and the type of the property. In this example, the name of the property is “name” and its type is “EString” which denotes a java String (don’t know why they need to add new types like this, but there is probably a good reason). This is the final result:
Repeat the above procedure for OPMProcess (and you will excuse me for not adding another screenshot).
- Now comes the best part: adding the references between the EClasses. A reference is a link from one EClass to another EClass. In my mini-OPM, all OPMObjects, OPMProcess and OPMLinks are contained inside the ObjectProcessDiagram – that means that there is a reference from the OPD to these classes, and this reference is a containment reference. Furthermore, each link has a reference to a source OPMObject and a destination OPMProcess (Hey! This is not right!. An OPMLink has a source and a target OPMThing. It seems that I will have to use inheritance after all. But no problem! We are agile here, right? So just add a new EClass called OPMThing, and in the properties of OPMObject and OPMProcess, set the ESuper Types attributes to OPMThing). After the short refactoring, we can now add the references, starting with the OPD references. Right click on the ObjectProcessDiagram EClass and select “New Child”->”EReference”, as shown below:
The reference is added as a child to the OPD, just like the attributes. But check out the properties view because it has changed. The most important properties to fill are the Name, EType (no need to explain what these are), EOpposite (if this reference can be accessed from the other side of the relation, this is the EOpposite), Containment (If the created instances should be stored as part of this object or only as references. This is specially important for serialization purposes), Lower and Upper bounds (minimum and maximum references. Maximum can be -1 which is unlimited). In this example, the following values were changed
- Name: objects
- EType: OPMObject
- Containment: true
- Upper Bound: -1
The EOpposite reference cannot be set since this is the first reference defined in the model. It will be set later after the opposite reference is defined. This is how things should look like:
Adding the processes and links references should now be fairly easy even for me :-). Don’t forget to set containment=true.
Now for the other references. OPMObject, OPMProcess and OPMLink should reference the ObjectProcessDiagram that contains them, and OPMLinks should reference two OPMThings (which in turn reference many OPMLinks). Most of the work is very repetitive so I will only show one more example of reference creation. Right click on the OPMObject and create a new reference. This reference will be named opd, and will reference an ObjectProcessDiagram EClass. Now that we have both sides of a relation (the OPD EClass also references OPMObject), we can set the EOpposite property, on which the editor kindly provides us with all matching references of the selected EClass to this EClass, in this case, the objects reference:
Notice that since OPMObject is contained in ObjectProcessDiagram, after you select the EOpposite reference the Container property of the reference from OPMObject to ObjectProcessDiagram changes to true. While not very important, this is nice.
Now add all remaining references (OPMProcess->ObjectProcessDiagram, OPMLink->ObjectProcessDiagram, OPMthing<->OPMLink). The final model should look something like this:
And that’s all for today. Now I understand why people don’t write long and detailed tutorials… but it is definitely time well spent. How you enjoy it. On the next chapter of “Creating a GEF editor” (which will be much shorter), we will create an EMF Generator Model to generate code from the model we just did.
Oh, and another thing: if you want to learn some more EMF, Lars Vogel has a nice tutorial that uses the EMF graphical modeling tool (which is nice but a bit overkill for my current needs).
Next Tutorial: Creating a GEF Editor – Part 2: EMF Code Generation
thanks for the detailed explanation.
it was very helpful for me.
n your sense of humor is excellent.
Here I am again – now on this tutorial. Hope you are having progress with the studies. I have one little question:
Is there any practical use of ObjectProcessDiagram to have attribute ‘links’? I have noticed no use so far and I am wondering if it is something for future use?
Also, this only gave me a problem of displaying an extra link in the top left corner. I have added links from the ObjectProcessDiagram to the getModelChildren() method of OPMObjectProcessDiagramEditPart class, which I thought is only natural. Now I know that root element is not in charge of links, but rather elements which are connected by those links.
Hi Bojan. I decided to model all links as being contained in the OPM, and not as contained in either the source or the target, and this is why the OPD has an attribute ‘links’. I did this because all objects in an EMF model need to be contained somewhere and instead of setting arbitrarily that links are contained in the source or in the target, they are contained in the OPD. Links should only exist between OPM things (objects and processes). The OPMObjectProcessEditPart is the ‘canvas’ of the editor and the links are created by the element contained in the editor (objects and processes).
Hope this answers your question.
Could you please tell me how to install GEF? I try to do it but i have a bug and i could not fix it.
Please search Google or StackOverflow on this topic. I will happily answer int this site questions regarding my tutorials. Good luck.
If I create a view to modify the EMF model, how do I sync with the model. “genmodel” .. my problem is that modify the properties of an element. “genmodel” .. and I was not updated in the view you create …
I’m not sure if this is what you are asking, but if you modified the EMF model, you can reload it in the genmodel editor with a right-click on the root of the genmodel editor, and selecting “reload”