NSFItemScan関数の限界(その2) - Noteクラス - 「NotesPeek」をQtでリメイク

前回、同一文書内にある同名アイテムついて少し解説しました。それは、これからお話しするAPI関数、NSFItemScanの挙動に関係があるためです。

NSFItemScan関数は、文書内に含まれるアイテムを巡回し、アイテムごとにコールバック関数を呼び出してくれる関数です。

// nsfnote.h(再掲)

typedef STATUS (LNCALLBACKPTR NSFITEMSCANPROC)(
    WORD Spare,
    WORD ItemFlags,
    char far *Name, WORD NameLength,
    void far *Value, DWORD ValueLength,
    void far *RoutineParameter);

STATUS LNPUBLIC NSFItemScan (
    NOTEHANDLE hNote,
    NSFITEMSCANPROC ActionRoutine,
    void far *RoutineParameter);

既知の問題として、このコールバック関数でアイテムの内容を変更することはできません。ヘルプにもそう書いてあります。

The action routine can read the contents and properties of each field, but may not modify a field. This is because the action routine is passed the actual memory pointers of the field contents, and these should not be modified.

(機械翻訳) アクションルーチンは、各フィールドの内容とプロパティを読み取ることができますが、フィールドを変更することはできません。 これは、アクションルーチンがフィールドの内容の実際のメモリポインタを渡され、変更されるべきでないためです。 (APIリファレンスより)

これとは別に、次のような不具合が存在します。

この関数、一般的な文書では問題なく機能するのですが、実はこれ、「同名アイテムが存在する文書では、コールバック関数が呼び出される数と、アイテム数とで一致しない」ことが分かりました。以下の、画面ショットをご覧下さい。

f:id:takahide-kondoh:20170924200130p:plain

これは、同じ文書を展開したときの、NSFItemScan関数のデバッグ用出力結果(左)と、NSFinderの表示結果(中央)です。同じ文書を、Notesクライアントの文書プロパティで見ると、bodyフィールドは7つあるのがわかります。

f:id:takahide-kondoh:20170924201906p:plain

NotesPeekやNSFinderでは、添付ファイルを除くフィールド(アイテム)は、同名アイテムに分かれていた場合、1つにまとめられます。ところが、NSFItemScan関数をそのまま使ってしまうと、一つにまとめられるわけでもなく、かと言って同名アイテムの数分だけ呼び出してくれるわけでもなく、ここでは3回だけコールバックするという、なんとも不思議な動作結果が得られました。一体どういうことなんでしょうか。

このような結果が得られた以上、NSFItemScan関数に過剰な期待は禁物です。キーバリュー型のコンテナ(Map型など)を使ってアイテム名(フィールド名)だけをコレクションし、同じ名前が2つにならないようにして、集めた重複なしの名前の分だけ処理をするという方針にしなくてはいけないでしょう。

教訓:NSFItemScan関数はアイテム名を集めるだけに使用する

さて、次回以降ですが、Webアプリケーションの観点で短期的な連載を企画しています。Facebookでもつぶやきましたが、去る9月19日の「Notes/Domino Day 2017」でも発表がありました、「Domino Application on Cloud」が使えるようになると、これまでオンプレでしか利用できなかったNotesDBがクラウド上で使えるようになり、おそらくBluemixのようなPaaS環境との相互運用性が高まると予想されます。そこで、そのような環境を想定したWebアプリケーションのデモを考えています。来週に間に合うかな?間に合うといいな!乞うご期待でございます。

もちろん、その間にリメイクプロジェクトもパワーアップする予定です。