Adapters

In my last installment, I showed how—by making a domain class implement IPropertySource and (naturally) implementing the methods required by that interface—you can expose properties from a domain class that can be viewed and modified by the Properties view. In that posting, I suggested that implementing IPropertySource introduces a tight coupling between the model and view and hinted that such a tight coupling was a bad thing.

Tight coupling is bad because it tends to make things less flexible. Sure, we can look at the properties of our domain object, but what happens when we want to participate in other interactions? Do we just implement another interface? And another? Tight coupling makes reuse harder as well. Tightly coupling our domain class with the IPropertySource interface makes it so that our domain class can’t exist without that interface (and all the other types packaged along with it, plus those bits referenced by all those types, …).

Eclipse provides an adapter framework that can be used to solve this problem by decoupling the domain class from the view-specific code required to make the Properties view work.

The first step is to remove the IPropertySource behaviour from the domain class:

...
public class Person implements IAdaptable {
	private String name;
	private Object street;
	private Object city;

	public Person(String name) {
		this.name = name;
		this.street = "";
		this.city = "";
	}

	public Object getAdapter(Class adapter) {
		if (adapter == IPropertySource.class) return new PersonPropertySource(this);
		return null;
	}

	// Getter and setter methods follow...
	...
}

We move the IPropertySource behaviour to the PersonPropertySource class:

...
public class PersonPropertySource implements IPropertySource {
	private final Person person;

	public PersonPropertySource(Person person) {
		this.person = person;
	}

	public Object getEditableValue() {
		return this;
	}

	public IPropertyDescriptor[] getPropertyDescriptors() {
		return new IPropertyDescriptor[] {
				new TextPropertyDescriptor("name", "Name"),
				new TextPropertyDescriptor("street", "Street"),
				new TextPropertyDescriptor("city", "City")
		};
	}

	public Object getPropertyValue(Object id) {
		if ("name".equals(id)) return person.getName();
		else if ("street".equals(id)) return person.getStreet();
		else if ("city".equals(id)) return person.getCity();
		return null;
	}

	public boolean isPropertySet(Object id) {
		return false;
	}

	public void resetPropertyValue(Object id) {
	}

	public void setPropertyValue(Object id, Object value) {
		if ("name".equals(id)) person.setName((String)value);
		else if ("street".equals(id)) person.setStreet((String)value);
		else if ("city".equals(id)) person.setCity((String)value);
	}

}

The Property view goes through a few steps to sort out how it’s going to display properties. First, it determines whether or not the selected object implements the IPropertySource interface. If it does (as it did in my previous entry), it uses the selected object directly (after casting it to IPropertySource). If that check fails, the Property view then determines whether or not the selected object implements the IAdaptable interface (highlighted in the Person class). If the selected object is adaptable, it is asked—via the getAdapter method—for an adapter with the IPropertySource type. The getAdapter method either returns an object of the appropriate type or null. If the method returns an adapter, it is used by the Property view to gather properties. Our implementation of adapter fits this bill and so is used.

The astute reader will notice that this really doesn’t do very much to actually weaken the coupling between the domain class an IPropertySource. In fact, the coupling is just as strong. Even worse, we’ve actually introduced a tight coupling to another type (IAdaptable). We’ll fix this problem in the next installment…

This entry was posted in Eclipse 101. Bookmark the permalink.

6 Responses to Adapters

  1. Prakash G.R. says:

    Good one.

    I’ve seen many Eclipse developers not having a clear understanding of the Adapters and the worst, there is no articles on this (at least I’ve not seen). Once this series is completed you can post it in the eclipse.org/articles page. Will be helpful to many people because not everyone follows blogs🙂

  2. Trace Windham says:

    Thanks Wayne,

    This is just the kind of article we need out here in the wild. I’ve been working on RCP applications for a little over a year now, and a lot of my Eclipse RCP knowledge comes from “poking around” in the Eclipse code. Its easy to figure out what the code is doing when you look at, but its a little harder to figure out why its doing it without these kind of explanations.

    Thanks again, and keep up the great work.

    Thanks Alex for the link to the article. The eclipse corner articles page is probably one of my most clicked bookmarks in my browser. They are very helpful. http://www.eclipse.org/articles/index.php

  3. Tom Seidel says:

    The use of adapters with the PropertyPage is the most used example to explain Adapters and IMHO a very bad example. As I read the first time this example (it’s also explained in the “JDG2E”) I thought, “ok, to show up properties in a property-page I have to use an adapter”, but the intention of adapters became secondary.

    A very good example is IMHO the IWorkbenchAdapter. It becomes clear that you have the possibility to adapt an object to a presentation within the workbench. These presentations are shared through the workbench, that means you can implement e.g. 20 TreeViewers without providing a LabelProvider/ContentProvider; you don’t have to take care of object-representation. This scenario is more comprehensible (you have a better comparison –> with/without adapters).

  4. Pingback: Eclipse hints, tips, and random musings » Blog Archive » Adapters, part deux

  5. Pingback: Adapting with generics « Rambling about…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s