Lookup library SPI

This document describe usage of the SPI provided by the Lookup Library (for those seeking how to use lookup instance please check the API document).

By using the SPI you can create lookups that can be used by the users of the Lookup API. While the Lookup API consists of a couple of classes in the package org.openide.util.*, the SPI has its own package org.openide.util.lookup.*.

Simple lookups

Let us start with the simplest case. You have decided that your newly created object will provide an API in the form of a getLookup() method. You have to return a functional lookup from this call. You can use static methods in class Lookups to create a lookup for you. If you want only one object to be returned, just call Lookups.singleton(x) where x is the object to be returned by the lookup. Or if you want to supply more objects, use a call to the method fixed(Object []x). Note: The lookups returned from methods singleton(...) and fixed(...) do not support dynamic changes and attaching listeners. Their content is fixed from the time you call the creating method.

ProxyLookup

There can be situations where you get a lookup object from someone else and you want your lookup to return exactly the instances from the original lookup plus your own results. Here the class ProxyLookup comes into the play.

You simply create a new lookup like this:

    import org.openide.util.Lookup;
    import org.openide.util.lookup.*;

    Lookup lookup1 = ...;

    Lookup lookup2 = Lookups.singleton(MyService.class);
    return new ProxyLookup(new Lookup[] { lookup, lookup2 });

AbstractLookup

The most powerful way to provide a lookup is to directly define what instances and items it should provide, by subclassing. For this, AbstractLookup is recommended as it is easiest to use.

The simplest way to use AbstractLookup is to use its public constructor (in which case you need not subclass it). Here you provide an AbstractLookup.Content object which you have created and hold on to privately, and which keeps track of instances and permits them to be registered and deregistered. Often InstanceContent is used as the content implementation. To add something to the lookup, simply use add(Object) (and remove(Object) for the reverse). These may be called at any time and will update the set of registered instances (firing result changes as needed).

    import org.openide.util.lookup.*;
    InstanceContent ic = new InstanceContent ();
    ic.add(firstObject);
    return new AbstractLookup (ic);

In case it is expensive to actually compute the object in the lookup, but there is some cheap "key" which can easily generate it, you may instead register the key by passing in an InstanceContent.Convertor. This convertor translates the key to the real instance that the lookup client sees, if and when needed. For example, if you have a long list of class names and wish to register default instances of each class, you might actually register the class name as the key, and supply a convertor which really loads the class and instantiates it. This makes it easy to set up the lookup, but nothing is really loaded until someone asks for it.