Top / Eclipse / プラグイン開発のTIPS集 / org.eclipse.core.runtime.IAdaptable(cont.)

さて、Eclipse/プラグイン開発のTIPS集/org.eclipse.core.runtime.IAdaptable の続きです。 さっきのように、ContactクラスがPlatformObject?を拡張している場合は、

org.eclipse.core.runtime.IAdaptable インタフェース
org.eclipse.core.runtime.PlatformObject オブジェクト
org.eclipse.core.runtime.IAdapterFactory ファクトリ

を使ってViewに表示ができました。今度はModelオブジェクトがIAdaptableやPlatformObject?を実装していない場合はどうするか、です。。通常このような場合が多いですよね。モデルをEclipse依存にしたくないですしね。

モデル

モデルは先のクラス構成で、ContactがPlatformObject?を拡張していない、一般的なクラスであると仮定します。

model.png

org.eclipse.core.runtime.adapters拡張ポイント

こたえはやはりorg.eclipse.core.runtime.adapters拡張ポイントみたいです。

<extension point="org.eclipse.core.runtime.adapters">
  <factory
     adaptableType="org.eclipsercp.hyperbola.model.Contact"
     class="org.eclipsercp.hyperbola.model.HyperbolaAdapterFactory">
    <adapter type="org.eclipse.ui.model.IWorkbenchAdapter"/>
  </factory>
</extension>

このように定義しておくと、Contactのインスタンスelementに対して、

Platform.getAdapterManager().loadAdapter
   (element,  IWorkbenchAdapter.class.getName());
     ↑adaptableType     ↑<adapter type="org.eclipse.ui.model.IWorkbenchAdapter"/>

というメソッドがよばれたときに、

 IAdapterFactory adapterFactory = new HyperbolaAdapterFactory();
 Platform.getAdapterManager().registerAdapters(adapterFactory,Contact.class);

が自動的に行われます。でメソッドの返り値が

IAdapterFactory#getAdapter(element, IWorkbenchAdapter.class);

になります。

つまりContactがPlatformObject?ではないにもかかわらず、IAdapterFactory?を用いて

IWorkbenchAdapter adapter=(IWorkbenchAdapter) Contact.getAdapter(IWorkbenchAdapter.class);

の様なことができるわけですね。これと

 IAdapterFactory adapterFactory = new HyperbolaAdapterFactory();
 Platform.getAdapterManager().registerAdapters(adapterFactory,Contact.class);
 IWorkbenchAdapter adapter = (IWorkbenchAdapter)adapterFactory.getAdapter(IWorkbenchAdapter.class);は等価でしたね。

ちょっとまとめ

まとめると

となるわけです。つまり、ある一般的なクラスに対して、IAdaptableでないにも関わらず動的にgetAdapterが呼べる仕組みということですね。まだ、あたまがまとまってませんが、ものすごい事のような気がしてきました。

さて、つづき

さて、Viewerの続きです。ContactはもはやPlatformObject?ではないため当然IAdaptableでもありません。これだけだとBaseWorkbenchContentProvider?

protected IWorkbenchAdapter getAdapter(Object element) {
    if (!(element instanceof IAdaptable)) {
        return null;
    }
    return (IWorkbenchAdapter) ((IAdaptable) element)
            .getAdapter(IWorkbenchAdapter.class);
}

は当然nullになってしまうので、拡張クラスを作ってOverrideします。

public class HogeContentProvider extends BaseWorkbenchContentProvider {
   protected IWorkbenchAdapter getAdapter(Object element) {
       ↑この引数elementはモデル要素: Contact,ContactEntry,ContactGroupでした
       IWorkbenchAdapter adapter = null;
       // モデルが、IAdaptableならばそのまま使う
       if (element instanceof IAdaptable) {
           adapter = getAdapter(element);
       }
       // モデルが、一般的なオブジェクトならば、さっきの動的ローディングをつかう。
       if (element != null && adapter == null) {
           adapter = (IWorkbenchAdapter) Platform.getAdapterManager()
                   .loadAdapter(element, IWorkbenchAdapter.class.getName());
       } 
       // この返り値adapterは、org.eclipsercp.hyperbola.model.HyperbolaAdapterFactory
       // のgetAdapter(element,IWorkbenchAdapter.class);になるんでしたね。
       return adapter;
   }
}

Viewerにはこのコンテンツプロバイダをセットすることで、先と同じ結果が得られます。 当然、Viewでorg.eclipsercp.hyperbola.model.HyperbolaAdapterFactory?をnewする必要もないし、当然register,unregisterも必要ないです。モデルオブジェクトもPlatformObject?を拡張している必要もありません。

、、、、ここまでやって、コンテンツプロバイダやラベルプロバイダはIWorkbenchAdapter?を使わない一般的なやり方の方がいいような気がしますね。よくわかってないだけかも知れないけど。。

あ、当然ラベルプロバイダも書き換える必要があります。この書きかえ方が...またようわからん。。WorkbenchLabelProvider?#getAdapterはfinalだし。。。。じぶんで書くしかないのかなぁ。。


この記事は

選択肢 投票
おもしろかった 2  
そうでもない 0  

Top / Eclipse / プラグイン開発のTIPS集 / org.eclipse.core.runtime.IAdaptable(cont.)

現在のアクセス:13223


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS