<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>
それでは、UNOコンポーネントを作ろう。我々のUNOコンポーネントは'thebiasplanet.uno.hiunoextensionsunoextension.HiUnoExtensionsImplementation'だから、プロジェクトディレクトリの下にJavaのソースファイル、'source/java/thebiasplanet/uno/hiunoextensionsunoextension/HiUnoExtensionsImplementation.java'を作り、以下をこのファイルに書く。
// # Change the package name
package thebiasplanet.uno.hiunoextensionsunoextension;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import com.sun.star.lib.uno.helper.WeakBase;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XInitialization;
import com.sun.star.uno.XComponentContext;
// # Add necessary classes and interfaces START
import com.sun.star.lang.IllegalArgumentException;
// # Add necessary classes and interfaces END
// # Change the class name
public class HiUnoExtensionsImplementation
extends WeakBase
implements XServiceInfo, XInitialization,
// # Specify the UNO interface to implement
XHiUnoExtensions {
private static final Set <String> SERVICE_NAMES_SET = new HashSet <String> ();
private static final Class thisClass = new Object () { }.getClass ().getEnclosingClass ();
static {
// # Add service names START
SERVICE_NAMES_SET.add ("thebiasplanet.uno.hiunoextensionsunoextension.HiUnoExtensions");
// # Add service names END
}
static final String [] SERVICE_NAMES_ARRAY = SERVICE_NAMES_SET.toArray (new String [SERVICE_NAMES_SET.size ()]);
private XComponentContext componentContext = null;
// # Add member variables START
private String message = null;
// # Add member variables END
static void setThisClassToServicesProvider (Map <String, Object []> p_implementationClassNameToImplementationClassAndServiceNamesArrayMap) {
p_implementationClassNameToImplementationClassAndServiceNamesArrayMap.put (thisClass.getName (), new Object [] {thisClass, SERVICE_NAMES_ARRAY});
}
// # Change the class name
public HiUnoExtensionsImplementation (XComponentContext p_componentContext)
throws IllegalArgumentException {
componentContext = p_componentContext;
}
public final void initialize (java.lang.Object [] p_arguments)
throws com.sun.star.uno.Exception {
// # Write the initialization START
if (p_arguments != null && p_arguments.length == 1) {
if (p_arguments[0] instanceof String) {
message = (String) p_arguments[0];
if (message == null) {
throw new IllegalArgumentException ("The first argument can't be null.");
}
}
else {
throw new IllegalArgumentException("The first argument must be a String instance.");
}
}
else {
throw new IllegalArgumentException("The number of arguments must be 1.");
}
// # Write the initialization END
}
// # Add methods of the implemented UNO interface START
public String sayHi (String p_name)
throws IllegalArgumentException {
if (p_name == null) {
throw new IllegalArgumentException ("The first argument can't be null.");
}
return String.format ("%s, %s!", message, p_name);
}
// # Add methods of the implemented UNO interface END
// # Add other member methods START
// # Add other member methods END
public String getImplementationName () {
return thisClass.getName ();
}
public final boolean supportsService (String p_serviceName) {
return SERVICE_NAMES_SET.contains (p_serviceName);
}
public final String [] getSupportedServiceNames () {
return SERVICE_NAMES_ARRAY;
}
}
ふーむ、 . . .
このクラスは、'com.sun.star.lib.uno.helper.WeakBase'を継承するが、これは、'com.sun.star.lang.XTypeProvider'と'com.sun.star.uno.XWeak'を実装したUNOのヘルパークラスだ。
'com.sun.star.lang.XTypeProvider'は、我々のUNOコンポーネントがLibreOffice Basicマクロからアクセスされるならば実装しておく必要がある。LibreOffice Basicマクロは、UNOコンポーネントがどのUNOインターフェースを実装しているかを、'com.sun.star.lang.XTypeProvider'を通して知らなければならない。
Javaプログラムでは必要ないのに、LibreOffice Basicマクロは何故、それらを知らなければならないのか?
UNOプロキシはUNOインターフェースに対して作られることを思い出してくれ。Javaでは、別のUNOインターフェースに対するUNOプロキシが欲しい場合、そのUNOインターフェースを指定することでそのUNOプロキシを明示的に得る。LibreOffice Basicマクロでは、このプロセスはLibreOffice Basicランタイムによって処理されるが、LibreOffice Basicランタイムは、どのUNOインターフェースを問い合わせるべきかを'com.sun.star.lang.XTypeProvider'を通して知る。
それでは、LibreOffice Basicマクロでは、 UNOインターフェース毎にUNOプロキシを明示的に取得しなくてもよいわけだ。
そうだ。
'com.sun.star.uno.XWeak'は、実のところ、我々には特に実装する必要がない。このヘルパークラスを使うのは、このヘルパークラスが'com.sun.star.lang.XTypeProvider'を実装しており、'com.sun.star.lang.XTypeProvider'だけを実装しているヘルパークラスがないからだ。
'com.sun.star.uno.XWeak'の役割は何だ?
UNOコンポーネントが'com.sun.star.uno.XWeak'を実装したら、このUNOコンポーネントを弱い参照で参照できるようになる。弱い参照は、あるオブジェクトへの参照であるが、そのオブジェクトがガーベッジコレクトされるのを妨げない参照だ。
すると、我々のUNOコンポーネントのインスタンスが弱い参照で参照されているが普通の(強い)参照で参照されていない場合、そのインスタンスはそのうちガーベッジコレクトされるわけだ。
そう。
また、我々のUNOコンポーネントは、'com.sun.star.lang.XServiceInfo'、'com.sun.star.lang.XInitialization'、'thebiasplanet.uno.hiunoextensionsunoextension.XHiUnoExtensions'も実装する。
我々のUNOコンポーネントが'com.sun.star.lang.XServiceInfo'を実装するのは、UNOサービスとして登録されるからだ。そうでなければ、'com.sun.star.lang.XServiceInfo'を実装する必要はない。
メソッド、'getImplementationName'、'supportsService'、'getSupportedServiceNames'は、このインターフェースのメソッドだ。
メソッド、'getImplementationName'は、UNOコンポーネントクラスのフルネームを戻す。
メソッド、'supportsService'は、1つのStringインスタンスを受け取り、このStringインスタンスが、このUNOコンポーネントが登録されるUNO サービス名の1つと同値であるかを判断する。
メソッド、'getSupportedServiceNames'は、このUNOコンポーネントが登録されるUNOサービス名の配列を戻す。
UNOコンポーネントは、複数のUNOのサービス名で登録できるようだ。それは有用なのだろうか?
私には分からない。とにかく、メカニズム上、1つのUNOコンポーネントを複数のUNOサービス名で登録できるようになっている。
なるほど。
'com.sun.star.lang.XInitialization'については、我々のUNOコンポーネントがUNOサービスマネージャーを通してインスタンス化される時、このインターフェースによって、我々はそうしたインスタンスの初期化をカスタマイズできる。
メソッド、'initialize'がこのインターフェースのメソッドだ。我々のUNOコンポーネントがUNOサービスマネージャーを通してインスタンス化される時、このUNOコンポーネントのJavaコンストラクタが、コンポーネントコンテキストを引数として呼び出される。次に、'initialize'メソッドが、パラメータの配列を引数として呼ばれる。
ははあ。
そして、もちろん、我々のUNOコンポーネントはインターフェース、'thebiasplanet.uno.hiunoextensionsunoextension.XHiUnoExtensions'を実装する。
勿論。
スタティックファイナルなメンバー、'SERVICE_NAMES_SET'、'thisClass'、'SERVICE_NAMES_ARRAY'は、このUNOコンポーネントがUNOサービスとして登録されるために必要な情報を格納している。この情報は、これらのメンバーとして格納されている必要は特になく、先に述べたインターフェースが適切に実装されればそれでよい。
'SERVICE_NAMES_SET'に追加するUNOサービス名を変更すればよいだけなわけだ。
そう。
メンバー、'componentContext'は、コンポーネントコンテキストを格納している。コンポーネントコンテキストは、UNOオブジェクトに取っておく必要は必ずしもないが、多くの場合、ここに取っておくと役に立つ。コンポーネントコンテキストからグローバルUNOサービスマネージャーを取得できる。そこで、我々は、Javaコンストラクタの引数で渡されたコンポーネントコンテキストをそこに保存するのをデフォルトとする。
いいだろう。
メンバー、'message'は、このUNOコンポーネント独自のメンバーだ。他のUNOコンポーネントでは、それぞれ必要なメンバーで置き換える。
なるほど。
スタティックメソッド、'setThisClassToServicesProvider'は、このUNOコンポーネントの情報を'グローバルUNOサービス'プロバイダーに提供するメソッドだ。この情報は、このメソッドで提供する必要はなく、'グローバルUNOサービス'プロバイダーが知るべきことを知れればそれでよい。
オーケー。
そして、メソッド、'sayHi'は、インターフェース、'thebiasplanet.uno.hiunoextensionsunoextension.XHiUnoExtensions'のメソッドだ。
そこが、我々のUNOコンポーネント独自のアルゴリズムを記述する場所なわけだ。
- Apache OpenOffice Wiki. (2014/01/02). Apache OpenOffice Developer's Guide. Retrieved from https://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide