前の関連記事:LibreOffice(13)デベロッパーガイド1 ほとんどの例はJava
2 第一歩 First Steps
2.3 始めてみよう Getting Started
Installation SetsにでてくるNetBeansへのプラグインは現行のNetBeans7.4にはあてはまりませんでした。
サービス・マネージャー Service Managers
サービスマネジャ自体が何であるのかは最後に付属の用語集 GlossaryのService Managerの項目がわかりやいです。
サービスマネジャが工場(ファクトリー)であり、その工場でサービス名からUNOオブジェクト(インスタンス)を作るとなっています。
サービスマネジャが工場そのものというより発注(呼出)と出荷(実装)を手配すると考えたほうがわかりやすいかもしれません。
でもインスタンスの生成にサービスマネジャがからんでくるのはサービスとサービスマネジャの関係がLibreOffice(12)オブジェクト指向プログラミング:インターフェイスにでてくる(Javaの)インターフェイス($$$\neq$$$UNOのインターフェイス)とそれを実装するクラスとの関係に似ているからです。
サービスの中身には具体的には何も書いてなくてそのサービスが備えている(UNOの)インターフェイス($$$\neq$$$Javaのインターフェイス)の名前しかありません。
Javaのインターフェイスがそれを実装するクラスで具体的なコードが割り当てられたのと同じように、UNOではサービスマネジャがサービスに対して具体的なコードを割り当ててインスタンスを生成します。
このようにすることによってサービスを利用する側のコードを書くときはサービスの名前さえわかっていればサービスを利用できることになります。
具体的なコードは利用する側の環境に合わせてサービスマネジャが勝手に適したコードを割り当ててくれる訳です。
サービスマネジャの項をLibreOffice 4.2 SDK API Referenceでみる
サービスマネジャの解説は3 プロフェッショナル UNOの3.3.2 サービス・マネージャーとコンポーネント・コンテキスト Service Manager and Component Context にあります。
まずはLibreOffice 4.2 SDK API Reference(以下APIリファレンスと呼びます)でServiceManagerの項を見てみます。
ServiceManagerで検索するとcom.sun.star.lang.ServiceManagerがでてきます。
これがAPIリファレンスにあるServiceManagerサービスの継承関係図です。
Xから始まる名前のものは(UNOの)インターフェイスです。
LibreOffice(12)オブジェクト指向プログラミング:インターフェイスでできたJavaのクラスは多重継承ができずこのようにクラス図の継承が分岐できないのですが、UNOでは多重継承が可能なので分岐がいっぱいありますね。
ところがUNOもOpenOffice.org 2.0より以前はインターフェイスの多重継承ができませんでした。
そのためにOpenOffice.org 2.0より以前はサービスに複数のインターフェイスを持たしてそのサービス(old-style service)を継承することにより多重継承と同じ状態を作り出していました。
OpenOffice.org 2.0以降はインターフェイスの多重継承が可能となったので、サービス(new-style service)は複数のインターフェイスを持つ必要がなくなりました。
しかしold-style serviceは現在もそのまま使われています。
そのために継承関係図では上のようにXで始まるインターフェイス名の合間にXでは始まらないサービス名が挟まっているところがあります。
com.sun.star.lang.ServiceManagerのIncluded Servicesの項目にServiceManagerサービスが継承したサービスが載っています。
Exported Interfacesの項目にはServiceManagerサービスが継承したインターフェイスが列挙されています。
(日本語で考えると全部inheritedでいいように思いますがサービスはincluded、インターフェイスはexportedとわざわざなっているのは英語ではそれぞれニュアンスが異なるからでしょうかね。)
Exported Interfacesの項目の一番下の項目にはIncluded Servicesの項目にでてきた継承したサービスに含まれるインターフェイスも載っています。
ServiceManagerサービスの継承関係図を改めてよく見てみると継承したインターフェイスやサービスはすべてXinterfaceから継承されています。
こんな感じにXInterfaceインターフェイスから6つに分岐して継承してからまたServiceManagerサービスで一つに収束しています。
こういう形になるのはすべてのインターフェイスは com.sun.star.uno.XInterfaceを継承しないといけないと決まっているからです。(18.1.3 インヘリタンス Inheritance)
サービスマネジャが使う工場には2部門がある
継承されてcom.sun.star.lang.ServiceManagerがもつことになったインターフェイスがAdditional Inherited Membersに書いてあります。
1行目にXMultiSerivceFactory、2行目にXMultiComponentFactoryとあります。
com.sun.star.lang.ServiceManagerの継承関係図でみたようにいずれもcom.sun.star.lang.MultiServiceFactoryサービスから継承したものです。
このようにサービスマネジャにはMultiSerivceFactoryという工場があり、そのなかにXMultiSerivceFactoryとXMultiComponentFactoryの2種類の部門があることになります。
それぞれの使い方(メソッド)は行頭の▶をクリックすればわかります。
XMultiServiceFactory
サービスマネジャ.createInstance(サービス名) これでそのサービスのインタンスを得られます。
引数があるときはcreateInstanceWithArgumentsを使って以下のようにします。
サービスマネジャ.createInstanceWithArguments(サービス名, 引数)
XMultiComponentFactory
サービスマネジャ.createInstanceWithContext(サービス名, コンポーネントコンテクスト) これでそのサービスのインタンスを得られます。
引数があるときはcreateInstanceWithArgumentsAndContextを使って以下のようにします。
サービスマネジャ.createInstanceWithArgumentsAndContext(サービス名, 引数, コンポーネントコンテクスト)
XMultiServiceFactoryとXMultiComponentFactoryのどちらの部門を呼び出して実装を依頼するのかはサービスマネジャが決めるのではなくコードを書く人が決めないといけません。
これら2つがある理由とどちらを使えばよいのかは3.3.2 サービス・マネージャーとコンポーネント・コンテキスト Service Manager and Component Contextに書いてあります。
結論だけいうとXMultiComponentFactoryの方を使えと書いてあります。
XMultiSerivceFactoryとXMultiComponentFactoryの違いを理解するにはコーポーネントコンテクストについて知る必要があります。
そもそもサービスマネジャ自体をどこで得るのかもまだ書いていませんし。
コンポーネントコンテクストについては次回に書こうと思います。
APIリファレンスには書いていない情報もある
APIリファレンスを読めるようになれば他の資料は見なくてもよいのかと思っていましたがそうでもないようです。
XMultiSerivceFactoryとXMultiComponentFactoryの違いもAPIリファレンスを読んだだけではどちらを使ったらよいのかはわかりません。
3.2.2 API リファレンスの理解 Understanding the API Referenceを読むとUNOコンポーネントはAPIリファレンスに書いていないインターフェイスを備えていることもあるし、逆に特定の条件でないと使えないインターフェイスもあるようです。
UNOコンポーネントの一例としてLibreOffice(5)PythonでLibreOfficeが動く仕組み:UNOでPython UNOコンポーネントをみましたが、4.3 コンポーネント・アーキテクチャ Component Architectureの図をみるとUNOコンポーネントとサービスの関係のイメージがつかみやすいです。
その図ではUNOコンポーネントからSingleServiceFactory(今後はSingleComponentFactory)でクラスがインスタンス化されてサービスができインターフェイスを備えています。
自分でUNOコンポーネントを書くときはこれらの情報はいるのかもしれませんが、マクロを書くときにAPIリファレンスに載っていないインターフェイスまで使えるようになる必要があるのかわかりませんでした。
MultiSerivceFactoryを使ったときに内部ではSingleServiceFactoryが動いてUNOコンポーネントのクラスをインスタンス化してできたサービスがUNOオブジェクトになるということか、と思ったのですがそのように書いた部分は見つけられませんでした。
話は変わりますがLibreOffice(12)オブジェクト指向プログラミング:インターフェイスでオブジェクトの関数はメソッドという、と覚えたのですがこのAPIリファレンスではFunction(関数)と書いてあります。
Developer's Guideではmethodとfunctionの両方が同じような使い方ででてきます。
一緒と思ってしまえばそれまでですが、同じ意味はなるべく同じ用語に統一してくれたほうが斜読みのときに引っかからずに済みますのに。
APIリファレンスのメソッドの前に書いてあるインターフェイスは戻り値の型を表している
このようにメソッドcreateInstanceやcreateInstanceWithArgumentsの前に書いてあるcom::sun::star::uno::XInterfaceが何を表しているのかわからず一晩悩みました。
LibreOffice: com/sun/star/lang/XMultiServiceFactory.idl Source File
(APIリファレンスのidlソースの行番号が連続していないのはなぜでしょう?)
published interface XMultiServiceFactory: com::sun::star::uno::XInterface { com::sun::star::uno::XInterface createInstance( [in] string aServiceSpecifier ) raises( com::sun::star::uno::Exception ); com::sun::star::uno::XInterface createInstanceWithArguments( [in] string ServiceSpecifier, [in] sequence<any> Arguments ) raises( com::sun::star::uno::Exception ); sequence<string> getAvailableServiceNames(); };ソースのこの部分をみてようやく閃きました。
com::sun::star::uno::XInterfaceは戻り値のオブジェクトの型を表しているのですね。
同じ列にはsequence< string >とか書いてあるのでもっと早く「型」と気づくべきでしたね。
Javaの、作ったオブジェクトが型になるという発想になかなか慣れることができません。
参考にしたサイト
Apache OpenOffice Developer's Guide - Apache OpenOffice Wiki
PDF版の表紙にOpenOffice.org 3.1 Developer's Guideと書いてあります。
Developer's Guide
OpenOffice Developer's Guideの日本語版。OpenOffice.org 2.0より前のもののようです。
LibreOffice: Namespace List
LibreOffice 4.2 SDK APIの入り口com.sun.star。このブログではAPIリファレンスといいます。
0 件のコメント:
コメントを投稿