ということで、昨日の続きです。
なんとなく enum を処理したくなったので、ルールを作るというのをやってみました。
説明がややこしくなるのがいやなので、boolean を使った、以下のようなものを考えてみました。
これに対応する Foo クラスは以下のようなものになります。
Digester の ObjectCreateRule は、デフォルトコンストラクタの存在を前提にしているので、Boolean オブジェクトを ObjectCreateRule で生成することはできません。
で、Boolean オブジェクトを生成するルールを作ってみます。
ルールクラスでは要素の開始タグを読み込んだときに実行される begin メソッド、要素内の XML テキストを読み込んだときに実行される body メソッド、要素の終了タグを読み込んだときに実行される end メソッドで構成されます。
今回の Boolean オブジェクトの場合、XML テキストを読み込むまで何もやることが無いので、begin メソッドはとりあえず気にしないで、body メソッドと、end メソッドだけを作りました。
で、これを使う方法は以下のようなコードになります。
今回は Boolean オブジェクト限定ということでオブジェクトの生成をべた書きにしてしまいましたが、ルールのコンストラクタにクラス名とクラスを生成するメソッド名を指定するようにして、リフレクションを使用して実行するようにすれば、enum 汎用のルールとして使えるようになると思います。
# 私は勉強中の身なもので、リフレクションの使い方を理解できていません。申し訳ありません。
後はおまけ。
ExtendedBaseRules を使って、ワイルドカード処理をやらせようとすると、ルールの適用順序がおかしくなるみたいです。
たとえば、
といったコードを書くと、本来は ObjectCreateRule の begin、SetNextRule の begin、SetNextRule の end、ObjectCreateRule の end という順序でメソッドが起動されるはず (でないととても困る) ですが、どうも順序が不定になるようです。
これが仕様なのか不具合なのかは調査できていませんが、結構つらいところがあります。
なんとなく enum を処理したくなったので、ルールを作るというのをやってみました。
説明がややこしくなるのがいやなので、boolean を使った、以下のようなものを考えてみました。
<element name="foo"> <complexType> <sequence> <element name="bar" minOccurs="0" type="boolean" /> </sequence> </complexType> </element>
これに対応する Foo クラスは以下のようなものになります。
public class Foo { private Boolean bar = null; public Boolean getBar() { return bar; } public void setBar(Boolean bar) { this.bar = bar; } }
Digester の ObjectCreateRule は、デフォルトコンストラクタの存在を前提にしているので、Boolean オブジェクトを ObjectCreateRule で生成することはできません。
で、Boolean オブジェクトを生成するルールを作ってみます。
public class BooleanCreateRule extends Rule { public void body(String namespace, String name, String text) { Boolean value = Boolean.valueOf(text); getDigester().push(value); } public void end(String namespace, String name) { getDigester().pop(); } }
ルールクラスでは要素の開始タグを読み込んだときに実行される begin メソッド、要素内の XML テキストを読み込んだときに実行される body メソッド、要素の終了タグを読み込んだときに実行される end メソッドで構成されます。
今回の Boolean オブジェクトの場合、XML テキストを読み込むまで何もやることが無いので、begin メソッドはとりあえず気にしないで、body メソッドと、end メソッドだけを作りました。
で、これを使う方法は以下のようなコードになります。
Digester digester = new Digester(); digester.addObjectCreate("foo", Foo.class); digester.addRule("foo/bar", new BooleanCreateRule()); digester.addSetNext("foo/bar", "setBar"); Foo foo = (Foo) digester.parse(...);
今回は Boolean オブジェクト限定ということでオブジェクトの生成をべた書きにしてしまいましたが、ルールのコンストラクタにクラス名とクラスを生成するメソッド名を指定するようにして、リフレクションを使用して実行するようにすれば、enum 汎用のルールとして使えるようになると思います。
# 私は勉強中の身なもので、リフレクションの使い方を理解できていません。申し訳ありません。
後はおまけ。
ExtendedBaseRules を使って、ワイルドカード処理をやらせようとすると、ルールの適用順序がおかしくなるみたいです。
たとえば、
Digester digester = new Digester(); digester.setRules(new ExtendedBaseRules()); digester.addObjectCreate("foo", Foo.class); digester.addObjectCreate("foo/?" Bar.class); digester.addSetNext("foo/?", "addBar");
といったコードを書くと、本来は ObjectCreateRule の begin、SetNextRule の begin、SetNextRule の end、ObjectCreateRule の end という順序でメソッドが起動されるはず (でないととても困る) ですが、どうも順序が不定になるようです。
これが仕様なのか不具合なのかは調査できていませんが、結構つらいところがあります。
※コメント投稿者のブログIDはブログ作成者のみに通知されます