Adapters

Some very astute readers may noticed a problem with the previous sections on views and popup/context menus. In the view section that described the Accounts view they may have noticed that the Accounts view is displaying a list of Account objects, that is, objects that implement the org.jledger.model.IAccount interface. Further more, these objects were obtained from a remote object store and immediately added to the view widget's model. The view also set the widget's selection provider to the site's selection provider.
The thing to realize here is that the objects provided by the view's associated selection provider will be those very same org.jledger.model.IAccount objects that came from the remote object store.
The other thing to realize is that in the popup menu section that the

The point is that the objects added to the Accounts view do not already implement the IOpenable interaface. These objects came from a remote object store that should have no reason to know anything about IOpenable and would have no reason to return objects to a client that implemented IOpenable. Yet, when one of these objects is selected the workbench obviously thinks that an IOpenable object is selected. How did that happen?

The answer is that an adapter was defined by the org.jledger.ui plugin that added an implementation of the IOpenable interface to all IAccount accounts. JLense includes a facility for dynamically extending objects to provide different interfaces (or "adapters"). Adapters are created by adapter factories, which are in turn managed by type by adapter managers. See the IAdapterManager class for more details.

To add the IOpenable interface to all IAccount objects the org.jledger.ui plugin registered an adapter factory with the Platform Adapter Manager when the plugin was started. Here is the code from the JLedger UI plugin that does that:

public class JLedgerWorkbenchPlugin extends AbstractUIPlugin
{

    public void startup() throws CoreException
    {
        registerAdapters();
    }

    /**
     * Registers adapter factories for various object types.
     * Adapters are typically used to enable various workbench actions, like the
     * Open action for instance.
     */
    public void registerAdapters()
    {
        IAdapterManager manager = Platform.getAdapterManager();
        IAdapterFactory factory = new JLedgerWorkbenchAdapterFactory();
        manager.registerAdapters(factory, IAccount.class);
    }

}

Here is the code for the JLedgerWorkbenchAdapterFactory. The JLedgerWorkbenchAdapterFactory is responsible for creating adpapter instances for IAccount objects:

public class JLedgerWorkbenchAdapterFactory
implements IAdapterFactory
{
    public Object getAdapter(Object o, Class adapterType) {
        if (adapterType.isInstance(o)) {
            return o;
        }
        if (adapterType == IOpenable.class) {
            return getOpenable(o);
        }
        return null;
    }

    public Class[] getAdapterList() {
        return new Class[] {
            IOpenable.class
        };
    }

    IOpenable getOpenable(final Object adaptable) {
        IOpenable adapter= null;
        if (adaptable instanceof IAccount) {
            adapter= new DefaultOpenableAdapter(
                "org.jledger.ui.accounts.OpenWizard",
                false /*not modal, open in window*/,
                (IAdaptable)adaptable);
        }
        return adapter;
    }
}