LibreOffice5(52)Javaの例:ConfigExamplesをPythonにする その5

updateGroupExample()では/org.openoffice.Office.Calc/Gridの値を変更しています。ビューとかモデルとかリスナーとかでてくるので、まずMVCについてモデル/ビュー/コントローラについて学習しました。

前の関連記事:LibreOffice5(51)Javaの例:ConfigExamplesをPythonにする その4


MVC(モデル/ビュー/コントローラ)の学習


LibreOfficeではフレーム・コントローラ・モデル・パラダイム(FCM)を使っています(LibreOffice(32)デベロッパーガイド4:コンポーネントフレームワーク参照)。

ドキュメントがモデル、コントローラがビュー、フレームがコントローラです(Frame-Controller-Model Paradigm in OpenOffice.org - Apache OpenOffice Wiki)。

LibreOffice(32)デベロッパーガイド4:コンポーネントフレームワークを書いた時はMVCなんて知らなかったので特に違和感は感じませんでしたが、改めて読んでみると「コントローラがビュー」とか実にややこしいです。

MVCについてはHead Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本の462ページの解説がわかりやすかったです。

この本ではMVCは「第11章Compoundパターン」に分類されています。

bethrobson/Head-First-Design-Patterns: Code for Head First Design Patterns book (2014)にある実装例にはCompoundパターンのフォルダはなくて、combined/djview/がJavaの実装例になります。

compoundは化合物、combinedは合成された、という意味なので同じ、と言えば同じですが、Combinedパターンというのはないので、compoundフォルダに入れといてほしいものです。

とりあえずこのJavaの例はたくさんファイルがあってよくわからないので、本の図の方が理解の助けになります。

Compoundパターンというのは複数のデザインパターンを組み合わせたパターンを指します。

462ページの図を改変しました。

MVCはビュー(V)とモデル(M)間にコントローラ(C)が挟まっている印象をもっていましたが、そうではなくM V Cは三角関係にあるのでした。

コントローラは交換可能なようにStrategyパターンを実装しています。

ビューは通常はGUIなのでコンポジットパターンを実装しているはずですが、ビューがGUIとは限らないのでこれは限定できないでしょう。

モデルは変更があればビューに通知しないといけないので、オブザーバーパターンを実装しています。

ややこしいことにオブザーバーパターンを実装している方がオブザーブされる方(Observabule、Subject、通知する方)になり、ビューがオブザーブする方(Observer、通知を受ける方、リスナー)になります。

オブザーブされる方に実装しないといけない場合は、オブザーブされる方をパブリッシャ(発行者)、オブザーブする方をサブスクライバ(購読者)と命名する方法の方が理解しやすいですね。

updateGroupExample()をPythonに翻訳する


ConfigExamples/configexamples.py at 5389f19ebf70230f94aab0045a5dbfb251f6085c · p--q/ConfigExamples

とりあえずJavaと似たようにして翻訳してみました。
--- starting example: update group data --------------
Grid options editor: data=[ Grid is HIDDEN; resolution = (1000,1000); subdivision = (1,1) ]
Replacing integer value: XAxis
Replacing integer value: YAxis
GridEditor - Listener received changes event containing 2 change(s).
Grid options editor: data=[ Grid is HIDDEN; resolution = (1000,1000); subdivision = (9998,9998) ]
-- GridEditor executing --
GridEditor: toggling Visibility
GridEditor - Listener received changes event containing 1 change(s).
Grid options editor: data=[ Grid is VISIBLE; resolution = (1000,1000); subdivision = (9998,9998) ]
-- GridEditor done      --
このような結果が出力されます。

Grid is HIDDENとGrid is VISIBLE、subdivision = (1,1)とsubdivision = (9998,9998)、は交互に入れ替わって表示されます。

LibreOffice5(48)Javaの例:ConfigExamplesをPythonにする その1でみたようにこれらは/opt/libreoffice5.2/share/registry/main.xcdに書いてあるデフォルト値を書き換えています。

これらのデフォルト値はorg.openoffice.OfficeパッケージのCalcコンポーネントにあるGrid/Option/VisibleGridとGrid/Option/Subdivision下にあるXAxisとYAxisにあります。

LibreOffice5(30)xcsファイルとxcuファイルとxcdファイル:その1で学習した結果では書き換えられた値は~/.config/libreoffice/4/user/registrymodifications.xcuファイルに出力されているはずです。

このregistrymodifications.xcuファイルをChromiumで開いて/org.openoffice.Office.Calc/Grid/で検索してみるとこれらの3つの値がでてきます。

デフォルト値に戻してもregistrymodifications.xcuファイルの設定は消えません。

LibreOffice5(32)イベント駆動する拡張機能のJavaの例:AsyncJob.oxt その4のときはregistrymodifications.xcuファイルを書き換えても設定が反映されないと思いましたが今回はうまくいきました。

updateGroupExample()が変更している設定


updateGroupExample()が変更しているのはCalcのグリッド線です。

LibreOfficeからはツール→オプション→LibreOffice Calc→グリッド線、で設定が見れます。


デフォルトの設定はこうなっています。(たぶん)

updateGroupExample()を実行すると「グリッド線の表示」にチェックをつけ、「サブ目盛」の数値を2から99に変更されます。


これは変更後の状態です。

LibreOffice5(53)Javaの例:ConfigExamplesをPythonにする その6で書いているようにupdateGroupExample()に続くresetGroupExample()は動かないので、ConfigExamplesを実行するとCalcの設定が変更されたままになります。


updateGroupExample()で変更されたままCalcを実行するとスプレッドシートの上にブツブツと点が打たれた状態になっています。

最初はディスプレイが壊れたのかと思ってしまいました。

APIでデフォルトに戻せないのと同様にオプションパネルでも「デフォルトに戻す」ボタンはありません。

「元に戻す」ボタンはデフォルトに戻すものではなく、保存前の状態に戻すものです。

updateGroupExample()をMVCに沿って書き換える


Javaの例ではConfigurationUpdateAccessのインスタンスがviewrootという変数に格納されています。

Object Model - Apache OpenOffice Wikiの解説では確かにビューに分類されていますが、GridOptionsEditorクラスの中ではmodelという変数に収納されています。

viewrootにはリスナーも追加されているのでupdateGroupExample()の中ではこれはビューではなくモデルに相当すると思います。

ConfigExamples/configexamples.py at b63b6c61f33476e21584bba267252035e8ef12b9 · p--q/ConfigExamples

editGridOptions()の中でモデルとコントローラをインスタンス化しています。

ビューはコントローラであるGridOptionsEditorの中でインスタンス化しています。

今回はビューを変更する必要性がないのでビューはインスタンス化するとき以外はコントローラから呼び出す機会はありません。

モデルを読み込んだり、リスナーでモデルの変化の通知を受けるものをビューにまとめました(GridOptionsEditorViewクラス)。

モデルの内容を変更するものはコントローラにまとめました(GridOptionsEditorクラス)。

informUserOfError()はコントローラのメソッドにしていますが、コントローラのインスタンスを使うわけでもなく、コントローラと関係のないところでも使っているのでstaticmethodにしています。

228行目ではクラス属性として呼び出しています。

モデルはConfigurationUpdateAccessサービスのインスタンスです。

サービスのNotifierという名前がついたインターフェイスからそのリスナー名を調べる


MVCではビューはモデルから変更の通知を受け取らないといけないので、モデルにリスナーを付けます。

モデルはConfigurationUpdateAccessサービスのインスタンスですので、これにつけられるリスナーが何かを調べます。

LibreOffice: ConfigurationUpdateAccess Service ReferenceをみてもListenerという名前がつくものがありませんが、リスナーに通知するためのインターフェイスであるNotifierという名前のインターフェイスを見つけました。
(2017.6.26追記。こんなことをしなくてもこの記事の最後に載せているメソッド一覧からListenerという名前がついているメソッドを検索してadd~Listenerという名前のメソッドを探せばよいだけでした。)

XChangesNotifierインターフェイスです。

XChangesNotifierインターフェイスはaddChangesListener()メソッドとremoveChangesListener()メソッドをもっています。

これらの引数の型はXChangesListenerインターフェイスです。

ということでConfigurationUpdateAccessサービスにつけられるリスナーはXChangesListenerインターフェイスと分かりました。

あとはこのXChangesListenerインターフェイスを継承したクラスを作成してそのクラスでXChangesListenerインターフェイスのメソッドを実装してそのインスタンスをConfigurationUpdateAccessサービスのインスタンスにそのaddChangesListener()メソッドでくっつければよいわけです。

ConfigurationUpdateAccessサービスのインスタンスが変更されるとXChangesListenerインターフェイスの実装のchangesOccurred()メソッドが呼ばれます。

これでサービスからそれに付けられるリスナーにたどり着く方法がわかりました。

commitChanges()メソッド実行前にリスナーのchangesOccurred()メソッドが呼ばれる時がある


(2017.6.29追記LibreOffice5(53)Javaの例:ConfigExamplesをPythonにする その6でどういう場合にchangesOccurred()メソッドが呼ばれるのか調べ直しました。)

コンポジションになっているConfigurationUpdateAccessサービスのインスタンスはその子ノードのインスタンスの属性を変更してもConfigurationUpdateAccessサービスのXChangesBatchインターフェイスのcommitChanges()メソッドを呼び出さないと変更点が保存されません。

changeSomeData()ではreplaceByName()メソッドで値を変更しています。

変更した時点ではまだリスナーのchangesOccurred()メソッドは呼ばれません。

207行目のcommitChanges()メソッドで実行したときにchangesOccurred()メソッドが呼ばれて実行されます。

ところが奇妙なことにtoggleVisibility()でもConfigurationUpdateAccessサービスのインスタンスの子ノードの属性を変更しているのに、この場合はcommitChanges()メソッドを実行する前のsetHierarchicalPropertyValue()メソッドで値を変更した時点でchangesOccurred()メソッドが呼ばれて実行されています。

replaceByName()メソッドと違ってsetHierarchicalPropertyValue()メソッドを使うとchangesOccurred()メソッドの前にリスナーのメソッドが呼ばれると思いましたが、、、うーん、そうじゃないと思いましたがそうかもしれません。

ごちゃごちゃいじってみましたがよくわかりませんでした。

とりあえずわかったことはcommitChanges()メソッドを実行しなくてもchangesOccurred()メソッドが呼ばれる時もあるということです。

dispose()メソッドを実行するとリスナーのdisposing()メソッドが呼ばれる


ConfigExamples.javaの例ではdispose()メソッドを実行する前にremoveChangesListener()メソッドでリスナーを除去しているのでdisposing()メソッドを実行される機会がありません。

removeChangesListener()メソッドの行をコメントアウトするとリスナーのdisposing()メソッドの中で呼び出しているsetModel(null)にエラーが出ます。

モデルをdispose()したあとにdisposing()でモデルを呼び出しているのでエラーになるわけです。

なので、Pythonの翻訳ではリスナーの除去はモデルの消滅に委ねるようにして、それで呼び出されるdisposing()メソッドの中ではモデルは呼び出さないようにしました。

これでupdateGroupExample()の翻訳完了です。

ちなみにこの変更がCalcにどのように影響しているのかは今のところわかりません。
--- starting example: update group data --------------
Grid options editor: data=[ Grid is HIDDEN; resolution = (1000,1000); subdivision = (9998,9998) ]
Replacing integer value: XAxis
Replacing integer value: YAxis
GridEditor - Listener received changes event containing 2 change(s).
Grid options editor: data=[ Grid is HIDDEN; resolution = (1000,1000); subdivision = (1,1) ]
-- GridEditor executing --
GridEditor: toggling Visibility
GridEditor - Listener received changes event containing 1 change(s).
Grid options editor: data=[ Grid is VISIBLE; resolution = (1000,1000); subdivision = (1,1) ]
-- GridEditor done      --
GridEditor - Listener received disposed event: releasing model
出力はこのようになります。

最後の行がdisposing()メソッドで出力しているものです。

com.sun.star.configuration.ConfigurationUpdateAccessのサービスとインターフェイスの一覧


ConfigurationAccessとの違いは、LibreOffice5(148)ConfigurationAccessとConfigurationUpdateAccessのサービスとインターフェイスの比較でわかります。

from com.sun.star.beans import PropertyValue
def macro():
 ctx = XSCRIPTCONTEXT.getComponentContext()  # コンポーネントコンテクストの取得。
 smgr = ctx.getServiceManager()  # サービスマネージャーの取得。 
 tcu = smgr.createInstanceWithContext("pq.Tcu", ctx)  # サービス名か実装名でインスタンス化。
 configurationprovider = smgr.createInstanceWithContext('com.sun.star.configuration.ConfigurationProvider', ctx)
 node = PropertyValue(Name = 'nodepath', Value = 'org.openoffice.Setup/Product' )  # share/registry/main.xcd内のノードパス。
 configurationupdateaccess = configurationprovider.createInstanceWithArguments("com.sun.star.configuration.ConfigurationUpdateAccess", (node,))
 tcu.wtree(configurationupdateaccess)
「サービスやインターフェイスに属しないプロパティ」 には参照しているノードのプロパティがでてきます。

├─.configuration.ConfigurationUpdateAccess
│   ├─.configuration.ConfigurationAccess
│   │   ├─.configuration.AccessRootElement
│   │   │   ├─.lang.XComponent
│   │   │   │     void  addEventListener( [in] .lang.XEventListener xListener)
│   │   │   │     void  dispose()
│   │   │   │     void  removeEventListener( [in] .lang.XEventListener aListener)
│   │   │   ├─.lang.XLocalizable
│   │   │   │     .lang.Locale  getLocale()
│   │   │   │             void  setLocale( [in] .lang.Locale eLocale)
│   │   │   └─.util.XChangesNotifier
│   │   │        void  addChangesListener( [in] .util.XChangesListener aListener)
│   │   │        void  removeChangesListener( [in] .util.XChangesListener aListener)
│   │   ├─.configuration.GroupAccess
│   │   │   ├─.beans.XMultiPropertyStates
│   │   │   │                      [any]  getPropertyDefaults( [in] [string] aPropertyNames
│   │   │   │                                       ) raises ( .lang.WrappedTargetException,
│   │   │   │                                                  .beans.UnknownPropertyException)
│   │   │   │     [.beans.PropertyState]  getPropertyStates( [in] [string] aPropertyName
│   │   │   │                                     ) raises ( .beans.UnknownPropertyException)
│   │   │   │                       void  setAllPropertiesToDefault()
│   │   │   │                       void  setPropertiesToDefault( [in] [string] aPropertyNames
│   │   │   │                                          ) raises ( .beans.UnknownPropertyException)
│   │   │   ├─.beans.XPropertyState
│   │   │   │                        any  getPropertyDefault( [in] string aPropertyName
│   │   │   │                                      ) raises ( .lang.WrappedTargetException,
│   │   │   │                                                 .beans.UnknownPropertyException)
│   │   │   │       .beans.PropertyState  getPropertyState( [in] string PropertyName
│   │   │   │                                    ) raises ( .beans.UnknownPropertyException)
│   │   │   │     [.beans.PropertyState]  getPropertyStates( [in] [string] aPropertyName
│   │   │   │                                     ) raises ( .beans.UnknownPropertyException)
│   │   │   │                       void  setPropertyToDefault( [in] string PropertyName
│   │   │   │                                        ) raises ( .beans.UnknownPropertyException)
│   │   │   └─.configuration.PropertyHierarchy
│   │   │     ├─.beans.XHierarchicalPropertySet
│   │   │     │     .beans.XHierarchicalPropertySetInfo  getHierarchicalPropertySetInfo()
│   │   │     │                                     any  getHierarchicalPropertyValue( [in] string aHierarchicalPropertyName
│   │   │     │                                                             ) raises ( .lang.WrappedTargetException,
│   │   │     │                                                                        .lang.IllegalArgumentException,
│   │   │     │                                                                        .beans.UnknownPropertyException)
│   │   │     │                                    void  setHierarchicalPropertyValue( [in] string aHierarchicalPropertyName,
│   │   │     │                                                                        [in]    any aValue
│   │   │     │                                                             ) raises ( .lang.WrappedTargetException,
│   │   │     │                                                                        .lang.IllegalArgumentException,
│   │   │     │                                                                        .beans.PropertyVetoException,
│   │   │     │                                                                        .beans.UnknownPropertyException)
│   │   │     ├─.beans.XMultiHierarchicalPropertySet
│   │   │     │     .beans.XHierarchicalPropertySetInfo  getHierarchicalPropertySetInfo()
│   │   │     │                                   [any]  getHierarchicalPropertyValues( [in] [string] aPropertyNames
│   │   │     │                                                              ) raises ( .lang.WrappedTargetException,
│   │   │     │                                                                         .lang.IllegalArgumentException)
│   │   │     │                                    void  setHierarchicalPropertyValues( [in] [string] aHierarchicalPropertyNames,
│   │   │     │                                                                         [in]    [any] Values
│   │   │     │                                                              ) raises ( .lang.WrappedTargetException,
│   │   │     │                                                                         .lang.IllegalArgumentException,
│   │   │     │                                                                         .beans.PropertyVetoException)
│   │   │     ├─.beans.XMultiPropertySet
│   │   │     │                        void  addPropertiesChangeListener( [in]                         [string] aPropertyNames,
│   │   │     │                                                           [in] .beans.XPropertiesChangeListener xListener)
│   │   │     │                        void  firePropertiesChangeEvent( [in]                         [string] aPropertyNames,
│   │   │     │                                                         [in] .beans.XPropertiesChangeListener xListener)
│   │   │     │     .beans.XPropertySetInfo  getPropertySetInfo()
│   │   │     │                       [any]  getPropertyValues( [in] [string] aPropertyNames)
│   │   │     │                        void  removePropertiesChangeListener( [in] .beans.XPropertiesChangeListener xListener)
│   │   │     │                        void  setPropertyValues( [in] [string] aPropertyNames,
│   │   │     │                                                 [in]    [any] aValues
│   │   │     │                                      ) raises ( .lang.WrappedTargetException,
│   │   │     │                                                 .lang.IllegalArgumentException,
│   │   │     │                                                 .beans.PropertyVetoException)
│   │   │     └─.beans.XPropertySet
│   │   │                              void  addPropertyChangeListener( [in]                         string aPropertyName,
│   │   │                                                               [in] .beans.XPropertyChangeListener xListener
│   │   │                                                    ) raises ( .lang.WrappedTargetException,
│   │   │                                                               .beans.UnknownPropertyException)
│   │   │                              void  addVetoableChangeListener( [in]                         string PropertyName,
│   │   │                                                               [in] .beans.XVetoableChangeListener aListener
│   │   │                                                    ) raises ( .lang.WrappedTargetException,
│   │   │                                                               .beans.UnknownPropertyException)
│   │   │           .beans.XPropertySetInfo  getPropertySetInfo()
│   │   │                               any  getPropertyValue( [in] string PropertyName
│   │   │                                           ) raises ( .lang.WrappedTargetException,
│   │   │                                                      .beans.UnknownPropertyException)
│   │   │                              void  removePropertyChangeListener( [in]                         string aPropertyName,
│   │   │                                                                  [in] .beans.XPropertyChangeListener aListener
│   │   │                                                       ) raises ( .lang.WrappedTargetException,
│   │   │                                                                  .beans.UnknownPropertyException)
│   │   │                              void  removeVetoableChangeListener( [in]                         string PropertyName,
│   │   │                                                                  [in] .beans.XVetoableChangeListener aListener
│   │   │                                                       ) raises ( .lang.WrappedTargetException,
│   │   │                                                                  .beans.UnknownPropertyException)
│   │   │                              void  setPropertyValue( [in] string aPropertyName,
│   │   │                                                      [in]    any aValue
│   │   │                                           ) raises ( .lang.WrappedTargetException,
│   │   │                                                      .lang.IllegalArgumentException,
│   │   │                                                      .beans.PropertyVetoException,
│   │   │                                                      .beans.UnknownPropertyException)
│   │   ├─.configuration.GroupElement
│   │   │   └─.container.XChild
│   │   │        .uno.XInterface  getParent()
│   │   │                   void  setParent( [in] .uno.XInterface Parent
│   │   │                         ) raises ( .lang.NoSupportException)
│   │   ├─.configuration.HierarchyAccess
│   │   │   ├─.beans.XExactName
│   │   │   │     string  getExactName( [in] string aApproximateName)
│   │   │   ├─.beans.XPropertySetInfo
│   │   │   │     [.beans.Property]  getProperties()
│   │   │   │       .beans.Property  getPropertyByName( [in] string aName
│   │   │   │                                ) raises ( .beans.UnknownPropertyException)
│   │   │   │               boolean  hasPropertyByName( [in] string Name)
│   │   │   ├─.container.XContainer
│   │   │   │     void  addContainerListener( [in] .container.XContainerListener xListener)
│   │   │   │     void  removeContainerListener( [in] .container.XContainerListener xListener)
│   │   │   ├─.container.XHierarchicalNameAccess
│   │   │   │         any  getByHierarchicalName( [in] string aName
│   │   │   │                          ) raises ( .container.NoSuchElementException)
│   │   │   │     boolean  hasByHierarchicalName( [in] string aName)
│   │   │   └─.container.XNameAccess
│   │   │     │        any  getByName( [in] string aName
│   │   │     │             ) raises ( .lang.WrappedTargetException,
│   │   │     │                        .container.NoSuchElementException)
│   │   │     │   [string]  getElementNames()
│   │   │     │    boolean  hasByName( [in] string aName)
│   │   │     └─.container.XElementAccess
│   │   │              type  getElementType()
│   │   │           boolean  hasElements()
│   │   ├─.configuration.HierarchyElement
│   │   │   ├─.beans.XProperty
│   │   │   │     .beans.Property  getAsProperty()
│   │   │   ├─.beans.XPropertyWithState
│   │   │   │          .uno.XInterface  getDefaultAsProperty()
│   │   │   │     .beans.PropertyState  getStateAsProperty()
│   │   │   │                     void  setToDefaultAsProperty()
│   │   │   ├─.container.XHierarchicalName
│   │   │   │     string  composeHierarchicalName( [in] string aRelativeName
│   │   │   │                           ) raises ( .lang.NoSupportException,
│   │   │   │                                      .lang.IllegalArgumentException)
│   │   │   │     string  getHierarchicalName()
│   │   │   └─.container.XNamed
│   │   │        string  getName()
│   │   │          void  setName( [in] string aName)
│   │   ├─.configuration.SetAccess
│   │   │   └─.configuration.SimpleSetAccess
│   │   │     ├─.configuration.XTemplateContainer
│   │   │     │     string  getElementTemplateName()
│   │   │     └─.util.XStringEscape
│   │   │           string  escapeString( [in] string aString
│   │   │                      ) raises ( .lang.IllegalArgumentException)
│   │   │           string  unescapeString( [in] string aEscapedString
│   │   │                        ) raises ( .lang.IllegalArgumentException)
│   │   └─.configuration.SetElement
│   │     └─.configuration.XTemplateInstance
│   │           string  getTemplateName()
│   ├─.configuration.GroupUpdate
│   │   └─.container.XNameReplace
│   │        void  replaceByName( [in] string aName,
│   │                             [in]    any aElement
│   │                  ) raises ( .lang.WrappedTargetException,
│   │                             .container.NoSuchElementException,
│   │                             .lang.IllegalArgumentException)
│   ├─.configuration.SetUpdate
│   │   └─.configuration.SimpleSetUpdate
│   │     ├─.container.XNameContainer
│   │     │     void  insertByName( [in] string aName,
│   │     │                         [in]    any aElement
│   │     │              ) raises ( .lang.WrappedTargetException,
│   │     │                         .container.ElementExistException,
│   │     │                         .lang.IllegalArgumentException)
│   │     │     void  removeByName( [in] string Name
│   │     │              ) raises ( .lang.WrappedTargetException,
│   │     │                         .container.NoSuchElementException)
│   │     ├─.lang.XMultiServiceFactory
│   │     │     .uno.XInterface  createInstance( [in] string aServiceSpecifier
│   │     │                           ) raises ( .uno.Exception)
│   │     │     .uno.XInterface  createInstanceWithArguments( [in] string ServiceSpecifier,
│   │     │                                                   [in]  [any] Arguments
│   │     │                                        ) raises ( .uno.Exception)
│   │     │            [string]  getAvailableServiceNames()
│   │     └─.lang.XSingleServiceFactory
│   │           .uno.XInterface  createInstance()
│   │           .uno.XInterface  createInstanceWithArguments( [in] [any] aArguments
│   │                                              ) raises ( .uno.Exception)
│   └─.configuration.UpdateRootElement
│     └─.util.XChangesBatch
│                       void  commitChanges()
│           .util.ChangesSet  getPendingChanges()
│                    boolean  hasPendingChanges()
├─.beans.XHierarchicalPropertySetInfo
│     .beans.Property  getPropertyByHierarchicalName( [in] string aHierarchicalName
│                                          ) raises ( .beans.UnknownPropertyException)
│             boolean  hasPropertyByHierarchicalName( [in] string aHierarchicalName)
├─.container.XHierarchicalNameReplace
│     void  replaceByHierarchicalName( [in] string aName,
│                                      [in]    any aElement
│                           ) raises ( .lang.WrappedTargetException,
│                                      .container.NoSuchElementException,
│                                      .lang.IllegalArgumentException)
└──(サービスやインターフェイスに属しないプロパティ)
           string  ooName
             long  ooOpenSourceContext
           string  ooSetupExtension
           string  ooSetupVersion
           string  ooSetupVersionAboutBox
           string  ooSetupVersionAboutBoxSuffix
           string  ooVendor
           string  ooXMLFileFormatName
           string  ooXMLFileFormatVersion

参考にしたサイト


Frame-Controller-Model Paradigm in OpenOffice.org - Apache OpenOffice Wiki
LibreOfficeで採用されているフレーム/コントローラ/モデルの解説。

Head-First-Design-Patterns/src/headfirst/designpatterns/combined/djview at master · bethrobson/Head-First-Design-Patterns · GitHub
Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本の462ページのJavaの実装例。

Object Model - Apache OpenOffice Wiki
ConfigurationUpdateAccessサービスのモデルの解説。

次の関連記事:LibreOffice5(53)Javaの例:ConfigExamplesをPythonにする その6

PR

0 件のコメント:

コメントを投稿