かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

ちょっと戻ってLookup

Lookupの結果に変化があったら処理をするってことが出来るみたいだ。
LookupListenerを使うといいぞと書いてある。

早速お試し。
Lookupなので、普通のJavaアプリにorg-openide-util.jarを追加すればOK。
まずは、自分で任意のLookupを追加出来るMyLookupを作る。
これは、ProxyLookupの持ってるprotectedメソッドのsetLookupsを使って実現してる。

class MyLookup extends ProxyLookup {
    public MyLookup(Lookup... lookups) {
        super(lookups);
    }
    
    public void addLookups(Lookup... lookups) {
        List<Lookup> list = new ArrayList<Lookup>();
        Collections.addAll(list, super.getLookups());
        Collections.addAll(list, lookups);
        super.setLookups(list.toArray(new Lookup[0]));
    }
}

LookupListenerだけど、これはLookup.Resultに対して追加できる。
Lookup.ResultはLookup.lookup(Lookup.Template template)メソッドで取得する。
コード的にはこんな感じ。

Lookup.Template<String> template = new Lookup.Template(String.class);
Lookup.Result<String> results = someLookup.lookup(template);

// 全インスタンスの入ったコレクションを取得
Collections<? extends String> col = results.allInstance();

このLookup.ResultにaddLookupListenerをしてやる。
コード的にはこんな感じになる。

package okazuki.lookuplistener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.openide.util.Lookup;
import org.openide.util.lookup.ProxyLookup;
import org.openide.util.lookup.Lookups;
import org.openide.util.LookupListener;
import org.openide.util.LookupEvent;

public class Main {
    
    public static void main(String[] args) {
        MyLookup proxy = new MyLookup(Lookups.singleton("Hello"));
        Lookup.Template<String> template = new Lookup.Template(String.class);
        final Lookup.Result<String> results = proxy.lookup(template);
        results.addLookupListener(new LookupListener(){
            public void resultChanged(LookupEvent e) {
                print(results.allInstances());
            }
        });
        // なぜか一度はLookup.ResultからLookupの結果を取得しないと駄目らしい
        // この行をコメントアウトすると、resultChangedが発生しない
        print(results.allInstances());
        
        proxy.addLookups(Lookups.singleton("world")); // String型が追加されたのでresultChangedが発生
        proxy.addLookups(Lookups.singleton(1)); // ここではresultChangedが
        proxy.addLookups(Lookups.singleton(3)); // 発生しないよ!
        
    }
    
    private static void print(Collection<? extends String> strings) {
        for (String str : strings) {
            System.out.print(str);
            System.out.print(" ");
        }
        System.out.println();
    }
}

これを実行すると、こうなる。

Hello 
Hello world 

String型の何かが追加されたときのみ、resultChangedイベントが発生しているのがわかる。
これを使うと、ウィンドウが開いたときに監視対象のLookup.Resultを取得してリスナを追加する。
変更があるたびに表示を更新する。
ウィンドウが閉じられたときにリスナを消す。

こんな処理が可能になる。
本を見る限り一般的にガンガン使う方法みたいだ。