当ブログに掲載しているサンプルは、すべて利用者の自己責任という形でお願いします。
ただし、明らかな不具合がある場合、ご連絡いただければ、訂正記事を出します。
また、こちらのサンプルは、別のサイト等への公開、転載は一切禁止しています。
どうしてもと言う場合は、筆者にあらかじめご連絡ください。

テクてく Lotus 技術者 Slack に参加しよう!

2015年8月13日木曜日

XPagesで日付の複数値を取り扱う場合は要注意

皆さん、こんにちは。


今日は2015年8月13日です。夏休み中という方も多いかと思いますが、私は仕事してます。
にほんブログ村 IT技術ブログへ
可哀そうに・・・と思ったら、上のボタンを押してください。



さて、今日もXPagesの話です。
そして、私の嫌いな?日付データの取り扱いについてです。


ノーツには「日付/時刻」型というフィールドタイプがあります。
このフィールドは「日付のみ」とか「時刻のみ」という形でデータを保存できます。
しかし、XPagesでは、そういった形式での保存が難しいです(できないわけではない)。

格納方法については、IBM ChampionのKazunori Tatsukiさんのブログに
XPagesでフィールドに”年月日のみ”、”時刻のみ”の値を設定する方法という形で掲載されています。


さて、これで一安心だ!と喜んでいたのですが、思わぬところで躓いてしまいました。

日付を格納しているフィールドを"複数値可"にしていたのです。
上記のブログにある日付フィールドの取得方法はNotesXSPDocumentのgetItemValueDateTimeという命令です。
これは、複数値の形式に対応していません。

困りましたね。
そこで、NotesXSPDocumentではなく、バックエンドクラスのNotesDocumentクラスの命令を使ってみることにしましょう。
NotesDocumentクラスには日付フィールドの値を取得するためのgetItemValueDateTimeArrayという命令があります。
こちらは、文書内の日付フィールド(アイテム)をjava.util.Vectorという配列のオブジェクトで返してくれます。
配列の一つ一つの要素はNotesDateTime型もしくはNotesDataRange型になります。
今回は、日付の範囲ではなく、単なる複数値なので、NotesDateTime型の配列になります。
取得できたら、iterator命令とwhile命令で配列の分繰り返し処理を行います(LotusScriptでいうところのForall関数と考えてください)。

フォームに「Hiduke1」という複数値を許可した日付/時刻フィールドがある場合の保存時の処理を書いてみました。
try {
    var notesDoc:NotesDocument = document1.getDocument( true );
    var hidukeArray = [];
    var dtArray:java.util.Vector = notesDoc.getItemValueDateTimeArray( "Hiduke1" );
    var iterator = dtArray.iterator();
    while (iterator.hasNext()) {
        var dt = iterator.next();
        if ( dt!= null ) {
            dt.setAnyTime();
            hidukeArray.push( dt );
        }
    }
    notesDoc.replaceItemValue( "Hiduke1", hidukeArray );
    notesDoc.save();
} catch ( e ) {
    print ( "エラー:" + e.toString() );
} finally {
    if ( dt != null ) dt.recycle();
    if ( notesDoc != null ) notesDoc.recycle();
}
context.redirectToPage( "viewDateTime" );


これを使ってXPagesで文書を保存した後、ノーツクライアントで文書のプロパティを確認した結果が下図です。
日付の複数値

確かに日付だけの複数値(リスト)として格納されています。

めでたしめでたし・・・
と思っていたのですが、新たな問題が発生しました!!

そもそも日付フィールドに値を入力しなかった場合にエラーになってしまうのです。

同じXPagesを使って日付を入力しないで保存したときのエラー画面です(面倒だったので、Dominoコンソールに吐き出すようにしました)
getItemValueDateTimeArrayでエラー発生

エラーは「Exception occurred calling method NotesDocument.getItemValueDateTimeArray(string)」となっています。どうやら例外として扱われたようです。
try ~ catch で組んでいるのでエラーをcatchしてくれたという事でしょう。
どうやら、値がnullは許可してくれないようです。


念のため、try ~ catch を外したソースで実行してみましたが、例外が発生するのは変わらずでした。
むしろ、エラーページが表示されてバグだろ!感が丸出しになりました。
try ~ catch なしでもエラーはエラー

どうしましょう・・・
ホントに困りました。



仕方なしに、ヘルプをもう一度よく読んでみました。
すると、NotesDocumentクラスで日付フィールドの値を取得する方法として、もう一つある事に気が付きました。
getItemValue命令です。
こちらは、指定したアイテムの値によって返してくれる値のデータ型を自動的に変更してくれるという賢い命令です。
日付の場合は、getItemValueDateTimeArrayと同じ、NotesDateTimeもしくはNotesDateRangeのjava.util.Vector型の配列で返してくれます。

うん、日付/時刻に至ってはまったく同じじゃないか。ダメだな、こりゃ・・・と思いましたが、モノは試し!ということで、ソースを変更してみました。

try {
    var notesDoc:NotesDocument = document1.getDocument( true );
    var hidukeArray = [];
    var dtArray:java.util.Vector = notesDoc.getItemValue( "Hiduke1" );
    var iterator = dtArray.iterator();
    while (iterator.hasNext()) {
        var dt = iterator.next();
        if ( dt!= null ) {
            dt.setAnyTime();
            hidukeArray.push( dt );
        }
    }
    notesDoc.replaceItemValue( "Hiduke1", hidukeArray );
    notesDoc.save();
} catch ( e ) {
    print ( "エラー:" + e.toString() );
} finally {
    if ( dt != null ) dt.recycle();
    if ( notesDoc != null ) notesDoc.recycle();
}
context.redirectToPage( "viewDateTime" );


ホントに、
var dtArray:java.util.Vector = notesDoc.getItemValueDateTimeArray( "Hiduke1" );


var dtArray:java.util.Vector = notesDoc.getItemValue( "Hiduke1" );

にしただけです。


しかし!
なんとまぁ、うまくいってしまいました。

つまり、
1.日付を入力しなくても正常に保存できる。
2.日付を一つだけ入力しても正常に保存できる。
3.日付を複数入力しても正常に保存できる。
のです。

当然、日付は日付のみの形で保存されています。

なんなんでしょう・・・

ヘルプをもう少し詳しく見てみると、
getItemValueの場合、「アイテムに値がない場合、このメソッドは空のベクトルを返します。」とあります。
どうやら、最初から値がない(null)を想定したつくりになっているようです。
getItemValueItemDateTimeArrayの説明には、そういったことは書いていませんので、値がないことは想定していなかったのかもしれません。

っていうか、それくらい想定しておけや!
と思いましたが、解決できたので、良し。としておきます。


あー、悩んだ悩んだ。

ということで、XPagesを使いましょう!
では、今日はこの辺で。






【PR】ノーツ/ドミノに関するお問い合わせは下記まで【PR】
単純なDBのカスタマイズから他アプリケーションとの連携までご要望にお応えします!
Lotus Notes/Domino カスタマイズとセキュリティ強化 - 株式会社エフ