Over a million developers have joined DZone.

Decorator Pattern in the Eclipse Modelling Framework

· Java Zone

Discover how powerful static code analysis and ergonomic design make development not only productive but also an enjoyable experience, brought to you in partnership with JetBrains

In the previous article, I discussed how to create generic classes in the Eclipse Modeling Framework (EMF). In this article, I will discuss how to use that knowledge to implement the decorator pattern in EMF. In the process, we will be pushing our knowledge of generics a little further.

In certain cases it is useful or even necessary to wrap legacy Java classes, especially Java beans, in an EMF model. For instance, you may need to display information provided by a Java remote method invocation (RMI) service. You do not have access to the source code, only the JARs.

I personally rely on EMF to handle the display of objects in EMF. Honestly, who wants to write all that code in the EMF.Edit framework? I would much rather right-click on a GENMODEL file and move on.
I have created an example of wrapping or decorating on set objects with another. In this example, we have a legacy Java interface named Aramaic. We will create an EMF model named Greek that will wrap the classes from Aramaic.
Listing 1 shows the Aramaic interfaces. I have kept this as simple as possible. The class Aleph has an attribute surname. The class Beth inherits from Aleph and adds an attribute nickname.

package com.jeffreyricker.aramaic;

public interface Aleph {
    public String getSurname();
}

public interface Beth extends Aleph {
    public String getNickname();
}

Listing 1

Let us assume that we are handed the JAR of this implementation. We would use the Eclipse plug-in wizard to transform the JAR into an OSGI bundle.
Next, we need to create our EMF model that will wrap or decorate the objects that implement the Aramaic interfaces. I want to keep this as clean as possible. The EMF interface should mirror but have no reference to the legacy interfaces.  The result is shown in Listing 2.

/** 
 * @model 
 */
public interface Alpha {

	/** 
       * @model 
       */
	public String getName();
}

/** 
 * @model
 */
public interface Beta extends Alpha {

	/**
	 * @model
	 */
	public String getNickname();

}

Listing 2 

The actual wrapping is hidden in the implementation. There is no reference to the Aramaic classes in the Greek interfaces.
We need a basic interface for the decorating. Here is where the generics begin. The Decorator interface shown in Listing 3 is very basic. The generic <D> is the class that will be wrapped by the decorator. The implementation of the interface is shown in Listing 4.

package com.jeffreyricker.greek.util;

public interface Decorator<D> {
    
     D getDecorated();
    
     void setDecorated(D decorated);

}

Listing 3
 

package com.jeffreyricker.greek.impl;

import org.eclipse.emf.ecore.impl.EObjectImpl;
import com.jeffreyricker.greek.util.Decorator;

public class DecoratorImpl<D> extends EObjectImpl implements Decorator<D>{

    private D decorated;
    
    public D getDecorated() {
        return decorated;
    }

    public void setDecorated(D decorated) {
        this.decorated = decorated;
    }

}
 

Listing 4

 

Our Greek model objects will inherit from this DecoratorImpl class. The first decorator Alpha is shown in Listing 5.

package com.jeffreyricker.greek.impl;

import com.jeffreyricker.aramaic.Aleph;
import com.jeffreyricker.greek.Alpha;

public class AlphaImpl<D extends Aleph> 
    extends DecoratorImpl<D> implements Alpha{

    public AlphaImpl(){
        super();
    }
    
    public String getName() {
        return getDecorated().getSurname();
    }

}

Listing 5

Notice the method getName makes the call getDecorated().getSurname().  Generics make this possible. The declaration <D extends Aleph> lets the parser know that the class return by getDecorated will have the getSurname method.
The class declaration may look a bit odd.

class AlphaImpl<D extends Aleph> extends DecoratorImpl<D> implements Alpha

The typical declaration one might expect is:

class AlphaImpl extends DecoratorImpl<Aleph> implements Alpha
// OKAY, BUT NO INHERITANCE

That would certainly work for this class. However, what happens when we need to inherit BetaImpl?

class BetaImpl extends AlphaImpl<Beth> implements Beta
// WRONG

If you tried this you would get an error stating quite correctly that AlphaImpl is not a generic.
You could try the following

class BetaImpl extends DecoratorImpl<Beth> implements Beta
// WRONG
It would compile, but then the following would fail.
Beta beta = new BetaImpl();
beta.getName();
// FAIL. No such method
The following also do not work. 
class AlphaImpl<D> extends DecoratorImpl<D> implements Alpha
// WRONG
class AlphaImpl<C extends D> extends DecoratorImpl<Aleph> implements Alpha
// WRONG


There are probably a dozen other declarations that you could come up with that do not work.

package com.jeffreyricker.greek.impl;

import com.jeffreyricker.aramaic.Beth;
import com.jeffreyricker.greek.Beta;

public class BetaImpl<D extends Beth> extends AlphaImpl<D> implements Beta{

    public String getNickname(){
        return this.getDecorated().getNickname();
    }

}

Listing 6

With the proper generic declarations, however, everything works as expected. Listing 6 shows the proper implementation of the Beta interface. With this declaration, we get all the methods of the parent classes. We can also continue indefinitely with more children inheritance.

From http://www.jeffreyricker.com/

Learn more about Kotlin, a new programming language designed to solve problems that software developers face every day brought to you in partnership with JetBrains.

Topics:

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 }}