[PR]血液型で当たる無料占い:アナタと私の相性は?《無料診断》

XUL チュートリアル - 8.3 - RDF データソースを操作する
戻る 内容 リファレンス 進む

XUL チュートリアル - RDF データソースを操作する

このセクションでは、スクリプトを使って RDF を操作する方法を説明します。

XPCOM をもつ RDF データソース

テンプレートを使えば、RDF データソースからデータを抽出し、その内容に基づいて内容を作ることが可能です。しかし、データソースは、スクリプトから検査することができます。これによって、データソースの変更ができます。これは、例えば、新しいブックマークを追加するのに必要となります。テンプレートを使って作られた要素からデータソースを捉え、個々のリソースを取り出すことができます。

RDF に対する XPCOM インターフェースには数多くのインターフェースがあります。以下のリストは、関連するインターフェースの一部です。

nsIRDFService グローバル RDF サービス。RDF データソース内のリソースを一意に識別できるリソースオブジェクトを生成するのに使われる。
nsIRDFDataSource 組み込みか、RDF ファイルの RDF データソース。メソッドを使って、値の取得と参照ができる。
nsIRDFContainer RDF データソース内のコンテナノード。メソッドを使って、リソースの追加と削除ができる。
nsIRDFContainerUtils このインターフェースには、Seq、Bag、Alt リソースを作るためのハンディーなコンテナメソッドが幾つかある。

「ファイル検索」ダイアログに、項目の最新の検索結果を保存する機能が実装できます。サーチテキストボックスを、最も最近検索された項目リストからなる編集可能なドロップダウンによって置き換えることができるでしょう。この機能は、今、付け加えることにしましょう。

これは実際には、ダイアログが、最新の検索項目リストが保存されているディスクの場所にアクセスできる場合にだけ動作します。このリストがある可能性が高いのは、ユーザーのプロファイルディレクトリーかユーザー自身が選んだディレクトリーでしょう。ここでは行ないませんが、ユーザーのプロファイルディレクトリーは、nsIFileLocator インターフェースを使って検索できます。例を簡単にするため、ファイルパスを直接 XUL の datasources 属性に置くだけにしましょう。

最新の検索リストはプレーンテキストファイルに保存することもできます。しかし、RDF を使うこともできます。データを読み書きし、テンプレートから作り出されたウィジェットを自動的に更新するための機能が既にあります。まず、XUL ファイルを変更します。テキストボックスをドロップダウンリストで置き換えます。datasources 属性の値を適切なパスで置き換えて下さい。(ファイル自身は存在する必要はありません。データが保存されるとき、それは自動的に作られます。)

<menulist id="find-text" flex="1" style="min-width: 15em;"
          editable="true"
          datasources="file:///mozilla/recents.rdf"
          ref="urn:findfile:recent">
  <template>
    <menupopup>
      <menuitem label="rdf:http://www.example.com/recent#Label" uri="rdf:*"/>
    </menupopup>
  </template>
</menulist>

テンプレートが作り出した子供をもつ XUL 要素はすべて、nsIRDFDataSource を参照する database プロパティーをもちます。このオブジェクトは、使われているデータソースを読んだり、それを更新するのに使うことができます。database プロパティーは、datasources 属性をもつ要素に置かれます。これは、多くの場合 tree か、この場合のように menulist 要素です。

database プロパティーには、datasources 属性内で指定されたデータソースそれぞれのリスト (実際には、nsISimpleEnumerator) があります。これは、たった一つしかない場合でも、個々の要素で処理を繰り返す必要があるということです。以下の例は、この方法を示しています。ここでは、データソースが一つしかないと想定しています。

var dsource;
  var menulist=document.getElementById("find-text");
  var sources=menulist.database.GetDataSources();

  if (sources.hasMoreElements()){
    dsource=sources.getNext();
  }
  dsource=dsource.QueryInterface(Components.interfaces.nsIRDFDataSource);

まず、メニューリストへの参照を取得します。ここでは、find-text という id があると仮定しています。次に、メニューリストからデータソースのリストを取得します。nsISimpleEnumerator インターフェースには、2 つのメソッドがあります (これは、Java の Enumeration インターフェースに似ています)。列挙 (enumeration) 内の要素をループし、getNext メソッドを使ってそれを取得します (一つしかないという前提です)。最後に、それが nsIRDFDataSource であることを確かめるために QueryInterface を呼び出します。

最新の検索リストを作るために、これと似たコードを使います。しかし、まず、使いたいコンポーネントを初期化することにしましょう。コンポーネントが 3 つ必要です。リソースオブジェクトを作るのに、インターフェース nsIRDFContainer が使えます。3 つ目のインターフェースである nsIRDFContainerUtils は、ルートノードを作るために、最新の検索リストが最初に使われるときにだけ使用します。スクリプトファイル (findfile.js) の先頭に、次のコードを追加します。これは、「ファイル検索」ダイアログがロードされる時に実行されます。

var RDFC = '@mozilla.org/rdf/container;1';
RDFC = Components.classes[RDFC].getService();
RDFC = RDFC.QueryInterface(Components.interfaces.nsIRDFContainer);

var RDFCUtils = '@mozilla.org/rdf/container-utils;1';
RDFCUtils = Components.classes[RDFCUtils].getService();
RDFCUtils = RDFCUtils.QueryInterface(Components.interfaces.nsIRDFContainerUtils);

var RDF = '@mozilla.org/rdf/rdf-service;1'
RDF = Components.classes[RDF].getService();
RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);

このコードは、使う必要のある 3 つのサービスを作ります。シンタックスは、XPCOM オブジェクトを作るためのコードと似ています。最初の 3 行は、nsIRDFContainer オブジェクトへの参照を取得します。次に、nsIRDFContainerUtils オブジェクトを取得するため、同じ操作を行ないます。最後に、再び、nsIRDFService を繰り返します。

次に、初期化関数を作ります。これは、ウィンドウの onload ハンドラーから呼び出します。ウィンドウが表示されるときに、これは実行されます。このコード内には、上で作った RDF オブジェクトを初期化するコードを追加することにします。

findfile.xul:

<window onload="initSearchList()" ... >

findfile.js:

function initSearchList()
{
  var recentlist=document.getElementById("find-text");
  var sources=recentlist.database.GetDataSources();
  var rootnode=RDF.GetResource("urn:findfile:recent");
  
  while (sources.hasMoreElements()){
    try {
      dsource=sources.getNext();
      dsource=dsource.QueryInterface(Components.interfaces.nsIRDFDataSource);
  
      RDFC.Init(dsource,rootnode);
  
      return;
    } catch (e){}
  }

  RDFCUtils.MakeSeq(dsource,rootnode);
  RDFC.Init(dsource,rootnode);
}

initSearchList 関数を細かく見ていきましょう。

インターフェース nsIRDFService には、引数として渡された文字列からリソースオブジェクトを作ってくれる GetResource というメソッドがあります。このメソッドは、他のものの値を取得することはありません。それは、文字列を、データソースから値を取得するのに使えるリソースオブジェクトに変換するだけです。RDF インターフェースを参照する場合、文字列ではなくリソースを使います。GetResource が返す値は、nsIRDFResource 型です。

オブジェクトの初期化ができたので、これでオブジェクトのリソースの追加と削除ができます。リソースをコンテナに追加したいのか、それともリソースを別のリソースに追加したいのか (アサーション (assertion) と呼ばれます) に応じて必要となる 2 つのメソッドがあります。これら 2 つのケースは、ブックマークを追加するのか、それともタイトルや URL のようなプロパティーをブックマークに追加するのかに対応しています。

ユーザーが Find ボタンをクリックしたら、項目リストの検索結果に新しいエントリーを追加することにしましょう。幾つかの意味で、これは単純化しすぎています。まず、重複したエントリーのチェックをしたくないからであり、次に、リストの長さを制限することに関わりたくないからです。

doFind 関数内部から呼び出される別の関数を追加しましょう。

function doFind()
{
  var recentlist=document.getElementById("find-text");
  var fldval=document.getAnonymousNodes(recentlist)[1].value;

  addSearchedItem(fldval);

.
.
.

このコードは、メニューリストのテキストの値を取得します。通常は、このために 'recentlist.value' を使うだけですが、これはまだ実装されているとは思えません。このため、回り道をする必要があります。XBL のセクションで、このシンタックスが実際には何を意味しているのか説明します。テキストを、次に定義する関数 addSearchedItem に渡します。

function addSearchedItem(txt)
{
  var newnode=RDF.GetResource("urn:findfile:recent:item"+(RDFC.GetCount()+1));
  var labelprop=RDF.GetResource("http://www.example.com/recent#Label");
  var newvalue=RDF.GetLiteral(txt);
  
  dsource.Assert(newnode,labelprop,newvalue,true);
  RDFC.InsertElementAt(newnode,1,true);
  
  dsource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush();
} 

このコードは 3 つのことを行なっています。新しいリソースの追加、その値をもつ新しいアサーションの追加、変更されたデータソースの書き出しです。コードを細かく見ていきましょう。

必ずしもすべてのデータソースが更新できる訳ではありません。ファイルとリソース URL からロードされたすべてのデータソースは、内部データソースの幾つかと同様に出力できます。

「ファイル検索」ダイアログを開いて何かテキストを入力して Find を押すと、そのテキストがテキストドロップダウンの選択の一つになるのが分かるでしょう。作業を終了して再ロードしても、テキストはそのまま残ります。

重複したエントリーのチェックをするため、インターフェース nsIRDFDataSource の関数である hasAssertion や GetAllResources を使って既にあるリソースのチェックができます。


(進む) 次は、コピーと貼り付け操作のため、システムクリップボードにアクセスする方法を見ることにしましょう。

XUL チュートリアル - 8.3 - RDF データソースを操作する
戻る 内容 リファレンス 進む

[PR]〈特集〉内側からの美容法:うるおい美人の秘密を公開!キューサイ