Over a million developers have joined DZone.

Generics in Eclipse Modelling Framework

· Java Zone

Check out this 8-step guide to see how you can increase your productivity by skipping slow application redeploys and by implementing application profiling, as you code! Brought to you in partnership with ZeroTurnaround.

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.

[img_assist|nid=2766|title=Figure 1: Basic Ecore Model|desc=|link=none|align=undefined|width=407|height=216]

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

 

[img_assist|nid=2767|title=Figure 2: Enabling Ecore for Generics|desc=|link=none|align=undefined|width=497|height=281]

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.”

[img_assist|nid=2768|title=Figure 3: Initial Generics Declaration|desc=|link=none|align=undefined|width=485|height=367]

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

We want to enforce that F is a type of Fruit. In the Ecore editor, select the EType Parameter child of the Basket element. Choose “New Child::EGeneric Bound Type”. In the properties view, set the EClassifier attribute to Fruit. Now the name of the class should display “Basket<F extends Fruit>”.

[img_assist|nid=2769|title=Figure 4: Setting the generic bound type|desc=|link=none|align=undefined|width=439|height=326]

Now we need to inherit this power in our basket objects. Expand the children of the  AppleBasket class. You will see an inheritance of Basket. Right click on theinheritance child, Basket, and choose from the context menu “New Child::EGeneric Type Argument”.  If you select on AppleBasket you will not see this menu selection.

[img_assist|nid=2770|title=Figure 5: Selecting the EGeneric Type Argument menu|desc=|link=none|align=undefined|width=590|height=112]

In the properties view, set the EClassifier to Apple. Repeat for OrangeBasket. You should have what appears in Figure 6.

[img_assist|nid=2771|title=Figure 6: Generic type argument on inheritance|desc=|link=none|align=undefined|width=426|height=285]

When you generate the model code, you should see interfaces that look like Listing 4.

public interface Basket<F extends Fruit> extends EObject {
  public EList<F> getContents();
}

public interface AppleBasket extends Basket<Apple> {
}

Listing 4

With the generics in place, you can now be as specific or as general in your model programming as you like. We have enforced that AppleBasket objects can only contain Apple objects. At the same time, we have enabled the access the contents of all FruitBasket objects as Fruit. Listing 5 shows an example of using the model.

AppleBasket appleBasket = FruitFactory.eINSTANCE.createAppleBasket();
…
for (Apple apple : appleBasket.getContents()){
…
}
List<FruitBasket> baskets;
…
baskets.add(appleBasket);
for (FruitBasket basket: baskets){
  for (Fruit fruit: basket.getContents){
    …
  }
}

Listing 5


 

The Java Zone is brought to you in partnership with ZeroTurnaround. Check out this 8-step guide to see how you can increase your productivity by skipping slow application redeploys and by implementing application profiling, as you code!

Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}