'singleton' UNOIDLエンティティを作成しても、シングルトンは作成されず、シングルトンgetterが作られるだけです。それでは、シングルトンはどうすれば作成できるのか?ここにその方法があります。
話題
About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: Java
About: C++
About: C#
About: Python
この記事の目次
- 開始コンテキスト
- ターゲットコンテキスト
- オリエンテーション
- 本体
- 1: 'singleton' UNOIDLエンティティはシングルトンを作成しない
- 2: UNOオブジェクトシングルトンとは本当には何であるか
- 3: 任意のUNOオブジェクトシングルトンを作成するの方法
- 4: 任意のUNOオブジェクトシングルトンを取得する方法
- 5: サンプルコード、プログラミング言語毎に
- 6: 利用方法
開始コンテキスト
- 読者は、UNOとは何か、UNOはLibreOfficeまたはApache OpenOfficeとどう関係しているかの知識を持っている。
- 読者は、UNOの基本的構成要素とそれらにこのシリーズで使われる用語体系の知識を持っている。
- 読者は、任意のUNOインターフェイスを作成・登録し、そのマッピングイメージたちを生成する方法の知識を持っている。
- 読者は、任意のUNOコンポーネントを、Java、C++、C#、Pythonで作成する方法の知識を持っている。
ターゲットコンテキスト
- 読者は、任意のUNOオブジェクトシングルトンを、Java、C++、C#、Pythonで作成する方法を知る。
オリエンテーション
本体
ト書きSpecial-Student-7、Objector 69A、Objector 69Bがコンピュータの前にいる。
1: 'singleton' UNOIDLエンティティはシングルトンを作成しない
Objector 69B
オフィシャルドキュメントは'singleton' UNOIDLエンティティを作成せよと言ってるけど、それってシングルトンなんか作成してないようなのよね。どうなってるの?
Special-Student-7
ああ、マダム、以下のようなエンティティのことを言われてますよね。
@UNOIDL ソースコード
#ifndef __theBiasPlanet_unoDatumTypes_heyUnoExtensions_ScolderPraiserUnoServiceSingleton_idl__#define __theBiasPlanet_unoDatumTypes_heyUnoExtensions_ScolderPraiserUnoServiceSingleton_idl__#include "theBiasPlanet/unoDatumTypes/heyUnoExtensions/XScolder.idl"module theBiasPlanet {module unoDatumTypes {module heyUnoExtensions {singleton ScolderPraiserUnoServiceSingleton: XScolder;};};};#endif
Objector 69B
ええ。そんなやつを作ったんだけど、それでどうなるの?シングルトンクラスの実装はどこに書けばいいわけ?意味わからない!
Special-Student-7
オフィシャルドキュメントは実に用語体系がゆるんでいます。この場合、それは、'シングルトンgetter'を'シングルトン'から区別していません。
Objector 69B
"シングルトンgetter"?
Special-Student-7
任意のシングルトンは、あるシステム内におけるあるクラスの唯一インスタンスです。つまり、そのシステム内にその同一クラスの別インスタンスはないということです。
Objector 69B
シングルトンが何かは知ってるわよ。
Special-Student-7
任意のシングルトンgetterは、そのシングルトンを取り出すものです。
そのUNOIDLエンティティは、シングルトンgetterを作成するのであって、何らのシングルトンも作成しません。
オフィシャルドキュメントは本当に誤解を招くものです、と言わざるを得ません。
Objector 69B
えーと、それじゃあ、私はどうすればシングルトンを作成できるわけ?
Special-Student-7
私が読む限りでは、オフィシャルドキュメントはそれについて何も言いません。そこで、私が知っている方法を見ましょう、それが想定されている方法なのか私には定かではありませんが。
2: UNOオブジェクトシングルトンとは本当には何であるか
Special-Student-7
任意のUNOオブジェクトシングルトンは本当には何であるかを理解しましょう。
任意のUNOオブジェクトシングルトンは、実のところ、単に、あるUNOオブジェクト群コンテキストの1プロパティです。 .
Objector 69A
"あるUNOオブジェクト群コンテキスト"?どのUNOオブジェクト群コンテキストだ?
Special-Student-7
サー、確かに、複数のUNOオブジェクト群コンテキストがあり得ます(それが、UNOオブジェクト群コンテキストというコンセプトが導入されたそもそもの理由です)が、1つのデフォルトUNOオブジェクト群コンテキストがあり、他のものはそれの派生であって、おそらくは、シングルトンは、通常はデフォルトUNOオブジェクト群コンテキストへ入れられ、全てのUNOオブジェクト群コンテキストに共有されることになりますが、ある特定の系統にのみへ入れられることはできないという理由はありません。
Objector 69A
えーと、どんなプロパティでもいいのかね?
Special-Student-7
メカニズム上は、どんなプロパティでもかまいません、もしも、上に記されたようなUNOIDLベースシングルトンgetterを用いることに固執されないのでしたら。しかし、慣習として、プロパティは/singletons/%the singleton specific name%'と名付けられ、それは、対応するUNOIDLベースシングルトンgetterを介して取得できます。
3: 任意のUNOオブジェクトシングルトンを作成するの方法
Objector 69B
それで、どうすれば私はシングルトンをUNOオブジェクト群コンテキストへ入れられるの?
Special-Student-7
それは、オフィシャルドキュメントが説明していないように思われることですが、任意のUNOオブジェクト群コンテキストは'com.sun.star.container.XNameContainer' UNOインターフェイスを実装してあるので、それを介して私たちはプロパティをセットできます。
Objector 69B
うん?UNOオブジェクト群コンテキストは変更できないものと思ってた、だって、'::com::sun.star::uno::XComponentContext'インターフェイスにはsetterメソッドがないから、でも、そんな方法があるのね . . .
4: 任意のUNOオブジェクトシングルトンを取得する方法
Special-Student-7
UNOオブジェクトシングルトンを取得するために、UNOIDLベースgetterは特に必要ありません、実のところ。
Objector 69A
そのはずだ: 単にUNOオブジェクト群コンテキストの1プロパティとして取得できるはずだ。
Special-Student-7
そして、私自身はUNOIDLベースシングルトンgetterたちを全然用いません、なぜなら、その方法はPythonには適用できませんから。
Objector 69A
できないの?
Special-Student-7
私が知る限りでは、というのは、対応するPythonマッピングイメージを生成する既存ツールがありませんから。
しかし、UNOオブジェクトシングルトンたちをPythonで問題なく使用できます。
5: サンプルコード、プログラミング言語毎に
Special-Student-7
以下は、UNOオブジェクトシングルトンをJavaにて作成・取得・削除するサンプルコードです('l_underlyingRemoteUnoObjectsContext'はUNOオブジェクト群コンテキスト)。
@Java ソースコード
import com.sun.star.container.ElementExistException;import com.sun.star.container.NoSuchElementException;import com.sun.star.container.XNameContainer;import com.sun.star.lang.XUnoTunnel;import com.sun.star.uno.UnoRuntime;import com.sun.star.uno.XInterface;import theBiasPlanet.unoUtilitiesTests.localUnoObjectsTest1.TestUnoComponent;String l_testUnoComponentSingletonUrl = "/singletons/theBiasPlanet.unoUtilitiesTests.localUnoObjectsTest1.TestUnoComponent";// creating a singleton Starttry {UnoRuntime.queryInterface (XNameContainer.class, l_underlyingRemoteUnoObjectsContext).insertByName (l_testUnoComponentSingletonUrl, new TestUnoComponent ());}catch (ElementExistException l_exception) {}// creating a singleton End// getting the singleton StartObject l_testUnoComponent = l_underlyingRemoteUnoObjectsContext.getValueByName (l_testUnoComponentSingletonUrl);if (l_testUnoComponent instanceof XInterface) {System.out.println (String.format ("### getSomething: %d.", UnoRuntime.queryInterface (XUnoTunnel.class, (XInterface) l_testUnoComponent).getSomething (null)));}else {System.out.println (String.format ("### the singleton is not there."));}// getting the singleton End// removing the singleton Starttry {UnoRuntime.queryInterface (XNameContainer.class, l_underlyingRemoteUnoObjectsContext).removeByName (l_testUnoComponentSingletonUrl);}catch (NoSuchElementException l_exception) {}// removing the singleton End
Objector 69B
'TestUnoComponent'はどこから来たの?
Special-Student-7
それは、別の記事から来たUNOコンポーネントです。普通は、あなたはあなた自身のUNOコンポーネントを持っていて、そのインスタンスがシングルトンになります、なんらかその他の形で取ってきたオブジェクトをシングルトンとして登録できないとは申しませんが。
Objector 69B
えーと。
Special-Student-7
以下は、C++コードです('l_underlyingRemoteUnoObjectsContext'はUNOオブジェクト群コンテキスト)。
@C++ ソースコード
#include <iostream>#include <osl/mutex.hxx>#include <string>#include <com/sun/star/container/ElementExistException.hpp>#include <com/sun/star/container/NoSuchElementException.hpp>#include <com/sun/star/container/XNameContainer.hpp>#include <com/sun/star/lang/XUnoTunnel.hpp>#include <com/sun/star/uno/Any.hxx>#include <com/sun/star/uno/Reference.hxx>#include <com/sun/star/uno/Sequence.hxx>#include "theBiasPlanet/unoUtilities/stringsHandling/UnoExtendedStringHandler.hpp"#include "theBiasPlanet/unoUtilitiesTests/localUnoObjectsTest1/Option4UnoComponent.hpp"using namespace ::osl;using namespace ::std;using namespace ::com::sun::star::container;using namespace ::com::sun::star::lang;using namespace ::com::sun::star::uno;using namespace ::theBiasPlanet::unoUtilities::stringsHandling;using namespace ::theBiasPlanet::unoUtilitiesTests::localUnoObjectsTest1;string l_testUnoComponentSingletonUrl ("/singletons/theBiasPlanet.unoUtilitiesTests.localUnoObjectsTest1.TestUnoComponent");// creating a singleton Starttry {Mutex l_unoMutex;Reference <XNameContainer> (l_underlyingRemoteUnoObjectsContext, UNO_QUERY)->insertByName (UnoExtendedStringHandler::getOustring (l_testUnoComponentSingletonUrl), Any (Reference <XUnoTunnel> (new Option4UnoComponent (l_unoMutex))));}catch (ElementExistException l_exception) {}// creating a singleton End// getting the singleton StartAny l_testUnoComponent (l_underlyingRemoteUnoObjectsContext->getValueByName (UnoExtendedStringHandler::getOustring (l_testUnoComponentSingletonUrl)));if (l_testUnoComponent.hasValue ()) {Sequence <sal_Int8> l_datumIdentification;cout << string ("### getSomething: ") << Reference <XUnoTunnel> (* ( (Reference <XInterface> *) l_testUnoComponent.getValue ()), UNO_QUERY)->getSomething (l_datumIdentification) << endl << flush;}else {cout << string ("### the singleton is not there.") << endl << flush;}// getting the singleton End// removing the singleton Starttry {Reference <XNameContainer> (l_underlyingRemoteUnoObjectsContext, UNO_QUERY)->removeByName (UnoExtendedStringHandler::getOustring (l_testUnoComponentSingletonUrl));}catch (NoSuchElementException l_exception) {}// removing the singleton End
'Option4UnoComponent'は、別の記事から来たUNOコンポーネントです。
Objector 69B
'UnoExtendedStringHandler'って何?
Special-Student-7
ああ . . .、'UnoExtendedStringHandler::getOustring'は私のユーティリティメソッドであり、'::rtl::OUString'(C++ UNO文字列クラス)インスタンスを、指定された'string'インスタンスから生成するものです。あなたは、そのメソッドを使う必要はありません、ご自身の方法で'::rtl::OUString'インスタンスを取得されればよいだけです。
Objector 69B
. . .
Special-Student-7
以下は、C#コードです('l_underlyingRemoteUnoObjectsContext'はUNOオブジェクト群コンテキスト)。
@C# ソースコード
using uno;using unoidl.com.sun.star.lang;using unoidl.com.sun.star.container;using unoidl.com.sun.star.uno;using theBiasPlanet.unoUtilitiesTests.localUnoObjectsTest1;String l_testUnoComponentSingletonUrl = "/singletons/theBiasPlanet.unoUtilitiesTests.localUnoObjectsTest1.TestUnoComponent";// creating a singleton Starttry {( (XNameContainer) l_underlyingRemoteUnoObjectsContext).insertByName (l_testUnoComponentSingletonUrl, new Any (l_underlyingRemoteUnoObjectsContext.GetType (), new TestUnoComponent ()));}catch (ElementExistException l_exception) {}// creating a singleton End// getting the singleton StartAny l_testUnoComponent = l_underlyingRemoteUnoObjectsContext.getValueByName (l_testUnoComponentSingletonUrl);if (l_testUnoComponent.Value != null) {Console.Out.WriteLine (String.Format ("### getSomething: {0:d}.", ( (XUnoTunnel) l_testUnoComponent.Value).getSomething (null)));}else {Console.Out.WriteLine (String.Format ("### the singleton is not there."));}// getting the singleton End// removing the singleton Starttry {( (XNameContainer) l_underlyingRemoteUnoObjectsContext).removeByName (l_testUnoComponentSingletonUrl);}catch (NoSuchElementException l_exception) {}// removing the singleton End
'TestUnoComponent'は、別の記事から来たUNOコンポーネントです。
以下は、Pythonコードです('l_underlyingRemoteUnoObjectsContext'はUNOオブジェクト群コンテキスト)。
@Python ソースコード
from typing import castimport sysimport unofrom com.sun.star.container import ElementExistExceptionfrom com.sun.star.container import NoSuchElementExceptionfrom com.sun.star.container import XNameContainerfrom com.sun.star.lang import XUnoTunnelfrom com.sun.star.uno import XComponentContextfrom com.sun.star.uno import XInterfacefrom theBiasPlanet.unoUtilitiesTests.localUnoObjectsTest1.TestUnoComponent import TestUnoComponentl_testUnoComponentSingletonUrl: str = "/singletons/theBiasPlanet.unoUtilitiesTests.localUnoObjectsTest1.TestUnoComponent"# creating a singleton Starttry:cast (XNameContainer, l_underlyingRemoteUnoObjectsContext).insertByName (l_testUnoComponentSingletonUrl, TestUnoComponent ())except (ElementExistException) as l_exception:None# creating a singleton End# getting the singleton Startl_testUnoComponent: object = l_underlyingRemoteUnoObjectsContext.getValueByName (l_testUnoComponentSingletonUrl)if l_testUnoComponent is not None:sys.stdout.write ("### getSomething: {0:d}.\n".format (cast (XUnoTunnel, l_testUnoComponent).getSomething ([])))else:sys.stdout.write ("### the singleton is not there.\n")# getting the singleton End# removing the singleton Starttry:cast (XNameContainer, l_underlyingRemoteUnoObjectsContext).removeByName (l_testUnoComponentSingletonUrl)except (NoSuchElementException) as l_exception:None# removing the singleton End
'TestUnoComponent'は、別の記事から来たUNOコンポーネントです。
6: 利用方法
Objector 69B
問題は、私はシングルトンをどこからセットするか?
Special-Student-7
それは全くあなた依存です。
Objector 69B
"あなた依存"と言われても、そんなに依存されたくないんだけど。
Special-Student-7
シングルトンUNOオブジェクトは、オフィスJVM内に生存してもよいですが、あなたの外部Javaプログラム内に存在してもよいです。
Objector 69B
後者は可能なの?つまり、そのUNOオブジェクトは外部プログラム内にいて、あるPythonマクロは、外部プログラム内のUNOオブジェクトを、何も特別なことはないかのように使えるの?
Special-Student-7
はい。それがUNOです。
しかし、勿論、その外部プログラムは稼働し続けておく必要があります。
Objector 69B
それは当然のことね。
Special-Student-7
したがって、C#プログラマーで、できるだけC#で何でも書きたい方は、いくつかのシングルトンを登録するC#外部UNOクライアントを書き、当該C#コードをPythonマクロたちに使わせることができます。そうすると、C#プログラマーはマクロをC#で書けませんが、彼または彼女のC#コードはマクロから使用できます。
Objector 69B
ああ、そのC#外部クライアントはWindowsサービスでもいいのよね、例えば。
Objector 69A
はあ?でも、オフィスインスタンスは上がったり落ちたりするかもしれないだろう。そのWindowsサービスはどうやってシングルトンたちをサービスし続けるんだ?
Special-Student-7
そのWindowsサービスはコネクションアウェアUNOクライアントにできます、それは、任意のオフィスインスタンスへ、そのオフィスインスタンスが起動したらコネクトし、そのオフィスインスタンスがシャットダウンする時にはそのオフィスインスタンスから切断します。
Objector 69A
えーと、俺はJavaプログラマーなんだがな。どうすれば、俺のJavaシングルトンたちは、オフィスインスタンスが起動したら自動的にオフィスインスタンスにセットされるようにできるんだ?
Special-Student-7
あなたはオフィスインスタンス起動イベントリスナーをセットすることができます、それは将来の記事にて説明されます。