[IM]コンテキストの内部実装

コンテキスト定義に従って、実際にページ合成を行うときに、クライアントの内部にコンテキストのオブジェクトを作ります。このオブジェクトは以下の3種類あります。

  • IMLibLocalContext:ローカルコンテキスト
  • IMLibContext:データベースから取り出したコンテキスト
  • IMLibContextPool:コンテキスト群を管理するオブジェクト

このうち、IMLibContextについては、new等、生成をして利用します。他の2つは1つだけでいいので(つまり、シングルトンでいいので)、そのまま使います。IMLibLocalContextについては、別の記事で説明しています。この記事では残りの2つを解説します。

IMLibContextは、エンクロージャ/リピーターの識別があるごとに1つのオブジェクトが生成されます。いくつかプロパティがあり、それぞれ動作上は細かい説明が必要かとは思いますが、まず、いちばん重要なプロパティは、storeとbindingです。いずれも多次元の連想配列、つまりオブジェクトのオブジェクトという形式になっています。1次元目はレコードを示すキーで、主キーフィールド名がid、そのフィールドの値が45なら「id=45」という文字列をキーとして仕様します。2次元目はフィールド名です。storeプロパティは、this.store[‘id=45’][‘birthday’]という要素に対して、その値が代入されています。

一方、bindingプロパティは、this.binding[‘id=45’][‘birthday’]という要素に対して、{id: id属性値, target: ターゲット}形式の配列になっています。階層の深いオブジェクトです。つまり、bindingは、あるレコードのあるフィールドの値を、ページ上のどの要素に設定したかを記録するものであり、id属性値とターゲットが必要です。また、複数の要素に値を設定することもあるので、オブジェクトの配列で記録しなければなりません。

さらに、要素のid属性とターゲットから、コンテキスト、レコード、フィールドを知るために、contextInfoというプロパティを用意しあり、this.contextInfo[id属性値][ターゲット]という要素に対して、{context: this, record: recKey, field: key} といったオブジェクトが保存されています。なお、ターゲットは””もあるので、その場合は”_im_no_target”に置き換えて記録します。

これらに直接アクセスして利用することも可能ですが、IMLibContextPoolでは生成したコンテキストすべてを把握していて、ここからコンテキストに対するさまざまな処理ができるようにメソッドを用意しています。これは一種のMediatorパターンです。

  • IMLibContextPool.getContextInfoFromId(id属性値, ターゲット)
    • 引数に指定したid属性値を持つ要素の指定したターゲットにバインドしているコンテキスト情報(キーとして、context、record、fieldを持つ)を返す
  • IMLibContextPool.contextFromName(コンテキスト名)
    • 引数に指定したコンテキスト名を持つコンテキスト(IMLibContextクラス)のうち、最初に見つかったものを返す
  • 《IMLibContext》.getValue = function (recKey, key)
    • コンテキスト内にある指定したレコード(”id=45″)とフィールド(”birthday”) の値を返す
  • 《IMLibContext》.getContextInfo = function (nodeId, target)
    •  引数に指定したid属性値を持つ要素の指定したターゲットにバインドしているコンテキスト情報(キーとして、context、record、fieldを持つ)を返す
  • 《IMLibContext》.getContextValue = function (nodeId, target)
    •  引数に指定したid属性値を持つ要素の指定したターゲットにバインドしているコンテキスト内での値を返す
  • 《IMLibContext》.setValue = function (recKey, key, value, nodeId, target)
    • コンテキストに値を設定する。nodeIdがnullの場合、最初から3つの引数(レコード、フィールド、値)により、値が記録されると同時に、同じレコードの同じフィールドを持つ他のコンテキストに対しても値の同期を行う。nodeIdとtargetを指定すると、値は自分のコンテキストにのみ設定し、同時にbindingなどの連携情報を設定する。通常はnodeIdはnullを指定してコンテキストへの設定と他のコンテキストへの同期処理をさせることが多いと思われる

 

IMLibContextPoolが記録している全てのコンテキストを得るには、プロパティのIMLibContextPool.poolingContextsを利用します。ここにコンテキストの配列が設定されています。