Guide To EMF¶
The Eclipse Modeling Framework is amazing; but it is also hard to find useful documentation on. This page covers some of our notes as we were learning EMF and should be a good starting point.
Summary¶
A short summary on how to use EMF - the basic work flow of using EMF is as follows:
- Load an EMF model. Potential source of loading are the following:
- Annotated Java interfaces
- XML Schema
- UML model
- Optional editing of the model with the EMF model editor
- Generate code
- Customize generated code
- Repeat (after customizing model annotations you can “refresh” your model)
If the source used to load the EMF model is not annotated Java interfaces then the generated interfaces will be annotated Java interfaces and can be used at a later date to reload the model.
The methods that are generated by the EMF generator all have the javadoc annotation: @generated. This tag indicates that the method has been generated and will be regenerated in the future. The tag must be changed in order for custom changes to be made to the method. If the annotation is not changed then the changes will be lost. See How to Modify a Generated Method.
A second concern one should be aware of is that the methods that are generated also regenerate comments during each generation. See Adding Comments to EMF Generated Methods to understand how one can add comments to a generated method.
Adding Comments to EMF Generated Methods¶
How to add(an not lose) custom Java docs....
It is important to realize that comments are generated in addition to method bodies. There are two different ways to add comments to a method:
Modify or remove the @generated. If this strategy is used, remember that the method will no longer be generated and model changes will not be made to that method. See How to Modify a Generated Method
Insert comments between the
* <!-- begin-user-doc --> * <!-- end-user-doc -->
lines. Comments placed between these two lines will kept during code generation.
How to Modify a Generated Method¶
There are two ways that methods can be customized:
- Delete or modify the @generated tag. Replacing @generated with @generated NOT is the standard way. When the @generated tag is replaced or modified the method will no longer be generated by the EMF generator. The positive side of this is that customizations will not be lost. The negative side is that changes to the model must be made by hand to the method rather than generated by the EMF generator. For example, suppose that a method, setAttr, is the setter for an attribute that notifies listeners when the attribute is changed. If a modification is made to the model that indicates that the setter should not notify listeners then changes will have to be made manually rather than generated. SolutionHow to Modify a Generated Method 2 overcomes this limitation.
- The name of the generated method can changed to nameGen (Gen is added to the end of the method name) and the method is recreated manually without a @generated tag. When this strategy is used the EMF generator will generate to the method with Gen at the end and the custom implementation will be unchanged. This allows the custom implementation to call the generated implementation, thereby retaining the benefits of code generation. Using the previous example if the method is changed to no longer raise notifications the new code will replace the code in setAttrGen, rather than setAttr.
Regenerating Model¶
To regenerate a model and code the following steps should be taken:
- Right click on the .genmodel file and select Reload or select the .genmodel editor and select Reload from the Generator menu. Reloading a model recreates the model from one of the source mentioned in the Summary . If the code has been generated then regardless of what source was originally used the generated Java interfaces can be used as a source.
- Complete the wizard.
- Select the generate option desired from the editor’s context menu or from the Generate menu.
- “Generate Model Code” generates the model code only.
- “Generate Edit Code” generates code that provides adapters and editing functionality.
- “Generate Editor Code” generates the UI code for editing and viewing the model.
- “Generate All” is equivalent to running all of the previous choices.
Code generate will delete any customizations made to the code unless one of the steps in How to Modify a Generated Method is used.
Model Creation with Annotated Java¶
To create a model using annotated Java each method and class that is to be a model component must have the @model tag in its Javadocs. (If a class does not have the @model tag then none of the methods will be included in the model regardless of whether they have the @model tag.) To create an attribute provide a get method with a @model tag. The model generator will generate a setter for the attribute which will, by default, provide change notification if the attribute is changed. An attribute can be a data attribute or a reference attribute. A reference attribute is an attribute that refers to another object in the EMF model. A reference is more powerful in that it is an EMF Object so containment relationship and bi-directional relationship can be generated from the model. For example in a containment relationship an object can have only one container. The generator will generate code so that when a object is added to a container it will be removed from its previous contain automatically. There are a number of functions that the generated code can offer to reference attributes that are not possible with data attributes. Many of the standard Java types have EObject equivalents that are used automatically. For example a String attribute is by default interpreted as a EString reference attribute.
EMF Annotations¶
@model | Object | indicates this something real you want saved, not just another method |
@model type=”XXX” | List | indicates the List elements are of type XXX |
@model transient=”true” | don’t save | |
@model dataType=”org.geotools.filter.Filter” | Filter | Use of custom datatype |
@model serializable=”false” | ? | ? |
EMF Model and Generator editor¶
The EMF model and model generator are separated into one .genmodel file and a number of .ecore files. The .ecore files specify the model itself and the .genmodel file specifies how the model will be generated. Editors are provided for both .ecore files and .genmodel files. The .ecore editor allows the attribute of each class, attribute and method to be modified using the properties view. The properties view provides the list of possible options and a short tip is provided in the status line.
Tips and Tricks¶
How do save my model?
A: Saving is largely automated in EMF. Each eObject can optionally be assigned to an eResource. (eResource() obtains the resource for an object). If an object is contained by another object then the contained object will have the same eResource as the containing resource. To save the model a call to eResource.save(null) will save the EObject and all of its referenced EObjects. If the model has multiple EObjects that are not declared as being contained then each of those objects must be have been assigned to an eResource.
How do I load my model?
A: To load an EMF model, an eResource must be created that references the file containing the model. A call to eResource.load(null) will load the model. However, all references to objects saved in other files will be proxy objects until the references are accessed using a get or set method. At that time the real object will be loaded.
How can I extend a non-EMF interface?
A: According to the EMF model all supertypes of an EObject must be EObjects. However there exists a mechanism to declare normal non-EMF interfaces as EMF objects. For example, standard Java interfaces (such as comparable) can be extended. An interface can be declared to be an EClass EMF objects can be declared in the Package Interface and then can be used as a supertype.
Example in UDIG
StyleBlackboard extends IBlackboard. StyleBlackboard interface has the @model declaration and is therefore part of the EMF model. However IBlackboard is not part of the Model (does not have the @model declaration). In this situation the EMF Generator will complain that “supertype IBlackboard cannot be resolved”; this is because it is not part of the model as a EClass. To fix this error the following must be added to the Package interface:
ProjectPackage.java
/**
* @model instanceClass="org.locationtech.udig.project.IBlackboard"
*/
EClass getIBlackboard();
Once this line is part of the Package declaration IBlackboard is considered to have an EClass and the model will load and be generated correctly.