MailとRDF

Mozilla Mail は、その data 構造のほとんどを、いくつかの datasource を通して、RDF で表現します。これは、RDF Templateを使って、mailnews に特化した data を user interface で表現できるようにします。

このドキュメントを読む前に、RDFについて学ぶ必要があります。そうしないと、絶望的なほど混乱するでしょう。

Mail RDF graphの概要

全ての account, folder, message の root resource は、msgaccounts:/と名付けられたRDF Resourceです。 この resource から、server, folder, 最終的に message へと到達するいくつかの arc が続きます。最終的に、graph の中の node から mail filter, annotation などをおそらく見付けることができるでしょう。これがどうやって設定されるか1つの例をここで示します。:

1つの RDF graph のこの tree-style 表現において、arc はitalic、resources はboldで示します。

msgaccounts:/
    +-- http://home.netscape.com/NC-rdf#child -->
    |     imap://alecf@imap.mywork.com
    |   +-- http://home.netscape.com/NC-rdf#IsServer --> "true"
    |   +-- http://home.netscape.com/NC-rdf#child -->
    |         imap://alecf@imap.mywork.com/INBOX
    |       +-- http://home.netscape.com/NC-rdf#TotalMessages --> "4"
    |       +-- http://home.netscape.com/NC-rdf#IsServer --> "false"
    |       +-- http://home.netscape.com/NC-rdf#MessageChild -->
    |       |     imap_message://alecf@imap.mywork.com/INBOX#1
    |       +-- http://home.netscape.com/NC-rdf#MessageChild -->
    |       |     imap_message://alecf@imap.mywork.com/INBOX#2
    |       +-- http://home.netscape.com/NC-rdf#MessageChild -->
    |       |     imap_message://alecf@imap.mywork.com/INBOX#3
    |       +-- http://home.netscape.com/NC-rdf#MessageChild -->
    |             imap_message://alecf@imap.mywork.com/INBOX#4
    |       etc...          
    +-- http://home.netscape.com/NC-rdf#child -->
    |     mailbox://alecf@pop.mywork.com
    |   +-- http://home.netscape.com/NC-rdf#IsServer --> "true"
    |   +-- http://home.netscape.com/NC-rdf#child -->
    |         mailbox://alecf@pop.mywork.com/INBOX
    |       +-- http://home.netscape.com/NC-rdf#TotalMessages --> "2"
    |       +-- http://home.netscape.com/NC-rdf#IsServer --> "false"
    |       +-- http://home.netscape.com/NC-rdf#MessageChild -->
    |       |     mailbox_message://alecf@pop.mywork.com/INBOX#1
    |       +-- http://home.netscape.com/NC-rdf#MessageChild -->
    |             mailbox_message://alecf@pop.mywork.com/INBOX#2
    |       etc...          
      

もちろん、RDF で表現された property はもっと多くありますが、しかし、この例はその雰囲気を与えるでしょう。

Datasources

mail の中で使われるいくつか基本的な dataresource があります:
  • nsMsgAccountDataSource - は、msgaccounts:/ から出て来る arc について query に答えます。それを msgaccounts:/ の外の #child nodes のために尋ねるなら、account manager の全てのserver の root URI を返します。現在、返された URI の server については何も知らないことに注意しなさい。
  • nsMsgFolderDataSource - は、 toplevel の server folder を含んでいる mail folder の query に答えます。 #child arc に沿った1つの folder について尋ねるなら、その folder の中の全ての subfolder の resource を返すでしょう。 #MessageChild arc に沿った1つの folder について尋ねるなら、1つの folder の全ての message のための resource を返すでしょう。 message の総数、この folder は現在は root server かどうかなど、folder の様々な property についての query に答えるでしょう。
  • nsMsgMessageDataSource - は、folder の中の message についての query に答えます。 現在は、1つの message の全ての RDF property は、含んでいる folder を保存している database から来ます。

DatasourceとUI

Mail は、UI を datasource に"伝統的"な方法で接続していません。

全ての UI component に渡って共有された1つの singleton datasource を持つ代わりに、我々は per-view datasource を持ちます。 これは、それそれの datasource の view/window に特化した data を扱うために、それそれの template-base の widget を認めます。例えば,,,??? (sorting? そのほかに何かありましたっけ?)

それぞれの window の JavaScript が、javascript の source の中で datasource の variables を宣言することによって global な variable として load されるときに、Datasource は作られます。 document の onload= handler で、datasource は、それそれのRDF templateの親の element で、database property の設定することによって、それらの関連した widget に付けられます。

RDFへdataの反映

依存している content が変化したとき更新される1つの dynamic な UI を持つために、1つの datasource は、data を RDF へ反映する2つの key となる方法を実現しなければなりません。
  • query への応答: RDF が1つの resource について情報を尋ねるとき、datasource は query の結果を答えます。
  • RDF へ非同期に通知 data それ自身が変わるときに、RDF は通知される必要があります。

詳細

Queryの応答

Mail は、RDF Resource Factory を、mail に特化した情報を RDF resource に付加するために使います。(RDF Resource Factory の詳細は、現在、RDF documentation にあります。) RDF Resource から、QueryInterface()が、mail/news object に割り当てた後、それから情報にアクセスすることを可能にします。

例えば、folder の panel は INBOX の中の message の数を表示する必要があります。この column の情報は、tree のRDF Templateが、datasource の GetTarget() method を呼ぶときに、尋ねられます。この質問の target はmailbox://alecf@pop.myisp.com/INBOXと名付けられた resource でして、その property node は、http://home.netscape.com/NC-rdf#TotalMessagesと名付けられます。次は、舞台裏での基本的な振舞です。:

    var target = RDF.GetResource("mailbox://alecf@pop.myisp.com/INBOX");
    var property = RDF.GetResource("http://home.netscape.com/NC-rdf#TotalMessages");
    var resultNode = dataSource.GetTarget(target, property, true);
    

folder datasource の GetTarget() の中で, targetnsIMsgFolderへ QueryInterface 付けられます。 全てのmessages を得るために、datasource は nsIMsgFolder.GetTotalMessages()を呼ぶでしょう。最後に、この call の結果を1つのRDF Literalへ変換し、GetTarget() の戻り値として戻すでしょう。

これが datasource の内側でどのように働くか示す1つの例:

    var msgCountArc = RDF.GetResource("http://home.netscape.com/NC-rdf#TotalMessages");

    function GetTarget(target, property, unused) {
       var folder = target.QueryInterface(Components.interfaces.nsIMsgFolder);
       if (property == msgCountArc) {
           var msgCount = folder.GetTotalMessages(false);
           var result = RDF.GetLiteral(msgCount.toString());
           return result;
       }
    }
    

RDF の非同期な通知

ある mail object の data が変化したとき、そのデータは、datasource に登録された RDF の全ての observer に通知されて、RDF の中で反映されます。

mail folder の例で、それぞれの folder datasource は、始めにそれ自身を、mail session と共に、1つの nsIFolderListener として、登録します。なぜなら、それは1つの folder が変化したという情報を欲しているからです。 それぞれの template は、自分自身を、1つの RDF observer として、登録します。 folder の content、または、property が変化したとき、mail session に、folder listener に data が変化したことを通知することを伝えます。 folder datasource は、それらの property の変化を、OnAssert() または OnUnassert() の observer の呼出へ observer のために変換します。

呼出の流れは品質的には次のようです。:

登録:

  1. Folder datasource は自分自身を mail sesstion に folder listener として登録します。
  2. RDF Template は自分自身を datasource に content observer として登録します。
通知:
  1. Folder data が変化します。
  2. Folder は、mail session へその data が変化したことを通知します。
  3. Mail session は、folder listener へ folder が変化したことを通知します。
  4. Folder datasource は、RDF Content observers へその変化を通知します。
  5. Content observers は UI を更新します。
余談: この design の裏に隠れた合理性

この design をレビューしたとき、通知/登録を二重化することは必要ないように思えました。folder は、RDF Content observers に、何か変化したときに、なぜ直接通しないのでしょうか?

ここに、この design の裏に隠れた合理性があります。:

  • 全ての RDF datasource に関連した code を1箇所、それも、message や folder の場所以外の所にとどめます。 これは、mail code を、RDF から最も自由にします。 現在の RDF へ依存は小さいです。そして、RDF を folder や message の外にとどめることは道理にかなったことです。
  • folder の変化を通知するために RDF 以外用の mechanism がある必要があります。 我々が、RDF で行う必要の無い folder への通知を望んだ所(例えば、JavaScript/XUL から)がいくつかあります。 RDF を使うためにそれらの listener を要求することは、不必要な API を持った不必要で負荷の高いことでしょう。
  • folder、または mail session は、それぞれの datasource で、全ての RDF observer に知られる必要があるでしょう。これは、folder はそれらの observer のそれぞれに通知されなければならないことを意味します。 この design では、それぞれの datasource が、自身の observer を管理することを認めます。そして、それぞれのmail session が、folder listener の1つのリストを、RDF 的に関連しているそれらの listerner のいくつかを知る必要がなく、管理することを認めます。
コメントをどうぞ!
Alec Flett
Last modified: Thu Oct 7 11:33:42 PDT 1999
このドキュメントのオリジナルはmozilla.orgにおいて英語で公布されています。
またドキュメントの管理の言語は現在も英語です。この日本語訳は、
利用者の利便のためにmozilla.org 和訳プロジェクトによって提供されたものです。
フィードバックは英語で、元の著者に送って下さい。
翻訳された文書の一覧は、現在以下のURLで見ることが出来ます。
http://www.mozilla-japan.org/jp/td/index.html