// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents

さて、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依存にしたくないですしね。

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

#ref(model.png)




***org.eclipse.core.runtime.adapters拡張ポイント [#w41962c2]
こたえはやはり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);
は等価でしたね。



***ちょっとまとめ [#e297a645]
まとめると
-あるモデルがある
-あるモデルに対して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が呼べる仕組みということですね。まだ、あたまがまとまってませんが、ものすごい事のような気がしてきました。





***さて、つづき [#ldaa64ed]
さて、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だし。。。。じぶんで書くしかないのかなぁ。。



***関連リンク [#c3b6a9f0]
#ls2(Eclipse/プラグイン開発のTIPS集/org.eclipse.core.runtime.IAdaptable)





----
この記事は
#vote(おもしろかった[3],そうでもない[0])
#vote(おもしろかった[6],そうでもない[0])
-ここに書いた情報は、まだあってるかあやしいですよ。。ごちゅうい。。 -- [[きの]] &new{2006-03-27 16:47:16 (月)};

#comment
#topicpath


SIZE(10){現在のアクセス:&counter;}


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