Generics in Eclipse Modelling Framework
Java introduced the power of generics in version 1.5. Generics make many common tasks in programming not only simple but elegant. The most notable instance is the task of iterating lists. Prior to Java 1.5, one had to type cast a list in iteration as shown in Listing 1.
List fruits = new ArrayList();
…
for (int i =0; i < fruits.size(); i++) {
Fruit fruit = (Fruit) fruits.get(i);
…
}
Listing 1
With generics, iterating through the list is far less cumbersome. Equivalent code is shown in Listing 2.
List<Fruit> fruits = new ArrayList<Fruit>();
…
for (Fruit fruit : fruits) {
…
}
Listing 2
In this article, we do not have the space and time to delve into the full background of Java generics. There are some good references available on line such as the tutorial by Gilad Bracha. We will instead focus on how to implement generics in the Eclipse Modeling Framework (EMF).
For our first example, we will use a trivial model of fruit and fruit baskets. Figure 1 shows the basic model in the Ecore editor. The objects Fruit and Basket are abstract. The Basket class has an attribute contents which provides a list of Fruit objects.
Figure 1: Basic Ecore Model
We would like to enforce that AppleBasket only contains Apple objects. Before generics, we would have two choices, neither of them preferable. First, we could overwrite the contents method on the AppleBasket to check that the Fruit object was an Apple. Second, we could create a method named getApples on the AppleBasket. Both approaches compromise the advantages and reusability of the interfaces in our object-oriented design.
To add generics to our Ecore model, we must turn on the “Show Generics” option. You will find this on the “Sample Ecore Editor” menu
Figure 2: Enabling Ecore for Generics
Now you will notice that the context menu in the editor (right click) has more choices.
We will add the generic to our Basket class. Right-click on the Basket class and select “New Child::Etype Parameter”. In the properties view, give the parameter a simple name like “F”. Such is the naming convention of Java generics. Select the contents attribute and change its EType to F. Figure 3 shows the results. Notice that the model will display “contents: F” but the properties will display “EObject.”
Figure 3: Initial Generics Declaration
If we generate our EMF code from the model, we will see the following in the Basket interface.
public interface Basket<F> extends EObject {
public EList<F> getContents();
}Listing 3
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)




Comments
afdsf afees replied on Wed, 2009/03/11 - 11:52am
But anyway the EclipseLink looks great, StoredProc and Converter are what I want to see in the next JPA
regards,
Term Paper
Greg Dorval replied on Tue, 2010/03/30 - 1:49am
Hi Jeffery. Very good article. However after working with this for a while and noticing that the default generated editor lets me add Oranges to Apple Baskets and vice versa I dug a little deeper into the code. It seems that when the code is generated it parameterizes the EList properly but in the get function, when it creates the new EList, it passes the base class as the dataClass parameter, which it uses to define the type of internal storage array for the list. This means that there is no code, not from java.*, org.eclipse.* or org.eclipse.emf.*, nor from any of the generated model code that would prevent adding an Orange to an Apple Basket.
(Note: I added a superclass above fruit called Food, which is the base class in my model - I wanted to see how you would pass generics along multiple levels of superclasses)
public EList<F> getFood() {
if (food == null) {
food = new EObjectContainmentEList<F>(Food.class, this, FoodPackage.FOOD_BASKET__FOOD);
}
return food;
}
I've overriden this generated method so that the dataClass parameter will be the interface for the actual type of F at runtime. I implemented a helper utility based on the article on Reflecting Generics (http://www.artima.com/weblogs/viewpost.jsp?thread=208860) and then I set the actual type class to a class variable when the Food() constructor is called. Now getFood() looks like this and the CommandStack catches a runtime error if an inappropriate object is attempted to be added. It then simply disposes of the command.
public EList<F> getFood() {
if (food == null) {
food = new EObjectContainmentEList<F>(typeClass, this, FoodPackage.FOOD_BASKET__FOOD);
}
return food;
}
Piter Noize replied on Thu, 2011/09/29 - 1:28am
in response to: crazzy
eclipse is my favourite IDE
term paper