Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!

Jeffrey Ricker is an experienced technology development executive with 15 years of leadership in defense and the private sector. He is the principal of Jeffrey Ricker LLC, providing expertise in Eclipse, RCP and OSGi to Fortune 500 and start-up clients. Previously, he was the founder of Distributed Instruments and XML Solutions Corp. Jeffrey has posted 5 posts at DZone. You can read more from them at their website. View Full User Profile

Generics in Eclipse Modelling Framework

05.06.2008
Email
Views: 9219
  • submit to reddit

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 ModelFigure 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 GenericsFigure 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 DeclarationFigure 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

Published at DZone with permission of its author, Jeffrey Ricker.

(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

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.