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);

は等価でしたね。

ちょっとまとめ

まとめると

  • あるモデルがある
  • あるモデルに対してgetAdapterして別のオブジェクトを取得したい
  • plugin.xmlに
    <extension point="org.eclipse.core.runtime.adapters">
      <factory
         adaptableType="あるモデルのクラス名"
         class="IAdapterFactoryの実装クラス名">
        <adapter type="別のオブジェクトのクラス名"/>
      </factory>
    </extension>
    と定義しておく
  • IAdapterFactory?の実装クラスで
    public Object getAdapter(Object adaptableObject, Class adapterType);
    public Class[] getAdapterList();
    をoverrideする
  • public Object getAdapter(Object adaptableObject, Class adapterType);は
    adaptableObjectはあるモデルのクラス名
    adapterTypeは別のオブジェクトのクラス名
    だった場合は「別のオブジェクトのクラス」を返す、という処理を書く
  • public Class[] getAdapterList?();は「別のオブジェクトのクラス」を返すようにしておく

となるわけです。つまり、ある一般的なクラスに対して、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だし。。。。じぶんで書くしかないのかなぁ。。

関連リンク


この記事は

選択肢 投票
おもしろかった 6  
そうでもない 0  
  • ここに書いた情報は、まだあってるかあやしいですよ。。ごちゅうい。。 -- きの? 2006-03-27 16:47:16 (月)

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

現在のアクセス:11853


添付ファイル: filemodel.png 795件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-09-12 (木) 11:54:56 (2136d)