JP4551899B2 - 随時接続アプリケーションサーバー - Google Patents
随時接続アプリケーションサーバー Download PDFInfo
- Publication number
- JP4551899B2 JP4551899B2 JP2006542905A JP2006542905A JP4551899B2 JP 4551899 B2 JP4551899 B2 JP 4551899B2 JP 2006542905 A JP2006542905 A JP 2006542905A JP 2006542905 A JP2006542905 A JP 2006542905A JP 4551899 B2 JP4551899 B2 JP 4551899B2
- Authority
- JP
- Japan
- Prior art keywords
- data
- xsd
- node
- server
- mas
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/20—Information retrieval; Database structures therefor; File system structures therefor of structured data, e.g. relational data
- G06F16/27—Replication, distribution or synchronisation of data between databases or within a distributed database system; Distributed database system architectures therefor
- G06F16/273—Asynchronous replication or reconciliation
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/20—Information retrieval; Database structures therefor; File system structures therefor of structured data, e.g. relational data
- G06F16/27—Replication, distribution or synchronisation of data between databases or within a distributed database system; Distributed database system architectures therefor
Description
2005年5月4日出願されたボスワース氏等の「OCCASIONALLY-CONNECTED APPLICATION SERVER」と題する米国特許出願第11/122,294号[代理人ドケットNo.BEAS−01537US1]
本発明の一実施形態は、XMLフォーマットのデータノードのローカルキャッシュ128と、ノードのタイプ及びノード間の関係を定義する随時接続データモデル115と、データノードの変更を許すアクションとを含む移動ユニット110である。
−関連データへのナビゲーションで、例えば、アカウントに関連したコンタクトを得る。
−CRUDオペレーション、即ちデータを生成し、読み取り、更新しそして削除する要求で、例えば、アカウントに関連したコンタクトを生成し、コンタクトの細部を更新し、又はコンタクトを削除することを要求する。
−あるデータに関連したエンタープライズにおいて行う必要があるが、データモデルに対して不透明なアクションである顧客オペレーションで、例えば、タスクをクローズすることを要求する。
データノードは、構造化データ(即ち、XML文書)を含むことができるが、トラバースに対して原子的であり、即ち一実施形態では、トラバースは、2つのノード間の特定の関係を表わすが、特定のノード内のデータを参照することも、別のノードを参照するノード内のデータを参照することもできない。
随時接続データモデルは、関係エンティティ及び関係(一次/外部キー)構造と同様のスキーマ及びkeyref宣言で構成することができる。
一例のCRMシステム(説明の目的で、本書全体にわたって参照される)は、リレーショナルデータベースを使用して実施される。図4に示すエンティティ関係ダイアグラム(ERD)400は、アカウント、コンタクト、事象、及びユーザエンティティを表わす。
CREATE TABLE account (
pkey INT NOT NULL PRIMARY KEY,
parentPkey INT FOREIGN KEY REFERENCES account(pkey),
ownerPkey INT FOREIGN KEY REFERENCES user(pkey),
name VARCHAR,
type CHAR
)
CREATE TABLE contact (
pkey INT NOT NULL PRIMARY KEY,
accountPkey INT NOT NULL FOREIGN KEY REFERENCES account(pkey),
ownerPkey INT FOREIGN KEY REFERENCES user(pkey),
first VARCHAR,
last VARCHAR,
email VARCHAR
)
CREATE TABLE user (
pkey INT NOT NULL PRIMARY KEY,
login VARCHAR
)
アカウントの一次キーpaが与えられると、次のSQLは、全てのコンタクトを選択する。
SELECT * FROM contact WHERE accountPkey = pa
SELECT account.* FROM account, contact
WHERE account.pkey = contact.accountPkey
AND contact.pkey = pc
SELECT * FROM account WHERE account.pkey = c.accountPkey
事象が多数のアカウント及びコンタクト(例えば、存在する2つのアカウントを満足するセール)に属することができると仮定する。これは、例えば、ジョインテーブルを使用してモデリングされる。
CREATE TABLE event (
pkey INT NOT NULL PRIMARY KEY,
title VARCHAR,
details VARCHAR
)
CREATE TABLE event_account (
eventPkey INT FOREIGN KEY REFERENCES EVENT(pkey),
accountPkey INT FOREIGN KEY REFERENCES ACCOUNT(pkey)
)
アカウントの一次キーpaが与えられると、次のSQL(ジョイン)は、全ての関係事象を選択する。
SELECT event.* FROM event, event_account
WHERE event_account.accountPkey = pa
AND event.pkey = event_account.eventPkey
SELECT account.* FROM account, event_account
WHERE event_account.eventPkey = pe
AND account.pkey = event_account.accountPkey
XMLスキーマは、アプリケーションにより使用されるデータモデルにおいてnodetypeを定義することができる。スキーマサブディレクトリーは、多数の.xsdファイルを含んでもよく、これらは全て始動時にフレームワークによりロードされる。
<?xml version=”1.0”?>
<xsd:schema targetNamespace=”http://example.com/”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:mas=”run:bea.com”
xmlns=”http://example.com/”>
...
<xsd:element name=”contact” type=”contactType”>
<xsd:annotation>
<xsd:appinfo>
<mas:nodeAnnotation>
<mas:label>$node.first + ” ” + $node.last</mas:label>
</mas:nodeAnnotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name=”contactType”>
<xsd:sequence>
<xsd:element name=”salutation” type=”contactSalutationEnum”/>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name=”contactSalutationEnum”>
<xsd:restriction base=”xsd:string”>
<xsd:enumeration value=”Mr”/>
<xsd:enumeration value=”Mrs”/>
<xsd:enumeration value=”Ms”/>
<xsd:enumeration value=”Dr”/>
</xsd:restriction>
</xsd:simpleType>
...
</xsd:schema>
<contact>
<salutation>Mr</salutation>
<first>Roger</first>
<last>Reed</last>
<email>roger@acme.com</email>
</contact>
随時接続データモデルは、全てのアプリケーションタイプに対して標準的なXMLスキーマ定義で構成することができる。これらスキーマは、他のXMLノードを参照するXMLエレメント及び属性を含むノードを定義することができる。これら参照の定義は、keyref宣言を使用して行うことができる。
キー定義は、一次キーを含む文書内の場所を定義することができる。例えば、次のキーは、accountKeyが各<account>エレメントにおいてidと称する属性として生じることを示している。
<xsd:key name=”accountKey”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:keyref name=”contactAccountRef” refer=”accountKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
タイプ及びインスタンス図
UMLを使用して、nodetype及びkeyref図を説明する。
図5は、同じCRMアプリケーションに関するUMLエンティティ関係図(ERD)500である。この図において、各エンティティは、アプリケーションnodetype(即ち、スキーマ)を表わす。ルートエンティティは、システムnodetypeであることに注意されたい。
ネームスペースの実施形態について以下に説明する。サーバープログラミングモデルは、ネームスペースを使用して、フレームワークとアプリケーションXMLエレメントとの間を区別することができる。ネームスペース定義は、XMLソースファイルの最上位レベルエレメント内の属性として含ませることができる。
xmlns:mas=”urn:bea.mas”
xmlns:app=”http://example.com/”
xmlns:ws=”http://www.openuri.org/”
xmlns:sfdc=”urn:partner.soap.sforce.com”
標準的なXSDスキーマ定義は、<xsd:appinfo>エレメント内でmasエレメントを宣言することにより拡張することができる。
<xsd:element name=”typeName” type=”type”>
<xsd:annotation>
<xsd:appinfo>
...
</xsd:appinfo>
<xsd:documentation>schema documentation</xsd:documentation>
</xsd:annotation>
</xsd:element>
mas:labelエレメントは、ノードに対するデフォールトラベルを宣言し、即ちストリングを構成するのに使用されるXPath表現を宣言する。この表現は、XMLノードオブジェクトの最上位レベルエレメントを参照する$node変数を任意に参照することができる。
シンタックス
<mas:label>spath-expression</mas:label>
次のラベル定義は、コンタクトの最初と最後のネームからストリングを構成する。
<xsd:element name=”contact” type=”contactType”>
<xsd:annotation>
<xsd:appinfo>
<mas:label>$node.first + ” ” + $node.last</mas:label>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<mas:label>first + ” ” + last</mas:label>
又、ラベル定義は、XScriptファンクション及び演算子を含んでもよい。
($node.first) + ($node.first.length() > 0 ? ” ” : ””) + $node.last
次のXMLスキーマは、アカウント及びコンタクトnodetypeを定義する簡単なアプリケーションデータモデルを記述する。
<xsd:schema ...>
<xsd:complexType name=”accountType”>
<xsd:all>
<xsd:element name=”name” type=”xsd:string”/>
<xsd:element name=”type” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”parentId” type=”xsd:string”/>
</xsd:complexType>
<xsd:complexType name=”contactType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”accountId” type=”xsd:string” use=”required”/>
</xsd:complexType>
<xsd:element name=”graph”>
<xsd:complexType>
<xsd:element name=”root” type=”mas:rootType”/>
<xsd:sequence>
<xsd:element name=”account” type=”accountType” maxOccurs=”unbounded”/>
<xsd:element name=”contact” type=”contactType” maxOccurs=”unbounded”/>
</xsd:sequence>
</xsd:complexType>
<xsd:key name=”accountKey”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:keyref name=”contactAccountRef” refer=”accountKey” mas:alias=”account”
mas:inverseAlias=”contacts”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
</xsd:element>
</xsd:schema>
上述したように、データモデルは、XMLスキーマ定義で構成される。次のスキーマは、アカウント及びコンタクトnodetypeを定義する。
<xsd:schema ...>
<xsd:complexType name=”accountType”>
<xsd:all>
<xsd:element name=”name” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”parentId” type=”xsd:string”/>
</xsd:complexType>
<xsd:complexType name=”contactType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/> <xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”accountId” type=”xsd:string” use=”required”/>
</xsd:complexType>
この実施例において、全てのタイプは、外部レコードの一次キーを表わす外部識別子idを定義することができ、又、contactタイプは、外部キーを表わす属性@accountIdも定義する。
<account id=”1.1”>
<name>Acme</name>
</account>
<contact id=”1.2” accountId=”1.1”>
<first>Bob</first>
<last>Harris</last>
<email>bob@acme.com</email>
</contact>
<contact id=”1.3” accountId=”1.1”>
<first>Maggie</first>
<last>Cheung</last>
<email>maggie@acme.com</email>
</contact>
データグラフ定義
随時接続データモデルは、デベロッパに対して仮想XML文書又はデータグラフとして表面化することができる。アプリケーションは、スキーマ及びkeyref宣言を指定することによりデータグラフの構造を定義する。
<xsd:complexType name=”rootType”/>
<xsd:element name=”root” type=”rootType”/>
<xsd:complexType name=”graphType”>
<xsd:sequence>
<xsd:element ref=”root”/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”graphType”>
<xsd:complexContent>
<xsd:extension base=”mas:graphType”>
<xsd:sequence minOccurs=”0” maxOccurs=”unbounded”>
<xsd:choice>
<xsd:element name=”nodeName” type=”nodeType”/>
</xsd:choice>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name=”graph” type=”graphType”>
<key-definitions>
<keyref-definitions>
</xsd:element>
<xsd:element name=”graph”>
<xsd:complexType>
<xsd:element name=”root” type=”rootType”/>
<xsd:sequence>
<xsd:element name=”account” type=”accountType” maxOccurs=”unbounded”/>
<xsd:element name=”contact” type=”contactType” maxOccurs=”unbounded”/>
</xsd:sequence>
</xsd:complexType>
グラフ構造は、その大部分が実施細部であり、デベロッパは、key/keyref定義を使用してデータグラフをトラバースすることに注意されたい。ここに提案する1つのグラフ実施は、フラットであり、即ち全てのnodetypeが、<graph>エレメントの第1レベルの子である。
<graph>
<account id=”1.1”>
<name>Acme</name>
</account>
<contact id=”1.2” accountId=”1.1”>
<first>Bob</first>
<last>Harris</last>
<email>bob@acme.com</email>
</contact>
<contact id=”1.3” accountId=”1.1”>
<first>Maggie</first>
<last>Cheung</last>
<email>maggie@acme.com</email>
</contact>
<graph>
又、スキーマ定義ファイルは、データタイプとデータタイプとの間の一次キー及び外部キーの関係を宣言することのできるkey及びkeyref定義も含むことができる。
key定義は、一次キーを定義することができる。キーは、多数のフィールド宣言(即ち、コンパウンドキーに対する)を含んでもよい。
例えば、次のkey及びkeyref定義は、コンタクトノードからその関係アカウントノードへの多対1(ルックアップ)関係と、ルートからアカウントへの1対多の関係とを定義する。
<xsd:key name=”accountKey”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:keyref name=”contactAccountRef” refer=”accountKey” mas:alias=”account”>
mas:inverseAlias=”contacts”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
</xsd:graph>
</xsd:schema>
<xsd:key name=”<schema>Key” ...
<xsd:keyref name=”<sourceSchema><element|attribute>Ref” ...
<xsd:keyref name=”contactAccountRef” refer=”accountKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
<xsd:keyref name=”messageFromRef” refer=”contactEmailKey”>
<xsd:selector xpath=”message”/>
<xsd:field xpath=”from”/>
</xsd:keyref>
<xsd:keyref name=”messageToRef” refer=”contactEmailKey”>
<xsd:selector xpath=”message/to”/>
<xsd:field xpath=”.”/>
</xsd:keyref>
フレームワークは、keyrefネームが最上位レベルエレメント属性ネームと衝突しないことを保証できる。
keyref宣言は、データグラフ内のノードとノードとの間のリーガルトラバースを定義することができる。@@演算子は、グラフをトラバースするのに使用できると共に、デフォールトにより、keyrefネームを使用する。しかしながら、エイリアスは、コードを読み易くするように定義されてもよい。
mas:alias=”[XPath:]name”
ここで、nameは、エイリアスネームを表わし、そして任意のXPathプレフィックスは、@@演算子及びエイリアスネームの前に入らねばならないSPath(グラフに対する)を表わす。即ち、
var refNode = srcNode.SPath.@@name
mass:alias=‘name’
次のXMLは、アカウントノードのインスタンスを表わす。
<account id=”1.1” type=”Web” ownerId=”bob”>
<name>Acme</name>
<events>
<eventRef>1.2</eventRef>
<eventRef>1.3</eventRef>
</events>
<purchaseOrders>
<purchaseOrder>
<lineItem><prodId>ABC-1234</prodId></lineItem>
<lineItem><prodId>XYZ-4321</prodId></lineItem>
</purchaseOrder>
</purchaseOrders>
</account>
<xsd:key name=”accountKey” mas:alias=”accounts”>
<xsd:selector xpath=”account ”/>
<xsd:field xpath=”@id”/>
</xsd:key>
var accounts = $root.@@accounts.*;
「製品」エイリアスは、次のように定義される。
<xsd:keyref name=”accountProductsRef” refer=”productKey” mas:alias=”product”>
<xsd:selector xpath=”account/purchaseOrders/purchaseOrder/lineItem”/>
<xsd:field xpath=”prodId”/>
</xsd:keyref>
var product = account.purchaseOrders.*[0].lineItems.*[0].@@product;
「所有者」エイリアスは、次のように定義される。
<xsd:keyref name=”accountOwnerRef” refer=”UserKey” mas:alias=”owner”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@ownerId”/>
</xsd:keyref>
var user = account.@@owner;
「事象」エイリアスは、次のように定義される。
<xsd:keyref name=”accountEventsRef” refer=”eventKey” mas:alias=”events”>
<xsd:selector xpath=”account/events/eventRef”/>
<xsd:field xpath=”.”/>
</xsd:keyref>
var events = account.@@events.*;
「製品」エイリアスも、次のように定義できることに注意されたい。
<xsd:keyref name=”accountProductsRef” refer=”productKey”
mas:alias=”account:products”>
<xsd:selector xpath=”account/purchaseOrders/purchaseOrder/lineItem”/>
<xsd:field xpath=”prodId”/>
</xsd:keyref>
var products = account.@@products.*;
逆の関係
keyref宣言は、逆方向のナビゲーションを可能にする逆keyrefを任意に定義することができる。通常、多対1のkeyrefは、逆の1対多のトラバーサルを可能にする逆keyrefを宣言する。
<xsd:keyref name=”name” refer=”keyName” mas:alias=”alias”
mas:inverseAlias=”inverseAlias”>
例えば、以下のkeyref定義は、contact→account及びaccount→contact関係を表わす。
<xsd:keyref name=”contactAccountRef” refer=”accountKey” mas:alias=”account”
mas:inverseAlias=”contacts”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
var account = contact.@@accountId;
逆の関係は、外部キーを使用してアカウントノードからコンタクトノードへトラバースできることを示す。即ち、
var contacts = account.@@contacts.*;
多数のkeyref定義は、同じnodetypeに「戻るように指す」逆の関係を宣言してもよいことに注意されたい。これらの場合に、逆のエイリアスは、当然、ターゲットnodetypeに対して独特のものでなければならない。例えば、bugノードは、bugs及びassignedBugsの逆のエイリアスを各々定義するowner及びassignedToに対するkeyrefを有してもよい。
ルートkeyref
外部キーの値に依存しないノード間の関係を定義することができる。例えば、現在ユーザ情報又は他の外部情報(例えば、日時、リアルタイムデータ、外部システム状態)を使用する問合せにより1組のノードを定義することができる。これらの場合に、nodesetをデータモデル内の任意のnodetypeにアタッチすることができる。しかしながら、通常、これらのnodesetは、ルートノードにアタッチされる。
var accounts = $root.@@accounts.*;
<xsd:keyref name=”accountRootRef” refer=”mas:rootKey”
mas:inverseAlias=”accounts”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@rootId”/>
</xsd:keyref>
<xsd:complexType name=”accountType”>
<xsd:all>
<xsd:element name=”name” type=”xsd:string”/>
<xsd:element name=”type” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string”/>
<xsd:attribute name=”parentId” type=”xsd:string”/>
<xsd:attribute name=”rootId” type=”mas:rootId” use=”optional”/>
</xsd:complexType>
<xsd:import namespace=”urn:bea.mas” schemaLocation=”mas.xsd”/>
ナビゲーションは、ページフロー内であるページから次のページへ移動するアクションである。これは、$contextシステム変数を変化してもよいし、しなくてもよい。
トラバースは、データグラフ(キャッシュ)内を移動するアクションである。SPath表現は、例えば、@@演算子を使用してグラフを「トラバース」する。
foo.@@bar
但し、fooは、ノード(又はノードの子エレメント)を表わし、そしてbarは、keyref定義(ネーム又はエイリアス)又はキーエイリアスにより外部キーであると定義された子エレメントのネームである。
<account id=”1.1” type=”Web”>
<name>Acme</name>
<contacts>
<contactRef>1.2</contactRef>
<contactRef>1.3</contactRef>
</contacts>
<purchaseOrders>
<purchaseOrder>
<lineItem @prodId=”ABC-1234”/>
<lineItem @prodId=”XYZ-3000”/>
<lineItem @prodId=”EOW-2004”/>
</purchaseOrder>
<purchaseOrder>
<lineItem @prodId=”XYZ-3000”/>
</purchaseOrder>
</purchaseOrders>
</account>
<contact id=”1.2” accountId=”1.1”>
<email>bob@acme.com</email>
</contact
<product id=”ABC-1234”>
<price>1000.00</price>
</product>
次のkeyref定義:
<xsd:keyref name=”accountContactsRef” refer=”contactPrimaryKey”
mas:alias=”.:contacts”>
<xsd:selector xpath=”account/contacts/contactRef”/>
<xsd:field xpath=”.”/>
</xsd:keyref>
<xsd:keyref name=”accountProductsRef” refer=”productKey”
mas:alias=”purchaseOrders/purchaseOrder/lineItem:product”>
<xsd:selector xpath=”account/purchaseOrders/purchaseOrder/lineItem”/>
<xsd:field xpath=”@prodId”/>
</xsd:keyref>
var contacts = account.contacts.*.@@contactRef;
var price = account.purchaseOrders.*[0].lineItems.*[0].@@(@prodId).price;
var contacts = account.@@contacts.*;
var email = account.@@contacts[0].email;
var price = account.purchaseOrders.*.lineItems.*[0].@@product.price;
データモデルにおいてノードとして表わすことのできる全ての外部レコードは、独特の一次キー(pkey)を定義しなければならず、即ち一次キーは、ウェブサービスSOAPインターフェイスの一部分として露出されねばならない。一実施形態では、一次キーは、全てのユーザに対しオペレーション呼び出しにわたって一貫したものとなる。というのは、ある場合に、フレームワークが、1人のユーザにより得たデータを共有キャッシュに配置できるからである。
<xsd:complexType name=”contactType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”timestamp” type=”xsd:string” mas:type=”seq”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”accountId” type=”xsd:string” use=”required”/>
</xsd:complexType>
<app:contact id=”83FEB4C38AB36520” timestamp=”12388832”
accountId=”B3F234AD3342ABA6”>
<app:first>Bob</app:first>
<app:last>Harris</app:last>
<app:email>bob@harris.com</app:email>
</app:contact>
<xsd:key name=”contactPrimaryKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”id”/>
</xsd:key>
<xsd:key name=”contactEmailKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”email”/>
</xsd:key>
キーの値は長くてもよいので、デフォールトにより、これらの値は、クライアントにも送信されないし、クライアントプログラミングモデルによりアクセスされることもない。mas:visible属性は、このデフォールト振舞いを抑制するように指定されてもよい。
var x = contact.id; // returns null
var y = cont
var contact =
<contact>
<first>Maggie</first>
<last>Cheung</last>
<email>maggie@acme.com</email>
</contact>
外部キーの値は、指定によりセットすることができる。指定表現のRHSがノードに対して評価する場合、これは、ノードの一次キーへと自動的に強制される。
以下に実施例では、コンタクトノードのアカウント外部キー(アカウントkeyref定義によりアカウント属性となるように定義される)が、供給されたアカウントノードを参照するようにセットされる。
function setAccount(contact, account)
contact.@@accountId = account;
}
keyref定義により参照されるスキーマがmas:visible一次キーを宣言する場合に、それに対応する外部キー値は、文字通りの値(即ち、ノード参照ではない)によってセットされてもよい。
例えば、次のアカウントスキーマは、可視pkey属性を定義する。
<xsd:complexType name=”accountType”>
<xsd:complexContent>
<xsd:all>
<xsd:element name=”name” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required”
mas:type=”pkey” mas:visible=”true”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”parentId” type=”xsd:string”/>
</xsd:complexContent>
</xsd:complexType>
var account = account.@@id;
又、値によりアカウントノードを参照する外部キーをセットしてもよく、例えば、
function setAccount(contact)
contact.@@account = ”A-1234”;
}
関係
多対1(ルックアップ)
多対1の関係は、関係一次及び外部キーを並行して生じるkey及びkeyref定義を使用して実施することができる。
<xsd:key name=”accountKey”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:keyref name=”contactAccountRef” refer=”accountKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
例えば、次のインスタンスデータが与えられる。
<account id=”1.1”>
<name>Acme</name>
</account>
<contact id=”1.2” accountId=”1.1”>
<first>Bob</first>
<last>Harris</last>
<email>bob@acme.com</email>
</contact>
<account id=”1.1”>
次は、コンタクトから同じアカウントへの外部キー(即ち、contactAccountRef)を定義する。
<contact id=”1.2” accountId=”1.1”>
<xsd:complexType name=”messageType”>
<xsd:sequence>
<xsd:element name=”from” type=”xsd:string” minOccurs=”1” maxOccurs=”1”/>
<xsd:element name=”to” type=”xsd:string” maxOccurs=”unbounded”/>
<xsd:element name=”subject” type=”xsd:string”/>
<xsd:element name=”body” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”contactType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”accountId” type=”xsd:string” use=”required”/>
</xsd:complexType>
<xsd:key name=”contactPrimaryKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:key name=”contactEmailKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”email”/>
</xsd:key>
<xsd:keyref name=”messageFromRef” refer=”contactEmailKey”>
<xsd:selector xpath=”message”/>
<xsd:field xpath=”from”/>
</xsd:keyref>
<xsd:keyref name=”messageToRef” refer=”contactEmailKey”>
<xsd:selector xpath=”message/to”/>
<xsd:field xpath=”.”/>
</xsd:keyref>
<xsd:keyref name=”messageFromRef” refer=”contactEmailKey”>
<xsd:selector xpath=”message/from”/>
<xsd:field xpath=”.”/>
</xsd:keyref>
1対多の関係は、逆keyrefとして実施することもできるし、又はデータノード内に含まれたマニフェスト外部キー値として実施することもできる。
逆Keyref
全ての多対1トラバースは、1対多のトラバースを定義する逆keyrefを宣言してもよい。
あるnodetypeのスキーマ宣言は、外部キー値を各々含むエレメントの中継シーケンスを含む複雑なXML文書を定義してもよい。
例
以下のスキーマ定義は、購入注文エンティティを記述する。
<xsd:element name=”purchaseOrder” type=”purchaseOrderType”>
<xsd:complexType name=”purchaseOrderType”>
<xsd:sequence>
<xsd:element name=”price” type=”xsd:double”/>
...
<xsd:complexType name=”lineItems”>
<xsd:sequence maxOccurs=”unbounded”>
<xsd:complexType ref=”lineItem”>
<xsd:sequence>
<xsd:element name=”prodId” type=”xsd:string”/>
...
</xsd:sequence>
</xsd:complexType>
</xsd:sequence>
</xsd:complexType>
</xsd:sequence>
<xsd:attribute name=”id” type=”xsd:string” mas:type=”pkey”/>
</xsd:complexType>
<xsd:key name=”purchaseOrderKey”>
<xsd:selector xpath=”purchaseOrder”/>
<xsd:field xpath=”id”/>
</xsd:key>
以下のkeyref宣言は、製品を参照する外部キーである購入注文内のエレメントを識別する。
<xsd:keyref name=”purchaseOrderProductRef” refer=”productKey”
mas:alias=”purchaseOrder:products”>
<xsd:selector xpath=”purchaseOrder/lineItems/lineItem”/>
<xsd:field xpath=”prodId”/>
</xsd:keyref>
var product = purchaseOrder.@@products.*;
多対多
多対多の関係は、1対多の関係の対として実施される。その一例が図12Bに示されている。
即ち、アカウント及び事象は、次のスキーマを宣言する。
<xsd:complexType name=”accountType”>
<xsd:all>
<xsd:element name=”name” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”parentId” type=”xsd:string”/>
</xsd:complexType>o0
<xsd:complexType name=”eventType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
</xsd:complexType>
<xsd:keyref name=”accountEventRef” refer=”eventKey”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”events”/>
</xsd:key>
<xsd:keyref name=”eventAccountRef” refer=”accountKey”>
<xsd:selector xpath=”event”/>
<xsd:field xpath=”accounts”/>
</xsd:keyref>
1対1
一実施形態において、1対1の関係は、対にされた多対1の関係として実施される。
例
又、システムの各ユーザは、図12Cに示すコンタクトレコードも有すると仮定する。
即ち、コンタクト及びユーザは、次のkeyrefを定義する。
<xsd:keyref name=”userContactRef” refer=”contactKey” mas:alias=”contact”
mas:inverseAlias=”user”>
<xsd:selector xpath=”user”/>
<xsd:field xpath=”@contactId”/>
</xsd:key>
1対1のkeyrefは、常に、逆keyrefを宣言しなければならない。
var contact = user.@@contact;
contact.@@user == user;
ノードスキーマ定義
次のXMLスキーマは、ノードの構造を定義する。
<?xml version=”1.0”?>
<xsd:schema targetNamespace=”urn:bea.mas”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns=”urn:bea.mas”>
<xsd:element name=”nodeType”>
<xsd:complexType>
<xsd:sequence>
<xsd:any minOccurs=”0” maxOccurs=”1”/>
</xsd:sequence>
<xsd:attribute name=”state” type=”mas:syncStateType”/>
</xsd:complexType>
</xsd:element>
一実施形態において、各アプリケーションに対して、nodetype mas:rootをもつ特殊なルートノードがあり、このノードは、アプリケーションデータを含まず、そして変更されることがない。フレームワークは、$root変数を経て参照されるルートノードのインスタンスを自動的に生成する。keyrefは、mas:rootをそれらのソースタイプとして参照してもよく、例えば、次の通りである。
<keyref name=”accounts” sourceType=”mas:root” targetType=”app:contact”/>
nodesetスキーマ定義
ルートノードはさておき、全てのノードは、keyrefに対応するnodesetに属する。nodesetは、次のXMLスキーマにより定義される。
<?xml version=”1.0”?>
<xsd:schema targetNamespace=”run:bea.com”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns=”run:bea.com”>
<xsd:element name=”nodeSet”>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref=”node” maxOccurs=”unbounded”/>
</xsd:sequence>
<xsd:attribute name=”keyref” type=”xsd:string”/>
</xsd:complexType>
</xsd:element>
同期状態
全ての持続性アプリケーションデータは、サーバーで同期されるノードに記憶することができる。各データノードは、syncStateTypeタイプにより定義される値を有する状態同期属性mas:stateをもつことができる。
<xsd:simpleType name=”syncStateType”>
<xsd:restriction base=”xsd:string”>
<xsd:enumeration value=”dsync”/>
<xsd:enumeration value=”modified”/>
<xsd:enumeration value=”pending”/>
<xsd:enumeration value=”uptodate”/>
<xsd:enumeration value=”rejected”/>
<xsd:enumeration value=”conflict”/>
<xsd:enumeration value=”deleted”/>
</xsd:restriction>
</xsd:simpleType>
一実施形態において、状態変数は、生成されたノードと変更されたノードとの間を区別しないことに注意されたい。というのは、これは、ゼロのグローバルシーケンスナンバーにより区別できるからである。
一実施形態において、クライアントアプリケーションは、ウェブサービスオペレーションを直接コールせず、むしろ、コンジットメカニズムが、個々の(限定された)ウェブサービスオペレーションのセマンティックスを、クライアントの仮想XML文書に対してプログラミングモデルへマップする(例えば、CRUDセマンティックス(生成、読み取り、更新、削除)、ナビゲーション、顧客オペレーション等)。クライアントデータモデルの変化は、サーバーに対して同期され、サーバーは、次いで、コンジットマネージャーをトリガーして、外部のウェブサービスオペレーションを呼び出す。
コンジットフローの概要
conduitsサブディレクトリーは、多数の.jsxファイルを含むことができ、それらは全て始動時にフレームワークによりロードされ、これらのファイルは、コンジット定義を含む。コンジットファイルは、コンジットオペレーションを実施するXScript及びXQueryファンクションで構成することができ、又、これらファイルは、コメントブロックで定義されたメタデータも含むことができる。注釈モデルは、デベロッパが視覚ツール及びスクリプトエディタの両方を使用してコンジットファイルを構築できるようにする。
例:
/**
* @mas:conversational shared=”false”
* @common:xmlns namespace=”http://schemas.xmlsoap.org/soap/envelope/” prefix=”soap”
* @common:xmlns namespace=”urn:partner.soap.sforce.com” prefix=”sfdc”
* @common:xmlns namespace=”http://example.com/” prefix=”app”
*/
又、コンジットファイルは、ウェブサービスコントロールを表わす(おそらく多数の)オブジェクト宣言も含む。コントロール定義は、対応する変数宣言の直前でヘッダーブロックに現われる。
例
/**
* @common:control
* @jc:location http-url=”http://enterprise.soap.sforce.com/”
*/
ws = new WebServiceControl();
次のタグが定義される。
jc:location
jc:locationタグは、次の属性を有する。
WebServiceControlオブジェクトは、ウェブサービスオペレーションの呼び出しをマネージする。
メッセージオブジェクト
メッセージオブジェクトは、ウェブサービスコントロールのinvoke()ファンクションへ通され及びそこから返送される。
var. Response = control. Invoke (message);
メッセージオブジェクトは、次のプロパティを有する。
<soapenv:Envelope xmlns:SOAP-ENC=”http://schemas.xmlsoap.org/soap/encoding/”
xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
<soapenv:Header>
<SessionHeader xmlns=”urn:partner.soap.sforce.com”>
<sessionId>12345678</sessionId>
</SessionHeader>
</soapenv:Header>
<soapenv:Body>
<createResponse xmlns=”urn:partner.soap.sforce.com”>
<result>
<errors xsi:nil=”true”></errors>
<id>87654321</id>
<success>true</success>
</result>
</createResponse>
</soapenv:Body>
</soapenv:Envelope>
function select($msg) {
var response = ws.invoke($msg);
if (! response.error) {
print(”Session: ” + response.header.SessoinHeader.sessionId);
print(”ID: ” + response.body.createResponse.result.id);
}
return response;
}
これは、次の出力をログする。
Session: 12345678
ID: 87654321
コンジットオペレーションは、ウェブサービスオペレーションへ直接マップすることができる。一実施形態では、各コンジットオペレーションは、次の3つのファンクションまで宣言する。
1.要求変換:出て行くメッセージ本体を生成するXQueryファンクション;
2.応答変換:到来する応答本体を処理し、コンジットマネージャーにより処理されたMASノードを生成するXQueryファンクション;
3.カスタムファンクション:カスタム手順ロジックを実行する(例えば、メッセージヘッダーを生成し、又はカスタムトランスポート又は他のコントロールを呼び出すために)XScript(又はJava(登録商標。以下同じ。))ファンクション。
カスタムファンクションは、ファンクションプロートタイプの直前でヘッダーブロックに注釈も含む。例えば、
/**
* @mas:operation type=”operationType” keyref=”keyrefName” inverse=”true”
* @mas:transform type=”request” function=”foo_request”
* @mas:transform type=”response” function=”foo_response”
*/
function foo($msg, $source) {
return ws.invoke($msg);
}
@mas:operation type=”operationType” keyref=”keyrefName”
@mas:operation type=”operationType” node=”nodeType”
inverse属性は、オペレーションが逆のkeyrefにおいてコールされることを指示する。
@mas:operation type=”operationType” keyref=”keyrefName” inverse=”true”
<xsd:keyref name=”contactAccountRef” refer=”accountKey”
mas:alias=”account” mas:inverseAlias=”contacts”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@account”/>
</xsd:keyref>
<xsd:key name=”accountKey”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:key name=”contactKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@id”/>
</xsd:key>
/** @mas:operation type=”select” keyref=”app:contactAccountRef” */
function selectAccount($msg, $source) {
return ws.invoke($msg);
}
/** @mas:operation type=”select” keyref=”app:contactAccountRef” inverse=”true” */
funciton selectContacts($msg, $source) {
return ws.invoke($msg);
}
mas:transform
mas:transformタグは、次の属性を有する。
Javaでは、要求及び応答の問合せ変換が、カスタムオペレーションのためのコメントブロック(自動的に発生される)内に含まれるか、又は注釈により参照される個別のファイルに含まれる。
カスタムファンクションの本体は、WLWにより発生される。セレクトオペレーションに対するデフォールト本体は、次の通りである。
/**
* @mas:operation type=”select” keyref=”keyrefName”
*/
function operationTypeSourceType($msg, $source) {
return control.invoke($msg);
}
/**
* @mas:operation type=”insert|update|delete” keyref=”keyrefName”
*/
function operationTypeSourceType($msg, $node) {
return ws.invoke($msg);
}
$node変数は、挿入/更新/削除されるべきノードを含む。
/**
* @mas:operation type=”custom” node=”nodeName” name=”operationName”
*/
function operationTypeSourceType($msg, $source, $node) {
return ws.invoke($msg);
}
ここで、$node変数は、カスタムオペレーションをコールするクライアントにより生成された問合せオブジェクトを含む。
オペレーションは、任意であるが、mas:transform注釈を使用して要求及び応答変換ファンクションを定義することができる。
例えば、以下のオペレーションは、アカウント識別子(即ち、contactAccountRefにより定義された逆keyref)が与えられると、コンタクトを検索するセレクトオペレーションを実施する。
/**
* select contacts for an account: $account.@@contacts.*
* @mas:operation type=”select” keyref=”app:contactAccountRef” inverse=”true”
* @mas:transform type=”request” function=”selectContacts_request”
* @mas:transform type=”response” function=”selectContacts_response”
*/
function selectContacts($msg, $source) {
return ws.invoke($msg);
}
/**
* @mas:namespace target=”sfdc”
* @language:body type=”xquery”
*/
function selectContacts_request($source) {
<query>
<queryString>
SELECT * FROM Contact
WHERE AccountId = ”{string($source/@id)}”
</queryString>
</query>
}
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function selectContacts_response($response) {
for $i in $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
}
コンジットオペレーション
コンジットオペレーションは、ウェブサービスオペレーションをフレームワークオペレーションへマップすることができ、このフレームワークオペレーションがアプリケーションプログラミングモデルへ露出される。
クライアントプログラミングモデルでは、ノード($rootを含む)又はkeyrefのいずれかにおいてオペレーションを呼び出すことができる。例えば、
$root.create(xml); // create node
node.@@keyref.create(xml); // create and link node
node.@@keyref.*; // implicit select
node.@@keyref.select(spath); // deep select
node.update(); // update node
$root.foo(xml); // custom operation
更新及び削除を除いて、他の全てのオペレーションにはオペレーションのコンテクスト(又はソース)を表わすノード(その一部分)が通される(mas:field宣言は、ソースノードのどれほど多くがサーバーに転送されるか決定する)。これは、$source変数を使用してコンジットファンクションにより参照される。
各コンジットオペレーションは、関連ウェブサービスオペレーションから受信され及びそれに送信される到来する及び出て行くXMLメッセージに対応するXMLオブジェクトを生成して処理する一対の問合せ(変換)を定義することができる。
変換は、XQuery(XML Query)ファンクションとして実施することができる。
次のオペレーションは、アカウント識別子(即ち、contactAccountRefにより定義された逆keyref)が与えられると、コンタクトを検索するセレクトオペレーションを実施する。
/**
* select contacts for an account: $account.@@contacts.*
* @mas:operation type=”select” keyref=”app:contactAccountRef” inverse=”true”
* @mas:transform type=”request” function=”selectContacts_request”
* @mas:transform type=”response” function=”selectContacts_response”
*/
function selectContacts($msg, $source) {
return ws.invoke($msg);
}
/**
* @mas:namespace target=”sfdc”
* @language:body type=”xquery”
*/
function selectContacts_request($source) {
<query>
<queryString>
SELECT * FROM Contact
WHERE AccountId = ”{string($source/@id)}”
</queryString>
</query>
}
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function selectContacts_response($response) {
for $i in $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
}
要求変換は、フレームワーク及びデータモデルエレメントから出て行くウェブサービスメッセージを生成することができる。オペレーションタイプに基づいて(上記のオペレーションテーブルを参照)、変換は、オペレーションに対するコンテクストを与える次のシステム変数を参照することができる。
...
<element name=”query”>
<complexType>
<sequence>
<element name=”queryString” type=”xsd:string”/>
</sequence>
</complexType>
</element>
...
/**
* @mas:namespace target=”sfdc”
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function selectContacts_request($source) {
<query>
<queryString>
SELECT * FROM Contact
WHERE AccountId = ”{string($source/@id)}”
</queryString>
</query>
}
<query xmlns=”urn:enterprise.soap.sforce.com”>
<queryString>SELECT * FROM Contact WHERE AccountId = 1000</queryString>
</query>
応答変換は、到来するウェブサービスメッセージを処理し、そしてコンジットマネージャーにより処理されるノード(又はnodeset)を生成する。全ての応答変換は、次のシステム変数を参照することができる。
...
<element name=”queryResponse”>
<complexType>
<sequence>
<element name=”result” type=”tns:QueryResult”/>
</sequence>
</complexType>
</element>
<complexType name=”QueryResult”>
<sequence>
<element name=”done” type=”xsd:boolean”/>
<element name=”queryLocator” type=”tns:QueryLocator” nillable=”true”/>
<element name=”records” minOccurs=”0” maxOccurs=”unbounded”
type=”ens:sObject”/>
<element name=”size” type=”xsd:int”/>
</sequence>
</complexType>
...
<complexType name=”sObject” abstract=”true”>
<sequence>
<element name=”Id” minOccurs=”0” type=”tns:ID”/>
...
</sequence>
</complexType>
<complexType name=”Contact”>
<complexContent>
<extension base=”ens:sObject”>
<sequence>
<element name=”AccountId” minOccurs=”0” type=”tns:ID”/>
<element name=”Email” minOccurs=”0” type=”xsd:string”/>
<element name=”FirstName” minOccurs=”0” type=”xsd:string”/>
<element name=”LastName” minOccurs=”0” type=”xsd:string”/>
<element name=”SystemModstamp” minOccurs=”0” type=”xsd:dateTime”/>
...
</sequence>
</extension>
</complexContent>
</complexType>
<element name=”Contact” type=”ens:Contact”/>
<sfdc:queryResponse xmlns:sfdc=”urn:enterprise.soap.sforce.com”>
<sfdc:result>
<sfdc:records xsi:type=”urn:Contact”>
<sfdc:Id>1234</sfdc:Id>
<sfdc:AccountId>1000</sfdc:AccountId>
<sfdc:Email>reoger@acme.com</sfdc:Email>
<sfdc:FirstName>Roger</sfdc:FirstName>
<sfdc:LastName>Reed</sfdc:LastName>
</sfdc:records>
<sfdc:records xsi:type=”urn:Contact”>
<sfdc:Id>5678</sfdc:Id>
<sfdc:AccountId>1000</sfdc:AccountId>
<sfdc:Email>sarah@acme.com</sfdc:Email>
<sfdc:FirstName>Sarah</sfdc:FirstName>
<sfdc:LastName>Smith</sfdc:LastName>
</sfdc:records>
</sfdc:result>
</sfdc:queryResponse>
$response/sfdc:queryResponse/sfdc:result/sfdc:records
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function selectContacts_response($response) {
for $i in $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
}
許可
コンジットにより定義されるオペレーションは、クライアントの対応するnodesetにおいて呼び出すことのできるオペレーションを決定する。例えば、コンジットが挿入オペレーションを定義しない場合には、クライアントは、対応するnodesetに対するノードを生成及び挿入するように試みることができず、このように試みる場合には(例えば、カスタムアクションにおいて)、これがランタイムエラーをトリガーする。クライアント側のプログラミングモデルは、これらの制約を強いる。
account.@quotes.create(
<quoteRequest>
<prodId>A1</prodId><qty>10</qty>
</quoteRequest>
);
contact.address.zip = ”11201”;
コンジットメカニズムは、2種類のエラー、即ちシステムエラー(例えば、プロトコル及びトランスポートエラー)と、アプリケーションエラー(例えば、無効データ)との間を区別する。更に、アプリケーションエラーは、2つの異なる仕方で生じ、即ちSOAP欠陥(即ち、プロトコルレベルエラー)として、及びSOAP(又は平易XML)応答メッセージの一部分として生じ得る。
<xsd:complexType name=”errorType”>
<xsd:sequence>
<xsd:element name=”pkey” type=”xsd:any” minOccurs=”0” maxOccurs=”1”/>
<xsd:element name=”system” type=”mas:systemErrorType” maxOccurs=”1”/>
<xsd:element name=”message” type=”xsd:string”/>
<xsd:element name=”field” type=”mas:errorFieldType” maxOccurs=”unbounded”/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”systemErrorType”>
<xsd:sequence>
<xsd:element name=”code” type=”xsd:any”/>
<xsd:element name=”message” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”errorFieldType”>
<xsd:sequence>
<xsd:element name=”code” type=”xsd:any”/>
<xsd:element name=”message” type=”xsd:string”/>
</xsd:sequence>
<xsd:attribute name=”xpath” type=”xsd:string”/>
</xsd:complexType>
<mas:error>
<mas:pkey>primary-key</mas:pkey>
<mas:system>
<mas:code>error-code</mas:code>
<mas:message>message-string</mas:message>
</mas:system>
<mas:message>message-string</mas:message>
<mas:field xpath=”spath-expression”>
<mas:code>error-code</mas:code>
<mas:message>message-string</mas:message>
</mas:field>
...
</mas:error>
システムエラーは、サーバーによりログすることができる。他の全てのエラー値は、クライアントへ返送し、そしてそれに対応するコールバックファンクションへ通すことができる。
エラーオブジェクトは、アプリケーションのコールバックファンクションへ返送され、このオブジェクトは、上記スキーマに対応するプロパティを有する。
次のオペレーションは、invoke()ファンクションの呼び出しがエラーを返送する場合にシステムエラーを返送する。
/**
* @mas:operation type=”select” keyref=”keyrefName”
*/
function operationTypeSourceType($msg, $source) {
var response = control.invoke($msg);
if (response.error) {
return
<mas:error>
<mas:system><mas:message>system-error</mas:message></mas:system>
</mas:error>;
}
return response;
}
次のオペレーションは、失敗時にinvoke()ファンクションを再試みした後にシステムエラーを返送する。
/**
* @mas:operation type=”select” keyref=”keyrefName”
*/
function operationTypeSourceType($msg, $source) {
for (i=0; i<3; i++) {
var response = control.invoke($msg);
if (!response.error) {
return response; // OK
}
}
return
<mas:error>
<mas:system><mas:message>Retry failed</mas:message></mas:system>
</mas:error>;
}
/**
* @mas:operation type=”create” keyref=”keyrefName”
*/
function operationTypeSourceType($msg, $source) {
var response = control.invoke($msg);
if (response.error) {
if (response.error.code == 101) {
return
<mas:error> <mas:system>
<mas:code>{response.error.code}</mas:code>
<mas:message>system-error</mas:message>
</mas:system></mas:error>;
}
else {
return
<mas:error>
<mas:message>general-error</mas:message>
</mas:error>;
}
}
// check for application errors
if (response.body.createResponse.result.errors) {
return process_error(response.body.createResponse.result.errors);
}
return response; // OK
}
// utility function to process field errors
function process_error(errors) {
var fields;
for (i=0; i<errors.length i++) {
var path = match_path(errors[i].fields[0]);
fields +=
<mas:field xpath=”{path}”>
<code>{$i/statusCode}</code>
<mas:message>{$i/message}</mas:message>
</mas:field>
}
return <mas:error>{fields}</mas:error>;
}
CRUD(生成読み取り更新削除)オペレーションは、4つの基本的な関係データオペレーションを表わす。これらのオペレーションは、MASデータモデル及びクライアントプログラミングモデルに直接マップすることができる。
ウェブサービスのコンタクトスキーマは、上記で定義されたアプリケーションのコンタクトスキーマとは異なる形状を有することに注意されたい。以下のセレクトオペレーションの例は、このマッピングをいかに行うか示す。
セレクトオペレーションは、特定のソースノードに対してkeyrefにより定義されたノードをフレームワークが検索できるようにする。通常、全てのコンジットがセレクトオペレーションを定義する。というのは、これは、クライアントアプリケーションによりノードを検索するのに使用される基本的メカニズムだからである。
/**
* @mas:operation type=”select” keyref=”keyrefName” [inverse=”true”]
* @mas:transform type=”request” function=”functionName_request”
* @mas:transform type=”response” function=”functionName_response”
*/
function functionName($msg, $source) {
return ws.invoke($msg);
}
<xsd:keyref name=”keyrefName” refer=”targetType”
mas:alias=”relationName” mas:inverseAlias=”inverseRelationName”>
<xsd:selector xpath=”sourceType”/>
<xsd:field xpath=”foreignKey”/>
</xsd:keyref>
SELECT * FROM keyref.targetType WHERE primary_key = $source/foreign_key
逆keyrefを実施するオペレーションは、次のSQL表現に対応する。
SELECT * FROM keyref.sourceType WHERE foreign_key = $source/primary_key
関連外部キーは、多対1(又は「ルックアップ」)関係を実施する。
例えば、次のスキーマ及びkeyref定義が与えられると、コンタクトノードのaccountId属性を、そのコンタクトが属するアカウントノードに対するポインタとして考えるのが自然である。
<xsd:complexType name=”contactType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”accountId” type=”xsd:string” use=”required”/>
</xsd:complexType>
<xsd:keyref name=”contactAccountRef” refer=”accountKey” mas:alias=”account”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
var account = contact.@@account;
/**
* @mas:operation type=”select” keyref=”contactAccountRef”
* @mas:transform type=”request” function=”selectAccountByContact_request”
* @mas:transform type=”response” function=”selectAccountByContact_response”
*/
function selectAccountByContact($msg, $source) {
return ws.invoke($msg);
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@accountId”
*/
function selectAccountByContact_request($source) {
<query>
<queryString>
SELECT * FROM Account
WHERE Id = {string($source/@accountId)}
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectAccountByContact_response($response) {
let $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<account id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<name>{string($i/sfdc:Name)}</name>
<type>{string($i/sfdc:Type)}</type>
</account>
}
/**
* @mas:operation type=”select” keyref=”contactAccountRef”
* @mas:transform type=”request” function=”selectAccountByContact_request”
* @mas:transform type=”response” function=”selectAccountByContact_response”
*/
function selectAccountByContact($msg, $source) {
return ws.invoke($msg);
}
要求変換は、アカウントノードを表わす$source変数を参照することができる。ファンクション注釈は、出て行くメッセージ文書の言語(XQuery)及びターゲットnamespaceを宣言することができる(コンジットファイルのヘッダー注釈で宣言されたnamespaceプレフィックスを参照する)。
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@accountId”
*/
function selectAccountByContact_request($source) {
<query>
<queryString>
SELECT * FROM Account
WHERE Id = {string($source/@accountId)}
</queryString>
</query>
}
応答変換は、ウェブサービスから返送されるメッセージのXML本体を表わす$response変数を参照することができる。又、ファンクション注釈は、コンジットマネージャーへ返送されるXMLオブジェクトの言語(XQuery)及びターゲットnamespaceも宣言することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectOwnerByAccount_response($response) {
let $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<account id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<name>{string($i/sfdc:Name)}</name>
<type>{string($i/sfdc:Type)}</type>
</account>
}
逆のセレクト(1対多)
外部キーにより定義された多対1の関係は、もちろん、逆の方向に、1対多の関係として考えることができる。
<xsd:complexType name=”contactType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
<xsd:element name=”modified” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”accountId” type=”xsd:string” use=”required”/>
</xsd:complexType>
<xsd:keyref name=”contactAccountRef” refer=”accountKey” mas:alias=”account”
mas:inverseAlias=”contacts”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
var contacts = account.@@contacts.*;
次のコンジットオペレーションは、この逆のkeyref関係を実施する。
/**
* @mas:operation type=”select” keyref=”contactAccountRef” inverse=”true”
* @mas:transform type=”request” function=”selectContactsByAccount_request”
* @mas:transform type=”response” function=”selectContactsByAccount_response”
*/
function selectContactsByAccount($msg, $source) {
return ws.invoke($msg);
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@id”
*/
function selectContactsByAccount_request($source) {
<query>
<queryString>
SELECT * FROM Contact
WHERE accountId = {string($source/@id)}
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectContactsByAccount_response($response) {
for $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
}
/**
* @mas:operation type=”select” keyref=”contactAccountRef” inverse=”true”
* @mas:transform type=”request” function=”selectContactsByAccount_request”
* @mas:transform type=”response” function=”selectContactsByAccount_response”
*/
function selectContactsByAccount($msg, $source) {
return ws.invoke($msg);
}
要求変換は、コンタクトノードを表わす$source変数を参照することができる。ファンクション注釈は、出て行くメッセージ文書の言語(XQuery)及びターゲットnamespaceを宣言する(コンジットファイルのヘッダー注釈で宣言されたnamespaceプレフィックスを参照する)。
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@id”
*/
function selectContactsByAccount_request($source) {
<query>
<queryString>
SELECT * FROM Contact
WHERE accountId = {string($source/@id)}
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectContactsByAccount_response($response) {
for $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
}
外部キー値に依存しないノードとノードとの間の関係を定義することができる。例えば、現在ユーザ情報又は他の外部情報(例えば、日時、リアルタイムデータ、外部システム状態)を使用する問合せにより1組のノードが定義されてもよい。これらの場合に、nodesetは、データモデル内の任意のnodetypeにアタッチされてもよい。しかしながら、通常、これらのnodesetは、ルートノードにアタッチされる。
<xsd:key name=”accountKey” mas:alias=”accounts”>
<xsd:selector xpath=”account ”/>
<xsd:field xpath=”@id”/>
</xsd:key>
var accounts = $root.@@accounts.*;
コンジットは、逆のkeyrefセレクトオペレーション(上述した)と同様に実施することができる。
/**
* @mas:operation type=”select” key=”accountKey” inverse=”true”
* @mas:transform type=”request” function=”selectAccounts_request”
* @mas:transform type=”response” function=”selectAccounts_response”
*/
function selectAccounts($msg, $source) {
return ws.invoke($msg);
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function selectAccounts_request($source) {
<query>
<queryString>
SELECT *.Account FROM Account, User
WHERE User.Alias = {string($user/username)}
AND User.Id = Account.OwnerId
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectAccounts_response($response) {
for $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<account id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<name>{string($i/sfdc:Name)}</name>
<type>{string($i/sfdc:Type)}</type>
</account>
}
要求変換は、ウェブサービスへ送信される要求問合せを構成するのに使用される$userシステム変数を参照することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function selectAccounts_request($source) {
<query>
<queryString>
SELECT *.Account FROM Account, User
WHERE User.Alias = {string($user/username)}
AND User.Id = Account.OwnerId
</queryString>
</query>
}
応答変換は、先のセクションで定義された応答変換と同様に、ウェブサービスオペレーションにより返送される1組のアカウントを処理することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectAccounts_response($response) {
for $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<account id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<name>{string($i/sfdc:Name)}</name>
<type>{string($i/sfdc:Type)}</type>
</account>
}
挿入
挿入オペレーションは、クライアントアプリケーションが新たに形成されたノードをサーバーに同期させるときにコンジットマネージャーによりコールすることができる。
var node = source.@@keyref.create(<xml>); // contextual create
var node = $root.create(<xml>); // context free create
両方の場合に、ノードのXMLオブジェクトだけを(即ちソースノードではなく)サーバーへ転送することができる。これは、コンテクスト生成オペレーションの場合に、ノードが、ソースノードを参照する外部キー値を含まねばならないからであり、この値は、keyref定義に基づいてフレームワークにより自動的にセットされる。
/**
* @mas:operation type=”insert” node=”nodeName”
* @mas:transform type=”request” function=”functionName_request”
* @mas:transform type=”response” function=”functionName_response”
*/
function functionName($msg, $source) {
return ws.invoke($msg);
}
挿入オペレーションの要求変換は、ウェブサービスオペレーションに対するメッセージ本体を生成し、これは、オペレーションに対してコンテクストを与える次のシステム変数を参照することができる。
一実施形態において、非関連性挿入オペレーションは、データモード内の他のnodetypeを参照する外部キーをもたない。例えば、ユーザnodetypeは、次のスキーマにより定義することができる。
<xsd:complexType name=”userType”>
<xsd:all>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string”/>
</xsd:complexType>
アドミニストレーションアプリケーションがシステムに対する新たなユーザを生成できると仮定する。これを行うクライアントコードは、次の通りである。
$root.create(<user><email>bob@acme.com</email></user>);
/**
* @mas:operation type=”insert” node=”app:user”
* @mas:transform type=”request” function=”insertUser_request”
* @mas:transform type=”response” function=”insertUser_response”
*/
function insertUser($msg, $node) {
return ws.invoke($msg);
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function insertUser_request($node) {
<create>
<sObjects xsi:type=”User”>
<Email>{string($node/app:email)}</Email>
</sObjects>
</create>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function insertUser_response($response) {
<user id=”{string($response/sfdc:createResponse/sfdc:result/sfdc:Id)}”/>
}
要求変換は、アプリケーションにより生成されたユーザノードを表わす$node変数を参照することができる。ファンクションの注釈は、出て行くメッセージ文書の言語(XQuery)及びターゲットnamespaceを宣言することができる(コンジットファイルのヘッダー注釈で宣言されたnamespaceプレフィックスを参照する)。
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function insertUser_request($node) {
<create>
<sObjects xsi:type=”User”>
<Email>{string($node/app:email)}</Email>
</sObjects>
</create>
}
応答変換は、ウェブサービスから返送されたメッセージのXML本体を表わす$response変数を参照することができる。このファンクションの注釈は、コンジットマネージャーへ返送されるXMLオブジェクトの言語(XQuery)及びターゲットnamespaceも宣言することができる。
<element name=”createResponse”>
<complexType>
<sequence>
<element name=”result” minOccurs=”1” type=”tns:SaveResult”/>
</sequence>
</complexType>
</element>
<complexType name=”SaveResult”>
<sequence>
<element name=”id” type=”tns:ID”/>
<element name=”success” type=”xsd:boolean”/>
<element name=”errors” minOccurs=”0” maxOccurs=”unbounded” type=”tns:Error”/>
</sequence>
</complexType>
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function insertUser_response($response) {
<user id=”{string($response/sfdc:createResponse/sfdc:result/sfdc:id)}”/>
}
この一次キー値は、コンジットマネージャーにより処理できると共に、クライアントアプリケーションと同期させることができる。
関連性挿入は、キャッシュ内の他のノードを参照する外部キー値を含むノードを伴うことができる。
例えば、以下のコンタクトスキーマは、所有者ノード(@ownerId)及びアカウントノード(@accountId)に対する外部キーを定義する。
<xsd:complexType name=”contactType”>
<xsd:all>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” use=”required” mas:type=”pkey”/>
<xsd:attribute name=”ownerId” type=”xsd:string” use=”required”/>
<xsd:attribute name=”accountId” type=”xsd:string” use=”required”/>
</xsd:complexType>
var contact =
<contact>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>;
function createContact1(account, owner, contact) {
contact.@@account = account;
contact.@@owner = owner;
return $root.create(contact);
}
しかしながら、次のファンクションは、同じ目標を達成する。
function createContact2(account, owner, contact) {
contact.@@owner = owner;
return account.@@contacts.create(contact)
}
function createContact3(account, owner, contact) {
contact.@@account = account;
return owner.@@contact = contact;
}
/**
* @mas:operation type=”insert” node=”app:contact”
* @mas:transform type=”request” function=”insertContact_request”
* @mas:transform type=”response” function=”insertContact_response”
*/
function insertContact($msg, $node) {
return ws.invoke($msg);
}
/**
* @mas:namespace target=”sfdc”
* @language:body type=”xquery”
*/
function insertContact_request($node) {
<create>
<sObjects xsi:type=”Contact”>
<AccountId>{string($node/app:@accountId})</AccountId>
<OwnerId>{string($node/app:@ownerId})</OwnerId>
<FirstName>{string($node/app:first)}</FirstName>
<LastName>{string($node/app:last)}</LastName>
<Email>{string($node/app:email)}</Email>
</sObjects>
</create>
}
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function insertContact_response($response) {
<contact id=”{string($response/sfdc:createResponse/sfdc:result/sfdc:id)}”/>
}
しかしながら、一実施形態では、互いに参照する多数のノードがアプリケーションにより生成される場合には、サーバーにより返送される一次キーの値を使用して、新たに挿入されたノードを参照するノードの外部キー値も更新しなければならない。
function createContact4(account) {
var owner = $root.create(<user><email>sarah@acme.com</email></user>);
var contact =
<contact>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>;
contact.@@owner = owner;
return account.create(contact);
}
ある場合に、ノードを生成するためにコールされるウェブサービスメソッドは、シーケンスナンバーを返送しないことがある。コンジットは、単一のコンジットオペレーション内で多数のウェブサービスコールを行って、この情報を検索することができる。
例えば、先のセクションで定義されたコンジットオペレーションは、次のように拡張される。
/**
* @mas:operation type=”insert” node=”app:contact”
* @mas:transform type=”request” function=”insertContact_request”
* @mas:transform type=”response” function=”insertContact_response”
*/
function insertContact($msg, $source) {
var response = ws.invoke($msg);
var id = response.sfdc:createResponse.sfdc:result.sfdc:id;
// retrieve sequence number
var msg2 = createMessage(requestTimestamp(id));
var response2 = ws.invoke(msg2);
// return both responses
response.body += response2.body.sfdc:queryResponse;
return response;
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function requestTimestamp($id) {
<query>
<queryString>
SELECT Id, SystemModstamp FROM Contact
WHERE Id = ”{$id}”
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function insertContact_request($node) {
<create>
<sObjects xsi:type=”Contact”>
<AccountId>{string($node/app:@accountId})</AccountId>
<OwnerId>{string($node/app:@ownerId})</OwnerId>
<FirstName>{string($node/app:first)}</FirstName>
<LastName>{string($node/app:last)}</LastName>
<Email>{string($node/app:email)}</Email>
</sObjects>
</create>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function insertContact_response($response) {
<contact id=”{string($response/sfdc:createResponse/sfdc:result/sfdc:id)}”>
<modified>
{string($response/sfdc:queryResponse/sfdc:records/sfdc:SystemModstamp)}
</modified>
</contact>
}
要求変換は、先のセクションで定義されたものと同じウェブサービスメッセージを生成することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function insertContact_request($node) {
<create>
<sObjects xsi:type=”Contact”>
<AccountId>{string($node/app:@accountId})</AccountId>
<OwnerId>{string($node/app:@ownerId})</OwnerId>
<FirstName>{string($node/app:first)}</FirstName>
<LastName>{string($node/app:last)}</LastName>
<Email>{string($node/app:email)}</Email>
</sObjects>
</create>
}
しかしながら、この場合に、コンジットの自動的に発生されたXScriptファンクションは、2つのウェブサービスコールを呼び出すように変更することができる。第1に、要求変換から返送されるメッセージを使用して、ノードを挿入し、そして挿入されたノードの一次キーを検索することができる。
/**
* @mas:operation type=”insert” node=”app:contact”
* @mas:transform type=”request” function=”insertContact_request”
* @mas:transform type=”response” function=”insertContact_response”
*/
function insertContact($msg, $source) {
var response = ws.invoke($msg);
var id = response.sfdc:createResponse.sfdc:result.sfdc:id;
// retrieve sequence number
var msg2 = createMessage(requestTimestamp(id));
var response2 = ws.invoke(msg2);
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function requestTimestamp($id) {
<query>
<queryString>
SELECT Id, SystemModstamp FROM Contact
WHERE Id = ”{$id}”
</queryString>
</query>
}
// return both responses
response.body += response2.body.sfdc:queryResponse;
return response;
}
応答変換は、コンジットファンクションにより生成されたXMLオブジェクトを処理し、そして一次キーとノードのシーケンスナンバーの両方を含む単一の<contact>ノードを返送することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function insertContact_response($response) {
<contact id=”{string($response/sfdc:createResponse/sfdc:result/sfdc:id)}”>
<modified>
{string($response/sfdc:queryResponse/sfdc:records/sfdc:SystemModstamp)}
</modified>
</contact>
}
更新オペレーションは、クライアントアプリケーションがノードを変更したときにコンジットマネージャーによりコールすることができる。
エンタープライズがデータの更新を要求されたときに、それを拒否するポリシー/プロセスがあるか、又は誰か他のものがデータを最初に変更したために、拒絶することが考えられる。第1の問題は、不可避であり、そして他の全てと同様に、更新オペレーションが失敗をハンドリングできることを要求する。フレームワークは、第2のケースに対する楽観的同時性モデルを実施することができる。
function modify(contact, address) {
contact.email = address;
contact.update();
}
更新オペレーションは、次の形態をもつことができる。
/**
* @mas:operation type=”update” node=”nodeName”
* @mas:transform type=”request” function=”functionName_request”
* @mas:transform type=”response” function=”functionName_response”
*/
function functionName($msg, $source) {
return ws.invoke($msg);
}
更新オペレーションの要求変換は、ウェブサービスオペレーションに対するメッセージ本体を生成することができ、これは、オペレーションのためのコンテクストを与える次のシステム変数を参照することができる。
次のファンクションは、コンタクトノードに対する更新コンジットオペレーションを実施する。
/**
* @mas:operation type=”update” node=”app:contact”
* @mas:transform type=”request” function=”updateContact_request”
* @mas:transform type=”response” function=”updateContact_response”
*/
function updateContact($msg, $source) {
ws.invoke($msg);
// retrieve sequence number
var msg2 = createMessage(requestTimestamp($source/@id));
var response2 = ws.invoke(msg2);
return response2;
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function updateContact_request($node) {
<update>
<sObjects xsi:type=”Contact”>
<Id>{string($node/app:@id})</Id>
<LastModifiedDate>{string($node/app:modified})</LastModifiedDate>
<AccountId>{string($node/app:@accountId})</AccountId>
<OwnerId>{string($node/app:@ownerId})</OwnerId>
<FirstName>{string($node/app:first)}</FirstName>
<LastName>{string($node/app:last)}</LastName>
<Email>{string($node/app:email)}</Email>
</sObjects>
</update>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function updateContact_response($response) {
let $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
</contact>
}
要求変換は、更新オペレーションを呼び出すのに使用されるウェブサービスメッセージを生成することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function updateContact_request($node) {
<update>
<sObjects xsi:type=”Contact”>
<Id>{string($node/app:@id})</Id>
<LastModifiedDate>{string($node/app:modified})</LastModifiedDate>
<AccountId>{string($node/app:@accountId})</AccountId>
<OwnerId>{string($node/app:@ownerId})</OwnerId>
<FirstName>{string($node/app:first)}</FirstName>
<LastName>{string($node/app:last)}</LastName>
<Email>{string($node/app:email)}</Email>
</sObjects>
</update>
}
挿入オペレーションと同様に、コンジットの自動的に発生されたXScriptファンクションは、2つのウェブサービスコールを呼び出すように変更することができる。第1に、要求変換から返送されるメッセージを使用して、ノードを更新する。
/**
* @mas:operation type=”update” node=”app:contact”
* @mas:transform type=”request” function=”updateContact_request”
* @mas:transform type=”response” function=”updateContact_response”
*/
function updateContact($msg, $source) {
ws.invoke($msg);
// retrieve sequence number
var msg2 = createMessage(requestTimestamp(id));
var response2 = ws.invoke(msg2);
最後に、第2のウェブサービスオペレーションの結果を返送して、応答変換により処理することができる。
return response2;
}
応答変換は、コンジットファンクションにより生成されたXMLオブジェクトを処理して、一次キー及びノードのシーケンスナンバーの両方を含む単一<contact>ノードを返送することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function updateContact_response($response) {
let $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
</contact>
}
クライアントが、外部システムにおいて既に更新された(別のクライアントによるか又は他の外因性変化プロセスにより)「古い」ノードを変更しそして同期しようと試みるときに、ノードの競合が生じ得る。古いノードとは、サーバーにより保持された現在シーケンスナンバーとは異なるシーケンスナンバーを有するものである。
次の更新オペレーションファンクションは、ウェブサービスにより返送されるエラー値をチェックする。要求変換は、上記で定義されたものと同じである。
/**
* @mas:operation type=”update” node=”app:contact”
* @mas:transform type=”request” function=”updateContact_request”
* @mas:transform type=”response” function=”updateContact_response”
*/
function updateContact($msg, $source) {
var response = ws.invoke($msg);
// check for error
if (! response.body.sfdc:updateResponse.sfdc:result.sfdc:success) {
// retrieve server's record
msg = createMessage(selectContact_request($source/@id));
response = ws.invoke(msg);
// set state expando
var node = response.body.sfdc:queryResponse.sfdc:result.sfdc:records;
node.@state=”conflict”;
}
else {
// retrieve sequence number
msg = createMessage(requestTimestamp($source/@id));
response = ws.invoke(msg);
}
return response;
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function updateContact_response($response) {
let $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
if ($i.@!= null)
then
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”
mas:state=”{$response.result.@state}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
else
<contact id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
</contact>
}
コンジットファンクションは、第1に、ウェブサービスにより返送されるエラー値をチェックすることができる。
function updateContact($msg, $source) {
var response = ws.invoke($msg);
// check for error
if (! response.body.sfdc:updateResponse.sfdc:result.sfdc:success) {
// retrieve server's record
msg = createMessage(selectContact_request($source/@id));
response = ws.invoke(msg);
// set state expando
var node = response.body.sfdc:queryResponse.sfdc:result.sfdc:records;
node.@state=”conflict”;
// retrieve sequence number
msg = createMessage(requestTimestamp($source/@id));
response = ws.invoke(msg);
return response;
}
応答変換は、最初に、state expando属性がコンジットオペレーションにより生成されたかどうか調べるためのチェックを行うことができる。もしそうであれば、この変換は、完全なノードエレメントを構成することができ、さもなければ、上述したように、一次キー及びシーケンスナンバーのみを返送することができる。
function updateContact_response($response) {
let $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
if ($i.@state != null)
then
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”
mas:state=”{$i.@state}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
else
<contact id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
</contact>
}
ノードは、XScript表現により変更することができる。これは、外部キー値についても適用される。このセクションの例は、アカウント及びコンタクトnodetypeを使用し、これらは、次のキー定義を宣言する。
<xsd:key name=”accountKey”>
<xsd:selector xpath=”account”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:key name=”contactPrimaryKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:key name=”contactEmailKey”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”email”/>
</xsd:key>
function foobar(contact) {
contact.first = $context.first;
contact.last = $context.last;
contact.email = $context.email; // runtime error
}
function foo(contact, account) {
contact.first = $context.first;
contact.last = $context.last;
contact.@@accountId = account; // changes account foreign key
contact.update();
}
<xsd:keyref name=”contactAccountRef” refer=”accountKey” mas:alias=”account”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
function bar(account, contact) {
account.@@contacts += contact;
}
<xsd:keyref name=”contactAccountRef” refer=”accountKey”
mas:alias=”account” mas:inverseAlias=”contacts”>
<xsd:selector xpath=”contact”/>
<xsd:field xpath=”@accountId”/>
</xsd:keyref>
function foo1(contact, account) {
contact.first = $context.first;
contact.last = $context.last;
contact.@@accountId = account;
update(contact);
}
function foo2(contact, account) {
contact.first = $context.first;
contact.last = $context.last;
account.@@contacts += contact;
update(contact);
}
function foo(contact) {
contact.first = $context.first;
contact.last = $context.last;
contact.@@accountId = null;
update(contact);
}
データは、2つのnodetype間の定義されたkeyref関係に関連するセレクトコンジットオペレーションを実施することにより検索することができ、即ち1つのノード内に含まれた外部キー値は、関連ノードの一次キーを識別する。これらのセレクトオペレーションの出力は、フレームワークによりローカルキャッシュへと収納されるノードである。
1.カスタムオペレーションは、クライアントが、不透明な一時的XMLオブジェクト(文書)を特定のコンジットオペレーションへ通過させるのを許すことができる。このオペレーションは、一時的なXML文書をクライアントコールバックへ非同期で返送することができる。
例えば、次のカスタムオペレーションmyQueryは、XMLオブジェクト<myRequest>を入力として取り出し、そしてXMLオブジェクトmyCallback()ファンクションを返送する。
$root.myQuery(<myRequest>product mobile application</myRequest>, myCallback);
function myCallback(myOutput) {
...
}
例えば、次のカスタムオブジェクト<takeQuery>が、タスクノードをtaskQueryノードに関連付けるkeyrefとして定義されたセレクトコンジットオペレーションへ送信される。
var query = $root.@@taskQueries.create(<taskQuery priority=”1”/>);
var tasks = query.@@tasks.*;
カスタムオペレーションは、カスタムコンジットオペレーション(ファンクション)をコールするためのメカニズムである。ファンクション入力及び出力は、両方とも、XML文書リテラル(スキーマにより定義されない)である。一実施形態では、フレームワークは、結果をローカルキャッシュへ直接収納しない。
次のコードクライアントコードは、XMLオブジェクト<query>が通されたカスタムオペレーションgetListをコールする。
function bar() {
account.getList(<query optedOut=”false”/>, callback);
}
function callback(result) {
for (i = 0; i < result.length; i++) {
addAddress(result[i].email);
}
}
以下のXQueryファンクションは、カスタム要求を実施する。
/**
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@id”
* @language:body type=”xquery”
*/
function foo_request($source, $query) {
<query>
<queryString>
SELECT Id, Email FROM Contact
WHERE AccountId = ”{string($source/@id)}”
AND HasOptedOutOfEmail = {boolean($query/@optedOut)}
</queryString>
</query>
}
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function foo_response($response) {
for $i in $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}”>
<email>{string($i/sfdc:Email)}</email>
</contact>
}
/**
* custom operatoin on contact: account.getList(<query optedOut=”false”/>);
* @mas:operation type=”custom” node=”app:account” name=”getList”
* @mas:transform type=”request” function=”foo_request”
* @mas:transform type=”response” function=”foo_response”
*/
function foo($msg, $source, $query) {
$msg.header += createHeader();
return ws.invoke($msg);
}
カスタムオブジェクトは、グラフの一部分となる非永続的ノード(スキーマにより定義される)の生成を伴うことができる。このオペレーションは、クライアントがそれに対応するkeyrefを「通してトラバース」するときに呼び出すことができ、この場合、カスタムオブジェクトは、$sourceノードとしてそれに対応するセレクトコンジットオペレーションへ通すことができる。
<xsd:complexType name=”taskQuery”>
<xsd:attribute name=”priority” type=”xsd:string”/>
</xsd:complexType>
<xsd:keyref name=”taskQueryKey”>
<xsd:selector xpath=”taskQuery”/>
<xsd:field xpath=”@priority”/>
</xsd:keyref>
<xsd:keyref name=”taskQueryRootRef” refer=”mas:rootKey”
mas:inverseAlias=”taskQueries”>
<xsd:selector xpath=”taskQuery”/>
<xsd:field xpath=”@mas:rootId”/>
</xsd:keyref>
<xsd:keyref name=”taskTaskQueryRef” refer=”TaskQueryKey”
mas:inverseAlias=”tasks”>
<xsd:selector xpath=”task”/>
<xsd:field xpath=”@taskQuery”/>
</xsd:keyref>
taskQueryノードは、標準的なcreate()ファンクションを使用してクライアントスクリプトにより生成されてもよい。
function init() {
var f = $root.@@taskQueries.create(<taskQuery priority=”1”/>);
}
次のテンプレートは、逆taskTaskQueryRefのkeyref定義をトラバースする。
<netui:repeater id=”$s”
source=”$root.@@taskQueries.where(priority=='1').@@tasks.*”>
<p>{$s}</p>
</netui:repeater>
/**
* @mas:operation type=”select” keyref=”app:taskTaskQueryRef” inverse=”true”
* @mas:transform type=”request” function=”selectTasks_request”
* @mas:transform type=”response” function=”selectTasks_response”
*/
function selectTasks($msg, $source) {
return ws.invoke($msg);
}
/**
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@priority”
* @language:body type=”xquery”
*/
function selectTasks_request($source) {
<query>
<queryString>
SELECT Id, Priority, Subject FROM Task
WHERE Priority = ”{string($source/@priority})”
</queryString>
</query>
}
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function selectTasks_response($response) {
for $i in $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<task id=”{string($i/sfdc:Id)}”
priority=”{string($i/sfdc:Priority)}”>
<subject>{string($i/sfdc:Subject)}</subject>
</task>
}
/**
* @mas:operation type=”select” keyref=”app:taskQueryRootRef” inverse=”true”
*/
function selectTasks($msg, $source) {
return <taskQuery priority='1'/><taskQuery priority='2'/>;
}
<td>
<netui:repeater id=”s1” source=”$root.@@taskQueries.*”>
<a href=”s1.select(s1.iterator)”>Priority {s1}</a>
</netui:repeater>
</td>
<td>
<netui:repeater id=”s2” source=”s1.selected.@@tasks.*”>
<p>{s2}</p>
</netui:repeater>
</td>
セレクトオペレーションは、フレームワークが特定keyrefに対するノードを検索できるようにする。コンジットは、セレクトオペレーションを定義することができる。というのは、これは、クライアントアプリケーションによりノードを検索するのに使用される基本的メカニズムだからである。
$account.@@contacts.*
コンジットセレクトオペレーションには、対応するアカウントオブジェクトの一次キーを通過させることができる。このセクションは、他の形態のセレクトオペレーションを詳述する。
クライアント及びMASは、両方とも、コンジットマネージャーにより返送されるデータをキャッシュ記憶することができる。それ故、各々のデータグラフトラバースがセレクト要求を発生しなくてよいことはない。クライアント及びサーバーの両キャッシュは、新たなセレクト要求が発生されるまでに、対応する1組のデータに、どれほど長時間、最新のものとして依存できるか決定するメタデータを、各ノード及びnodesetに対して維持することができる。
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectContactsByAccount_response($response) {
for $i := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
</contact>
}
キャッシュ内に含まれないノードについては、フレームワークがselect_setオペレーションをコールすることができ、これは、通常のセレクトオペレーションと同様に、要求された1組のpkey値に対して完全なノードを返送する。例えば、上述したselect_setオペレーションは、次の要求変換を実施する。
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function selectContacts_request($keyset) {
<query>
<queryString>
SELECT * FROM Contact
WHERE Id IN (
{
for $x in $keyset
return
{$x},
}
)
</queryString>
</query>
}
複雑なスキーマの選択
セレクトオペレーションは、中継されるエレメントを含む複雑な文書として定義されたノードを返送することができる。nodetypeのスキーマ定義の複雑さについては制約が課せられない。しかしながら、ノードレコードのサイズについては実際上の制限が生じ得る。次のセクションは、複雑な文書を多数のノードに分割できるときのケースを詳述する。
例
以下のスキーマは、多数のlineItemエレメントを含むpurchaseOrder nodetypeを示す。
<xsd:element name=”purchaseOrder” type=”purchaseOrderType”>
<xsd:complexType name=”purchaseOrderType”>
<xsd:sequence>
<xsd:element name=”price” type=”xsd:double”/>
...
<xsd:complexType name=”lineItems”>
<xsd:sequence maxOccurs=”unbounded”>
<xsd:complexType ref=”lineItem”>
<xsd:sequence>
<xsd:element name=”prodId” type=”xsd:string”/>
...
</xsd:sequence>
</xsd:complexType>
</xsd:sequence>
</xsd:complexType>
</xsd:sequence>
</xsd:complexType>
<purchaseOrder>
<price>1000.00</price>
...
<lineItems>
<lineItem>
<prodId>Widget-X</prodId>
...
</lineItem>
<lineItem>
<prodId>Widget-Y</prodId>
...
</lineItem>
...
</lineItems>
</purchaseOrder>
/**
* @mas:operation type=”select” keyref=”purchaseOrderAccountRef” inverse=”true”
* @mas:transform type=”request” function=”selectPurchaseOrders_request”
* @mas:transform type=”response” function=”selectPurchaseOrders_response”
*/
function selectPurchaseOrders($msg, $source) {
var response = ws.invoke($msg);
var pos = response.sfdc:queryResponse.sfdc:result.sfdc:records;
// retrieve line items for each purchase order
for (i = 0; i < pos.length-1; i++) {
var msg2 = createMessage(requestLineItems(pos[i].sfdc:Id));
var response2 = ws.invoke(msg2);
pos[i] += response2.body.sfdc:queryResponse.sfdc:result.sfdc:records;
}
return response;
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@id”
*/
function selectPurchaseOrders_request($source) {
<query>
<queryString>
SELECT * FROM PurchaseOrder
WHERE PurchaseOrder.AccountId = {string($source/@id)}
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
*/
function selectLineItems($id) {
<query>
<queryString>
SELECT * FROM LineItem
WHERE LineItem.PurchaseOrderId = $id
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectPurchaseOrders_response($response) {
for $po := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<purchaseOrder id=”{string($po/ws:Id)}”>
<price>{string($po/ws:Price)}</price>
...
<lineItems>
{
for $li in $po/ws:records
return
<lineItem>
<prodId>{string($li/ws:ProdId)}</prodId>
...
</lineItem>
}
</lineItems>
</purchaseOrder>
}
セレクトオペレーションは、中継されるエレメントを含む複雑な文書として定義されたノードを返送することができる。nodetypeのスキーマ定義の複雑さには制約が課せられない。
次のスキーマ定義において、purchaseOrderType及びlineItemTypeは、両方とも、次のスキーマ定義を伴うnodetypeとして宣言される。
<xsd:complexType name=”purchaseOrderType”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”price” type=”xsd:double”/>
...
<xsd:sequence>
</xsd:complexType>
<xsd:complexType>
<xsd:element name=”lineItemType”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”prodId” type=”xsd:string”/>
...
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:key name=”purchaseOrderKey”>
<xsd:selector xpath=”purchaseOrder”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:key name=”lineItemKey”>
<xsd:selector xpath=”lineItem”/>
<xsd:field xpath=”@id”/>
</xsd:key>
<xsd:keyref name=”lineItemPurchaseOrderRef” refer=”purchaseOrderKey”
mas:inverseAlias=”lineItems”>
<xsd:selector xpath=”lineItem”/>
<xsd:field xpath=”@purchaseOrderId”/>
</xsd:keyref>
コンパウンド文書が個々のノードへ分割されるときには、フレームワークは、成分ノード(例えば、ラインアイテム)におけるクライアントオペレーションがコンジットによりサポートされることを保証できる。例えば、クライアントアプリケーションは、lineItem keyrefに対して対応する挿入オペレーションがない限り、新たなラインアイテムオブジェクトを生成することが防止され得る。
/**
* @mas:operation type=”select” keyref=”purchaseOrderAccountRef” inverse=”true”
* @mas:transform type=”request” function=”selectPurchaseOrders_request”
* @mas:transform type=”response” function=”selectPurchaseOrders_response”
*/
function selectPurchaseOrders($msg, $source) {
var response = ws.invoke($msg);
var pos = response.sfdc:queryResponse.sfdc:result.sfdc:records;
// retrieve line items for each purchase order
for (i = 0; i < pos.length-1; i++) {
var msg2 = createMessage(requestLineItems(pos[i].sfdc:Id));
var response2 = ws.invoke(msg2);
pos[i] += response2.body.sfdc:queryResponse.sfdc:result.sfdc:records;
}
return response;
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@id”
*/
function selectPurchaseOrders_request($source) {
<query>
<queryString>
SELECT * FROM PurchaseOrder
WHERE PurchaseOrder.AccountId = {string($source/@id)}
</queryString>
</query>
}
/**
* @language:body type=”xquery”
* @mas:namespace target=”app”
*/
function selectPurchaseOrders_response($response) {
for $po := $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<purchaseOrder id=”{string($po/ws:Id)}”>
<price>{string($po/ws:Price)}</price>
...
<mas:nodeset keyref=”lineItemPurchaseOrderRef”>
{
for $li in $po/ws:records
return
<lineItem id=”{string($li/ws:Id)}”>
<prodId>{string($li/ws:ProdId)}</prodId>
...
</lineItem>
}
</mas:nodeset>
</purchaseOrder>
}
上述したように、アプリケーションは、SPath表現を使用してデータグラフをトラバースすることができ、これらトラバースは、フレームワークがバックグランドにおいて必要なデータを同期するようにさせ得る。一実施形態において、同期メカニズムは、非同期で呼び出されるので、SPath表現を、現在キャッシュ記憶されているデータグラフに対して完全に評価できないことがしばしば生じ勝ちとなる。
$root.@@accounts.*.@@contacts.*.@@tasks.*;
$root.select(@@accounts.*.@@contacts.*.@@tasks.*);
又、SPath表現は、where()ファンクションを使用して述語も含んでもよい。例えば、
$root.select(@@accounts.*.@@contacts.*.@@tasks.*.where(.priority == 1));
次の表現は、タイプ=”直接”エレメントを有する全てのアカウントに対して全てのコンタクト及びノードを検索することができる。
$root.select(@@accounts.where(.type=”Direct”).keyref(”contacts”, ”notes”).*;
セッション状態は、コンジットカスタム手順コードによりマネージすることができる。
コンジットは、セッション識別子を記憶するための変数を定義することができる。これは、コンジットにより生成されてもよいし、又はこの場合と同様に、ウェブサービスにより返送されてもよい。
// session object returned from Web service
var sessionId = null;
// create and send login message and process results
function login() {
var body =
<login>
<username>{$user.username}</username>
<password>{$user.password}</password>
</login>;
var response = ws.invoke(body);
// set session id
sessionId = string(response.body.sfdc:result.sfdc:sessionId);
// set URL for subsequent calls (from this conduit)
ws.endPoint = string(response.body.sfdc:result.sfdc:serverUrl);
}
各会話メソッドは、セッション識別子を含むヘッダーを指定することができ、次の(通常の)コンジットファンクションは、最初に、会話がスタートしたかどうかチェックし(もしそうでなければ、ログインをコールする)、次いで、適当なヘッダーXMLフラグメントを返送する。
// create conversational header
function createHeader() {
if (sessionId == null) {
login();
}
return
<SessionHeader>
<sessiondId>{sessionId}</sessiondId>
</SessionHeader>;
}
/**
* @mas:operation type=”select” keyref=”app:contactAcoountRef” inverse=”true”
* @mas:transform type=”request” function=”selectContacts_request”
* @mas:transform type=”response” function=”selectContacts_response”
*/
function selectContacts($msg, $source) {
$msg.header += createHeader();
return ws.invoke($msg);
}
次いで、このファンクションは、必要なヘッダー情報を含むXMLオブジェクトを得るためにcreateHeader()ファンクションをコールする。このファンクションは、セッションが現在スタートしていない場合にlogin()ファンクション(上述した)をトリガーする。次いで、ヘッダオブジェクトがメッセージに追加される。
ユーザ情報
$user変数は、どのユーザに代わってコンジットオペレーションが呼び出されるかに関するデータを含む。
ユーザは、MASにおけるそのURLを参照することによりアプリケーションにアクセスすることができる。ユーザがクライアントマシンからそれを初めて行うときに、アプリケーションの全てのコンポーネントをサーバーから自動的に「ダウンロード」することができる。アプリケーションデベロッパがアプリケーションに関するデータモデルしか指定しない場合には、そのデータモデルに対するメタデータをダウンロードすることができる。メタデータは、アプリケーションに対して最小ユーザインターフェイスを与えるに充分な移動ブラウザのための情報を含むことができる。メタデータを使用して、移動ブラウザは、ルートノード及びそのkeyrefを最初に表示することができる。ユーザは、これらのkeyrefをクリックすることによりアプリケーションデータを通してナビゲーションすることができる。ユーザがkeyrefを選択するときに、データ同期エンジンがそのkeyrefに対するノードを非同期でフェッチし、そしてデータをそれが得られたときに自動的に表示する。例えば、ユーザは、アカウントリンクをトラバースして、アカウントノードをフェッチさせ、次いで、アカウントコンタクトkeyrefをトラバースして、アカウントに対するそのコンタクトを見ることができる。このモデルは、機能的であるが、特に快適なものではなく、即ちデータが予めフェッチされないので、UIは、ありのままのもので、且つ経験は「ぎくしゃくした」ものである。このセクションは、アプリケーションプログラマーがユーザインターフェイスをどのようにカスタマイズできるか説明する。
function showContactsForAccount($account) {
$context.account = $account;
return [$account.@@contacts.*, ”ContactsTemplate.tmpl”];
}
MASクライアントアプリケーションは、ページフローファイル(controller.xpf)で構成することができ、このファイルは、XScriptアクション及びファンクションと、1組のページテンプレート(.tmpl)とを含むことができる。
クライアントは、アプリケーションデータのローカルキャッシュを維持することができる。このデータは、随時接続データモデルにより記述され、そしてSPathを使用して参照及び操作される。
SPath表現
クライアントプログラミングモデルは、XMLに対するECMAScript(E4X、XScript)を使用することができ、これは、本質的にXMLに対するナビゲーションサポートを伴うJavaScriptであり、SPathは、XPath同様の言語で、アプリケーションがXMLデータグラフに問合せできるようにする。これは、「ドット」演算子を使用して、グラフ内のエレメントを「トラバース」する。エレメントは、普通のXMLエレメントでもデータノードでもよい。
システム変数は、‘$’記号をプレフィックス(接頭辞)として設け、非タイプ入力とすることができる。他の変数の使用は、XScript仕様により定義される。
次の宣言は、変数foo及びbarを生成する。
foo = 100;
var bar = ”Alchemy”;
varキーワードは、現在ファンクションのローカル範囲内に変数を配置し、varを宣言しない変数は、グローバルな範囲に配置される。
var foo = <foo>Alchemy</foo>;
コンパウンドXMLオブジェクトも次のように生成及び参照することができる。
var foo = <foo><bar>Alchemy</bar></foo>;
var bar = foo.bar
bar == ”Alchemy”
又、XMLオブジェクトは、‘@’演算子を使用して参照される属性を宣言してもよく、例えば、
var foo = <foo id=”100”><bar>Alchemy</bar></foo>;
var id = foo.@id;
属性は暗示的に追加することができる(即ち、expando)。
foo.@ping = ”200”;
var foo = <foo><bar>Alchemy</bar></foo>;
foo.bar = ”MAS”;
foo == <foo><bar>MAS</bar></foo>
次の例は、全<bar>エレメントに置き換わる。
var foo = <foo><bar>Alchemy</bar></foo>;
for.bar = <foobar>Mobilized</foobar>
foo == <foo><foobar>Mobilized</foobar></foo>
var foo = <foo><bar>Alchemy</bar></foo>;
for.bar += <bar>Mobilized</bar>
foo == <foo><bar>Alchemy</bar><foobar>Mobilized</foobar></foo>
逆に、delete演算子を使用して、エレメントを除去する。
var foo = <foo><bar>Alchemy</bar></foo>;
delete foo.bar
foo == <foo></foo>
随時接続データモデルは、データモデルにおけるルートノードを指すマニフェスト変数$rootをもつ仮想XML文書としてデベロッパへと表面化することができる。関連ノードへのナビゲーションは、@@演算子を使用しそしてkeyref定義を経ての仮想XML文書内のモデルである。
本書において、ノードという語は、データモデルノードを示すのに使用される。例えば、次のサンプルは、XMLエレメントを生成する。
var account =
<account>
<name>Acme</name>
<type>Direct</type>
</account>
新たなノードは、keyrefにおいてcreate()ファンクションをコールすることにより生成することができる。例えば、次の例は、新たなaccountノードを生成する。
$root.@@accounts.create(<account><name>Brooklyn Industries</name></account>);
account.name = ”Acme Ltd”;
又、新たなXMLエレメントは、指定によりノード内に生成されてもよく、例えば、
account.address = <address><street>335
Madison</street><zip>11211</zip></address>
nodetype間の関係は、随時接続データモデルにおけるkeyref定義により定義することができる。例えば、次の宣言は、account keyrefがルートノードから発生され、そしてタイプaccount(これは、スキーマにより定義される)のノードを含むことを指定する。
<keyref name=”accounts” sourceType=”mas:root” targetType=”app:account”>
クライアントプログラミングモデルにおいて、keyrefは、@@演算子を使用してトラバースすることができる。例えば、
$root.@@accounts
$root.keyref(”accounts”)
keyrefは、指定の親ノードに対してkeyrefを参照するものとして考えることができる。次の例は、$rootノードのaccount keyrefの全てのaccountノードを参照する。
$root.@@accounts.*
$root.keyref(”accounts”).*
この表現は、各ノードがタイプaccountであるようなnodesetを返送し、例えば、
<account>
<name>Acme</name>
</account>
<account>
<name>Bancroft</name>
</account>
$root.@@accounts.*[0]
length()ファンクションは、nodesetにおけるノード数を返送するのに使用できる。
$root.@@accounts.*.length()
$root.@@accounts.length()
即ち、$root@@accountは、単一エレメント<accounts>を返送する。
データグラフは、SPath表現をアーギュメントとして取り上げるwhere()ファンクションを使用してフィルタリングすることができる。例えば、次のステートメントは、指定のラストネームをもつaccount keyrefにおける全てのcontactノードに一致し、そしてノードリストを返送する。
$root.@@accounts.*.where(.name == ”Acme”);
これは、次の表現と同等であることに注意されたい。
$root.@@accounts.*.(thisXML.name == ”Acme”);
ここで、クローズがノードリストに対して評価でき、そしてその後にSPath表現が続いてもよい。例えば、次の表現は、”Acme”と命名された全てのアカウントに対するコンタクトのノードリストを返送する。
$root.@@accounts.*.where(.name == ”Acme”).@@contacts.*;
各nodetype宣言は、ノードを参照するSPath表現であるラベルを定義してもよい。label()ファンクションは、計算されたストリングを返送する。
<p>{$context.account.label()}</p>
又、keyrefは、label()ファンクションにより返送されるラベルを定義してもよい。
<p>{$root.@@accounts.label()}</p>
ノードのラベルは、label()ファンクションにより得られる。例えば、
ノード又はkeyrefがそれ自身により参照されるときに、強制で自動的にlabel()ファンクションを呼び出す。次の例は、上記例と同等である。
<p>{$context.account}</p>
<p>{$root.@@accounts}</p>
クライアントプログラミングモデルにおいて、全てのオペレーションは、アプリケーション自身のデフォールトnamespaceにおいて実施することができる。
このデフォールトnamespaceは、setDefaultNamespaceファンクションを使用してセットされる。
function begin() {
$pageFlow.setDefaultNamespace(”http://example.com/”);
...
}
var account = <account><name>Acme</name></account>;
次のXMLを発生する。
<account xmlns=”http://example.com/”>
<name>Acme</name>
</account>
システム変数及びファンクションの参照
このセクションは、XML規格に対してECMAScriptを拡張できるシステム変数及びファンクションを説明する。
全てのシステム変数は、‘$’記号のプレフィックスをもつことができ、ユーザ変数も、規定により‘$’記号を使用してもよい。
フレームワークは、テンプレート及びアクションの両方から参照できる次のシステム変数を定義する。
$context変数は、発呼側アクションがテンプレートへの通過を望むことのある付加的なデータを表わす。これは、JPF又はHTTP GET属性におけるフォワードビーンと同様である。コンテクスト変数は、ヒストリーの一部分として保存することができる。
$session変数は、アプリケーションの「セッション」状態を表わし、これは、$contextオブジェクトとは異なり、経歴の一部分として記憶されない。これは、通常、全アプリケーションに関連した(即ち、特定のページではない)情報を記憶するのに使用される。これらの変数は、アプリケーションのライフタイム中に残存し、そしてアプリケーション(及びブラウザ)が停止し及び開始するときに持続されそしてデハイドレート(dehydrate)される。
例えば、次のファンクションは、ユーザ定義のカウント状態変数をセットするのに使用されてもよい。
function onExternalSync() {
$session.count = $root.@@messages.*.length();
}
<p>You have {$session.count} messages.</p>
<p>Click
<a href=”$pageFlow.navigate($root.@@messages.*,
‘showMessages.tmpl’)”>here</a>
to see them</p>
$current変数は、ノード(又はノードリスト)を表わすもので、通常、UIエレメントをデータにバインディングするために相対的SPath表現を伴うテンプレートにより使用される。
$user
$user変数は、ユーザに代わってコンジットオペレーションが呼び出されるところのユーザに関するデータを含む。オブジェクトは、次のフィールドを含む。
クライアントプログラミングモデルは、デベロッパが、アプリケーションを記述するメタデータの一部分にアクセスするのを許すことができる。
meta()
データモデルメタデータは、ノード又はkeyrefのいずれかにおいてmeta()ファンクションをコールすることによりアクセスでき、例えば、
$root.meta();
$root.keyref(”accounts”).meta();
<netui:repeater id=”s1” source=”$root.keyref(*')” iterator=”$i”>
<p>{$i}</p>
<ul>
<netui:repeater id=”s2”
source=”$s1.selected.meta().schema().keyref(*')”
iterator=”$j”>
<li>{j}</li>
</netui:repeater>
</ul>
</netui:repeater>
次の出力は、CRM使用の場合に発生される。
−owner
−subAccounts
−quoteRequest
−contacts
−notes
−events
−tasks
前記セクションで述べたデータモデルは、デベロッパに対し、ルートノードを指すマニフェスト変数$rootを伴う仮想XML文書として表面化することができる。一実施形態において、移動ブラウザは、常に、コンテクストとして、データモデル内の現在位置を有する(例えば、特定のアカウント又は1組のコンタクト)。テンプレート及びスクリプトは、別のマニフェスト変数$currentを通してこの現在位置にアクセスすることができる。
例えば、CRMアプリケーションは、次のスキーマを有する。
<?xml version=”1.0”?>
<xsd:schema targetNamespace=”http://example.com/”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:mas=”run:bea.com”
xmlns=”http://example.com/”>
<xsd:element name=”graph”>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref=”root” minOccurs=”1” maxOccurs=”1”>
<xsd:element ref=”account” maxOccurs=”unbounded”>
<xsd:element ref=”contact” maxOccurs=”unbounded”>
<xsd:element ref=”note” maxOccurs=”unbounded”>
<xsd:element ref=”event” maxOccurs=”unbounded”>
<xsd:element ref=”task” maxOccurs=”unbounded”>
<xsd:element ref=”quoteRequest” maxOccurs=”unbounded”>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
</xsd:schema>
<root>エレメントは、$rootシステム変数により参照することができる。ルートノードは、特殊なシステムタイプであるから、ルートノード内に含まれるユーザデータオブジェクトは存在しない。
随時接続データモデルは、アプリケーションnodetypesを定義することができ、これらは、アプリケーションスキーマ及びkeyref定義から構成することができる。例えば、次の例は、account nodetypeを詳述するもので、これは、スキーマエレメント(name及びtype)と、keyref定義(owner、subAccounts、contacts、notes、events、tasks、及びquotes)とを含む。
<xsd:element name=”account”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”name” type=”xsd:string”/>
<xsd:element name=”type” type=”accountType”/>
</xsd:sequence>
<xsd:attribute name=”ownerId”/>
<xsd:attribute name=”parentAccountId”/>
</xsd:complexType>
</xsd:element>
var user = account.@@owner;
var contacts = $root.@@accounts.*.@@contacts.*;
<xsd:element name=”contact”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”salutation” type=”contactSalutationEnum”/>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”addressType”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:sequence>
<xsd:attribute name=”accountId”/>
<xsd:attribute name=”ownerId”/>
</xsd:complexType>
</xsd:element>
<graph>
<root accounts=”a1 a2”/>
<account id=”a1” owner=”bob” contacts=”c1 c2” notes=”n1” events=”e1” tasks=”t1”>
<name>Acme</name>
<type>Direct</type>
</account>
<account id=”a2” owner=”bob” contacts=”c3”>
<name>Bancroft</name>
<type>Web</type>
</account>
<contact id=”c1” owner=”bob” events=”e2” tasks=”t2”>
<salutation>Mr</salutation>
<first>Roger</first>
<last>Reed</last>
<email>roger@acme.com</email>
</contact>
<contact id=”c2” owner=”bob” notes=”n2”>
<salutation>Ms</salutation>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>
<contact id=”c2” owner=”bob” notes=”n2”>
<salutation>Ms</salutation>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>
<note id=”n1”>
<title>ROI information</title>
<body>Attached document details ROI for product</body>
</note>
<note id=”n2”>
<title>Customer requirements</title>
<body>Attached document presents customer's current and anticipated needs</body>
</note>
<event id=”e1” assigned=”fred”>
<title>Sales meeting</title>
</event>
<event id=”e2” assigned=”fred”>
<title>Product demonstration</title>
</event>
<task id=”t1” assigned=”fred”>
<title>Prepare RFP for sales call</title>
<status>Not started</status>
</task>
<task id=”t2” assigned=”fred”>
<title>Send white paper to customer</title>
<status>Completed</status>
</task>
</graph>
一実施形態において、クライアントがデータグラフを変更する仕方は2つある。第1に、テンプレートの入力エレメントをデータノードへ直接バインディングすることができ、このメカニズムは、ユーザが、既存のノードに属するXMLエレメントを変更できるようにし、そしてコードを必要としない。第2に(そして通常は)、テンプレートが、データを変更するアクションを呼び出す。
create()及びupdate()ファンクションが呼び出されたときに、フレームワークは、次のことを実行する。
A)オブジェクトをアプリケーションスキーマに対して検証すると共に、要求された全ての外部キーを検証する;
B)逆方向にトラバースできる関係(即ち、逆の関係)に対してキャッシュが一貫したものであることを保証する。
いずれかの条件を満足しない場合には、ランタイムエラーが発生される。
又、link()又はunlink()ファンクション(又、+=/−=演算子)が呼び出されたときにはkey/keyrefが強制される。
次のアクションは、create()ファンクションを使用してノードを生成することができる。
var po = <purchaseOrder><date>03/12/05</date></purchaseOrder>;
po.lineItems += <lineItem><prodId>ABC</prodId><qty>100</qty></lineItem>
po.lineItems += <lineItem><prodId>XYZ</prodId><qty>200</qty></lineItem>
po = $account.@@purchaseOrders.create(po);
ノードpoは、XML指定表現(第1ライン)により構成することができる。第2及び第3表現は、XMLノードを変更する。しかしながら、ノードは、create()ファンクションが呼び出されるまで検証される必要がない。
同様に、アプリケーションは、ノードのデータに直接アクセスすることにより既存のノードを変更することができる。例えば、次のコードは、特定の購入注文を検索し、次いで、状態を変更しそして新たなラインアイテムを追加する。
po = $account.@@purchaseOrders.where(.date == ”03/12/05”).*[0];
po.status = ”getQuote”;
po.lineItems += <lineItem><prodId>DEF</prodId><qty>300</qty></lineItem>
$po.update();
ここでも、ノードを検証するためにupdate()ファンクションがコールされる。
クライアントに新たなノードを生成するためにcreate()ファンクションを使用することができる。
var node = sourceNode.@@keyref.create(<node>[, callback, id]);
このファンクションは、挿入コンジットオペレーションをサポートするkeyrefにおいてコールすることができる。このファンクションはノードオブジェクトを返送する。
例えば、次のXScriptは、指定の$accountオブジェクトに対するcontacts keyref内の新たなcontactノードを構成する。
var contact =
<contact>
<salutation>Mr</salutation>
<first>Sydney</first>
<last>James</last>
<email>sydney@james.com</email>
</contact>;
node = account.@@contacts.create(contact);
function init() {
$context.contact = <contact><salutation/><first/><last/><email/></contact>;
return [”editContact.tmpl”];
}
次いで、テンプレートが入力コントロールを個々のコンテクストエレメントにバインディングする。
<input type=”text” netui:bind=”$context.email”/>
次いで、テンプレートは、第2のアクションを呼び出し、フレームワークは、アクションをコールする前に、HTML入力値をコンテクスト変数へ自動的に転送して戻す。次いで、アクションは、新たなノードを生成する。
function create() {
$context.contact = $account.@@contacts.create($context.contact);
return [”showContact.tmpl”];
}
一実施形態において、insertコンジットオペレーションを定義するkeyrefは、ノードを生成するのを許し、そして無効のnodesetにおけるノードを生成するように試みると、ランタイムエラーを生じさせる。
create()ファンクションは、コールバックファンクションを指定することもでき、これは、同期メカニズムが、ノードが生成された(即ち、関連コンジットオペレーションが新たな一次キーの返送に成功した)確認をサーバーから受信するときに呼び出される。例えば、
function foo(account, quote) {
node = account.@@requests.create(quote, bar);
}
function bar(request) {
$context.lastRequest = request;
}
コールバックファンクションには、生成されたノードをパラメータとして通すことができる。
update()ファンクションを使用して、クライアントにおいて変更されるノードを同期させることができる。
node.update([callback, id]);
このファンクションは、更新コンジットオペレーションをサポートするkeyrefにおいてコールされる。
update()ファンクションは、関連ノードのsyncState属性をMODIFIED(変更済)へセットすることができる。このメカニズムは、ノードが同期される前に、多数の編集を単一ノードに対して行えるようにする。
以下のコードにおいて、最初の2つの表現は、$contactノードのsyncStateをDSYNCにセットすることができ、そして最後の表現は、syncStateをMODIFIEDにセットすることができる。
contact.first = ”Bob”;
contact.address = <address><zip>10017</zip></address>;
$contact.update();
update()ファンクションは、同期メカニズムが、ノードが更新された(即ち、関連コンジットオペレーションが成功した)という確認をサーバーから受信したときに呼び出されるコールバックファンクションを指定することもできる。例えば、
function foo(account, quote) {
quote.update(bar);
}
function bar(request) {
$context.lastRequest = request;
}
コールバックファンクションには、生成されたノードをパラメータとして通すことができる。
一実施形態において、クライアントが、外部システムにおいて既に更新されている(別のクライアント又は他の外因性変化プロセスのいずれかにより)「古い」ノードを変更しそして同期しようと試みるときに、ノードの競合が生じる。古いノードとは、サーバーにより保持されている現在シーケンスナンバーとは異なるシーケンスナンバーを有するノードである。
ノードが古いためにサーバーが更新を拒絶する場合には、同期状態属性を「conflict」にセットした状態で最新のノードを返送する。
コールバックファンクションは、最初に、syncState()システムファンクションを使用して競合状態についてテストしなければならない。次いで、アプリケーションに対してグローバルな変数(即ち、$session)をセットしなければならない。例えば、
function updateCallback(node) {
if (node.syncState() == CONFLICT) {
$session.message = ”<a href='showConflict()'>edit conflicts</a>”;
$session.conflict = node;
}
}
<netui:html>{$session.message}</netui:html>
ここで、グローバル変数は、競合エディタページを表示するアクションへとユーザをナビゲーションできるHTMLアンカーを含む。
function showConflict() {
$context.node = $session.conflict;
return [”showConflict.tmpl”];
}
以下のshowConflictテンプレートは、古いノード及び最新のノードの値を横に並べて表示する。
<p>Contact record conflicted with server.</p>
<form netui:action=”$pageFlow.updateConflict()”>
<table><tbody>
<tr>
<td>First</td>
<td>{$context.node.conflict().first}</td>
<td><input type=”text” netui:bind=”$context.node.first”/></td>
</tr>
<tr>
<td>Last</td>
<td>{$context.node.conflict().last}</td>
td><input type=”text” netui:bind=”$context.node.last”/></td>
</tr>
<tr>
<td>Email</td>
<td>{$context.node.conflict().email}</td>
<td><input type=”text” netui:bind=”$context.node.email”/></td>
</tr>
<tr colspan=”3”>
<td><input type=”submit” value=”Create”/></td>
</tr>
</tbody></table>
</form>
<a href=”copyValues($context.node)”>Copy server's record.</a>
function updateConflict() {
$context.node.update();
$status.message = null;
$status.conflict = null;
return [”BACK”];
}
又、上述したテンプレートは、クリック時に以下のcopyValues()アクションをコールするアンカーも定義する。
function copyValues(node) {
node.copy(node.conflict());
return [”CONTINUE”];
}
このアクションは、最新のノード値を古いノードへコピーし、そしてshowConflictページに戻る。
一実施形態において、link()ファンクションは、1対多の関係を表わすkeyrefにノード(又はノードのリスト)を追加するのに使用される。
node.@@keyref.link(nodeList);
nodeListパラメータは、既に生成されたノードを参照しなければならないことに注意されたい。
unlink()ファンクションは、1対多の関係を表わすkeyrefからノード(又はノードのリスト)を除去するのに使用される。
node.@@keyref.unlink(nodeList);
以下のファンクションは、現在(コンタクト)ノードの関連keyrefから全ての「ウェブ」アカウントを除去する。これは、次いで、ファンクションへ通される単一のnewAccountノードをリンクする。
function foo(newAccount) {
contact = $current.@@accounts.*.where(.type == ”Web”);
current.@@accounts.unlink($contact);
contact.@@account.link(newAccount);
}
エラーオブジェクトは、サーバーにより発生され、そしてコンジットオペレーションが失敗したときにクライアントへ返送される。
エラーオブジェクトは、アプリケーションのコールバックファンクションへ返送され、このオブジェクトは、上記スキーマに対応するプロパティを有する。
エラーオブジェクトは、アプリケーションのコールバックファンクションへ返送され、このオブジェクトは、上記スキーマに対応するプロパティを有する。
function updateNode(node) {
node.update(updateCallback, <token/>)
}
function updateCallback(id, error) {
var msg = error.message;
var node = error.node();
var fields = error.field.*;
}
var msg = error.field(spath).message;
カスタムオブジェクト
テンプレートもアクションも、外部ソース(例えば、ウェブサービス)に直接アクセスすることができない。むしろ、外部プロセスは、MASフレームワークにより同期されるデータオブジェクトとしてモデリングされる。
var customNode = $sourceNode.@@keyref-A.create(<node>[, callback]);
var resultNodes = customNode.@@keyref-B.*;
keyref宣言は、次の図で示される。
次の例は、次のプロートタイプを有するウェブサービスオペレーションを仮定する。
xsd:double submitQuote(xsd:string prodId, xsd:integer qty);
このオペレーションは、prodId及びqty入力パラメータを取り上げ、そしてprice値を返送する。
これは、prodId及びqty入力パラメータと、price応答フィールドとを含むnodetypeに対するカスタムXMLスキーマ定義を要求する。
<quoteRequest><prodId/><qty>0</qty></quoteRequest>
通常、デフォールト値を含む充分に形成されたXMLオブジェクトを指定することによりコンテクスト変数を生成するアクションが呼び出される。次の例は、quoteRequestエレメントを生成し、そしてコントローラがinputRequestテンプレートをナビゲーションするようにさせる。
function initiateRequest() {
$context.request = <quoteRequest><prodId/><qty>0</qty></quoteRequest>;
return [”inputRequest.tmpl”];
}
<table><tbody>
<tr>
<td>Product ID</td>
<td><input netui:bind=”$context.quoteRequest.prodId”/></td>
</tr>
<tr>
<td>Quantity</td>
<td><input netui:bind=”$context.quoteRequest.qty”/></td>
</tr>
<tr>
<td colspan=”2”>
<input type=”submit” value=”Submit” onClick=”submitQuoteRequest()”/>
</td>
</tr>
</tbody></table>
function submitQuoteRequest() {
$current.@@quotes.create($context.request);
return [”showRequests.tmpl”];
}
create()ファンクションは、直ちに戻って、同期のための新たに生成されたノードをマークする。通常のノードを生成するのと同様に、同期は、バックグランドプロセスとして行われる。それ故、このアクションは、ナビゲータが現在の1組のクオテ(quote)要求を表示するようにさせる。
<netui:repeater id=”$quotes” source=”$current.@@quotes.*” iterator=”$i”>
<tr>
<td>{$i.prodId}</td>
<td>{$i.qty}</td>
<td>{$i.response.price}</td>
</tr>
</netui:repeater>
<quoteRequest>
<prodId>Widget-Z</prodId>
<qty>1000</qty>
<response>
<price>2000.00</price>
</response>
</quoteRequest>
showRequestsテンプレートが依然見える場合には、クライアントフレームワークは、テンプレートを再レンダリングさせ、これは、対応するテーブルの行を更新する。
select()ファンクションは、keyrefにおいてコールすることができ、直ちに値を返送しない。このファンクションは、テンプレート内からはコールできない。
node.@@keyref.select(spath, [callback, id]);
又、select()ファンクションは、ルートノードにおいてコールされてもよい。
$root.select(spath, [callback, id]);
このメカニズムは、クライアントがSPath表現により記述された仮想XML文書の一部分の同期を要求できるようにする。
$root.@@accounts.*.select(@@contacts.*);
次の表現は、ルートノードからアクセスできる全てのアカウントに対する全てのコンタクトを要求する。
$root.select(@@accounts.*.@@contacts.*);
述語での選択
あるkeyrefは、大きなもので、クライアントと完全に同期させることが不可能なことがある。これらの場合には、クライアントは、where()ファンクションを使用してkeyrefをフィルタすることができる。
$root.select(@@acounts.*.where(.type == ”Web”));
次の表現は、上述した一致するアカウントに対する全てのコンタクトを選択する。
$root.select(@@acounts.*.where(.type == ”Web”)).contacts.*;
次の表現は、一致するeメールアドレスを有する全てのコンタクトを選択する(全てのアカウントから)。
$root.select(@@accounts.*.@@contact.*.where(.email == ”bob@acme.com”));
<netui:repeater id=”s1” source=”$root.@@accounts.*” iterator=”i”>
<tr>
<td><input type=”checkbox” netui:bind=”i.@@checked”></a></td>
<td>{i}</td>
</tr>
</netui:repeater>
次の表現(テンプレートにより呼び出されたアクション内に含まれた)は、同期メカニズムが、全てのチェックされたアカウントに対して全てのコンタクトを検索するようにさせる。
$root.select(@@acounts.*.where(.@@checked == true).@@contacts.*);
コールバックメカニズムは、SPathに対する全同期が完了したときに、発呼者が、コールされるべきファンクションを指定できるようにする。例えば、
$root.select(@@accounts.*.@@contacts.*, $id, callbackFn);
この例は、同期スクリプトをサーバーに送信して全てのアカウントに対して全てのコンタクトを検索すると共に、同期が完了したときに、ファンクションcallbackFnを、クライアントフレームワークにより呼び出されるべきコールバックとして登録する。$id変数は、特定のセレクト呼び出しを識別するためにファンクションへ通される。
例えば、このメカニズムの1つのアプリケーションは、特定のアプリケーションに関する全てのテンプレートが各ページの底部に「状態バー」エレメントを含み、これが一時的データ値(例えば、$session.message)にバインディングするようにしてもよい。
<p>Status: <span>{$session.message}</span></p>
コールバックでセレクトを開始するアクションが1つのテンプレートからコールされてもよい。
q1 = ”Q1”;
function beginSearch(email) {
$root.select(@@accounts.*.@@contact.*.where(.email == email), q1, onUpdate);
}
ユーザ定義のコールバックファンクションonUpdate()は、同期要求が完了したときにコールされる。
function onUpdate(id) {
if (id == q1) {
$session.message = + ” Received results.”;
}
...
}
同期
通常、同期は、バックグラウンドで実行される。一実施形態において、同期に作用するものについてユーザが有する唯一のコントロールは、セレクトオペレーションが完了したときにコールバックを登録することである。
例えば、以下のファンクションは、コンタクトのファーストネーム及びラストネームを変更すると共に、アカウントノードを参照する外部キーも変更する。
function foo(contact, account) {
contact.first = $context.first;
contact.last = $context.last;
contact.@@accountId = account;
}
アクションが、その後のアクションを呼び出すことがあり、この場合には、最も外側のアクションがこの暗示的トランザクションの範囲を形成する。
ある場合には、キャッシュは、一連のテンプレート(例えば、「ウイザード(wizard)」を呼び出すページフローによって更新される。これらの場合には、前ページフローが首尾良く完了するまで同期を延期するために、アプリケーションは、関連データを生成するか又はコンテクスト変数へコピーしなければならない。次いで、最終的なページフローアクションがキャッシュを更新する。
時々、ユーザは、レコードをサブミットする容易ができるまで(例えば、サブミットファンクションをプレスすることにより)、見掛け上の同期を延期することを希望する。
例えば、次のテンプレートは、購入注文のリスト(アカウントに対する)及び各アイテムのチェックボックスを表示する。チェックボックスは、アイテムの状態を決定する属性へバインディングされる。
<netui:repeater id=”s1” source=”$account.@@purchaseOrders.*” iterator=”i”>
<tr>
<td><input type=”checkbox” netui:bind=”i.@@complete”></a></td>
<td>{i}</td>
</tr>
</netui:repeater>
<input type=”submit” onClick=”$pageFlow.submit()”/>
funciton submit() {
for (i = 0; i < $accounts.@@purchaseOrders.*.length(); i++) {
var po = $account.@@purchaseOrders.*[i];
if (po.syncState() == ”DSYNC” && po.@@complete == true) {
$po.update();
}
}
}
テンプレート
テンプレートは、アプリケーションのユーザインターフェイスを作り上げる充分に形成された(そして検証された)XHTMLページである。テンプレートは、通常、キャッシュ内のデータを参照し、又、アクションを呼び出すこともできる。一実施形態において、テンプレートは、データグラフを直接変更できるスクリプト表現を含まない。
アンカーは、SPath表現(例えば、$current.@@orders.*)を指定することができ、これは、コントローラが$current変数を変更して異なるノード又はnodesetを指すようにし、これは、ナビゲーションとして知られている。システムは、特定のテンプレートをあるnodetype及びkeyrefに関連付けできるメタデータを与えて、ブラウザが自動的に適当なテンプレートを選択できるようにする。
フレームワークは、アプリケーションの振舞いを変更する種々のシステムファンクションを実施することができる。例えば、navigate()ファンクションは、特定のテンプレートへナビゲーションし、そして$current変数をセットし、select()ファンクション(リピータ内でコールされる)は、リスト又はテーブルから特定ノードを選択するのに使用される。
アクションは、手前のテンプレートにバインディングされたコンテクスト変数を処理しそして計算を実行し又はデータを変更することができる。次いで、アクションは、現在ページへ直接戻ることができ、この場合に、データバウンドフォームコントロールが更新され、そして表示がリフレッシュされる。又、アクションは、コントローラが$current及び$page変数を変更するようにさせて、ナビゲーションを生じさせることもできる。
一実施形態において、テンプレートは、カーリーブレース(curly brace)内のSPath表現を引用することにより、キャッシュからのデータをページへ直接合体することができる。評価された表現の結果は、普通のXHTMLとして処理される。
例えば、次の表現は、現在ノードのラベルを表示する。
<p>{$current.label()}</p>
例えば、次の表現は、変数$context.addressのコンテンツを評価し、そしてその結果をアンカータグのhref属性に入れる。
<a href=”{$context.address}”>Click</a>
$context.address = ”mailto:alchemy@bea.com”;
これは、コントロールがページへ戻されたときに、次のXHTML表現を発生させる。
<a href=”mailto:alchemy@bea.com”>Click</a>
このセクションは、一実施形態において経歴スタックに維持される3つのシステム変数($current、$context、及び$page)を詳述する。
$current
$current変数は、ノードリスト(1つ以上のノード)を参照する。これは、ノード又はnodeset、或いはノードリストを生じる評価されたSPath表現に対する明確な参照でよい。
例えば、CRMアプリケーションは、単一アカウントノードを指すことを$currentに期待するaccountDetail.tmplページを実施してもよい。
<html>
<head>
<meta current=”node”/>
<title>Account Detail</title>
</head>
<body>
<p>Account: {$current}</p>
<a href=”$pageFlow.navigate($current.@@contacts.*, contacts.tmpl')”>Contacts</a>
...
</body>
</html>
<html>
<head>
<meta current=”nodelist”/>
<title>Contacts</title>
</head>
<body>
<table><tbody><tr>
<netui:repeater id=”$contacts” source=”$current” iterator=”$i” focused=”true”>
<td>first</td><td>{$i.first}</td>
<td>last</td><td>{$i.last}</td>
<td>email</td><td>{$i.email}</td>
<td><a href=”$s.previous()”>Previous</a></td><td><a href=”$s.next()”>Next</a></td>
</netui:repeater>
</tr></tbody></table>
</body>
</html>
ここで、焦点の合わされたリピータは、ユーザが、コンタクトノードの集合を通して循環するのを許す。
コンテクスト変数は、多ページプロセスを整合するためにテンプレート及びアクションに対する「スクラッチパッド」を与え、それらは、概念的には、セッション変数と同様である。
コンテクスト変数は、アクション内で実行される指定オペレーションによって生成される。
$context.foo = 100;
$context.foo.bar = <bar>FooBar</bar>
テンプレートは、表現言語シンタックスを使用してコンテクスト変数を参照する。
<p>{$context.foo}</p>
<p>{$context.foo.bar}</p>
$context.reset();
$page
$page変数は、現在レンダリングされたテンプレートを含む。これは、現在レンダリングされたページ内のHTMLコントロールの状態をアクセスするためにアクションにより使用される。
このセクションは、クライアントフレームワークによりサポートされるXHTMLへの拡張を詳述する。
一実施形態において、テンプレートは、充分に形成され及び検証されたXHTMLを含まねばならない。このセクションに述べるXHTML拡張は、netui namespace内に定義され、全ての例は、次のnamespace宣言を必要とする。
<html xmlns=”http://www.w3.org/1999/xhtml”
xmlns:netui=”http://www.bea.com/netui”>
<a>(アンカー)タグは、ユーザがクリックして事象をトリガーさせることのできるハイパーリンクを生成する。アンカーは、ナビゲーションを行い、システムファンクション(アイテムの選択を含む)を呼び出し、そしてアクションを呼び出すのに使用される。
アンカーは、SPath表現(例えば、$current.@@orders.*)を指定することができ、これは、コントローラが、$current変数の値を変更して、異なるノード又はnodesetを指すようにさせ、これは、ナビゲーションとして知られている。
<a href=”url”/>
ナビゲーション
ナビゲーションは、種々の手段によって達成することができ、以下の例では、ブラウザがルートノードへナビゲーションさせる。
<a href=”$root”>Example 1</a>
<a href=”$pageFlow.navigate($root, bar.tmpl')”>Example 2</a>
<a href=”$pageFlow.foo($root, bar.tmpl')”>Example 3</a>
function foo($s, $p) {
return [$s, $p];
}
<a href=”$globalApp.history.home()”>Example 4</a>
例2は、システムnavigate()ファンクションをコールし、これは、$currentを、評価されたSPath表現にセットし、そして任意の第2パラメータを使用して、テンプレートをセットする。
例3は、ユーザアクション(コントローラファイルで定義された)を呼び出し、これは、通過されたパラメータを使用して、フォワードオブジェクト(アレー)を生成し、これは、例2と同じ作用を有する。
次の例は、1組の注文をリストし、そしてそれらの1つをクリックすることにより「選択された注文」として「選択」することを示す。
<netui:repeater id=”foo” source=”$current.@@orders.*” iterator=”$thisorder”>
<a href=”$foo.select($thisorder)”>{$thisorder.label()}</a>
</netui:repeater>
<netui:repeater id=”foo” source=”$current.@@orders.*” iterator=”$thisorder” focused=”true”>
<tr>
<td>OrderID: </td><td>{$thisorder.id}</td>
<td>OrderDate: </td><td>{$thisorder.date}</td>
<td>OrderAmount: </td><td>{$thisorder.amount}</td>
</tr>
<tr>
<td><a href=”$foo.previous()”>Previous</a></td>
<td><a href=”$foo.next()”>Next</a></td>
</tr>
</netui:repeater>
一実施形態において、データを表示するために、必要とされるものは、カーリーブレースにエンクローズされたSPathだけである。
例えば、$currentがコンタクトを参照する場合には、次のものがコンタクトのネーム及びアドレスを示す。
<tr>
<td>First:</td><td>{$current.name.first}</td>
<td>Last:</td><td>{$current.name.last}</td>
</tr>
しかし、これは、リードオンリモデルである。
<input type=”intputType” netui:bind=”SPath”/>
SPath表現は、通常、$context変数を参照する。例えば、
<input type=”text” netui:bind=”$context.address.name”/>
この変数は、ページがレンダリングされるときに入力フィールドの値をセットするのに使用される。
入力タグ
<input>タグは、type属性の値に基づいて種々の簡単なコントロールを実施する汎用の入力タグである。
<input type=”inputType” netui:bind=”spath-expr”/>
フレームワークは、netui:bind属性を、XHTMLでサポートされる標準的な属性に追加する。
<input type=”text” netui:bind=”$context.contact.email”/>
<input type=”radio” netui:bind=”$context.contact.selected” value=”yes”/>
<input type=”radio” netui:bind=”$context.contact.selected” value=”no”/>
<input type=”checkbox” value=”chinese” netui:bind=”$context.contact.langsSpoken”/>
<input type=”password” netui:bind=”$context.login.password”/>
<input type=”hidden” netui:bind=”$context.contact.MailingCountry” value=”USA”/>
<input type=”button” value=”press this button”/>
無線タグは、単一の値だけを選択してもよいようにグループ分けすることができ、同じ論理的グループ内の各無線タグを同じSPath表現にバインディングしなければならない。
<p>Selected:
<input type=”radio” netui:bind=”$context.contact.selected” value=”yes”>Yes</input>
<input type=”radio” netui:bind=”$context.contact.selected” value=”no”>No</input>
</p>
サブミット
サブミットのタイプは、onClick属性を定義し、これは、アンカー(上述した)と同様に振舞う。
<input type=”submit” onClick=”$pageFlow.submitContact()”/>
これは、クリックされると、バインディングされた全ての変数(ページ上の)を、現在入力タグ値と共に書き込ませる。
<textarea>タグは、ユーザがテキストの多数のラインを入力及び編集できるようにし、これは、スクロールバーの表示を伴ってもよい。
<textarea netui:bind=”spath-expr”/>
フレームワークは、XHTMLでサポートされた標準的属性にnetui:bind属性を追加する。
例えば、次のXHTMLエレメントは、<textarea>エレメントを生成し、これは、$context変数により参照されるノートノードのcomments子エレメントにバインディングされる。
<textarea netui:bind=”$current.note.comments”/>
<select>タグは、ユーザがドロップダウンコントロールから多数のアプリケーション定義値の1つを選択できるようにする。
<select netui:bind=”spath-expr”/>
フレームワークは、HTMLでサポートされる標準的属性にnetui:bind属性を追加する。
contactTypeスキーマ定義は、salutationエレメントを含み、これは、contactSalutationEnumタイプを有するように定義される。
<xsd:complexType name=”contactType”>
<xsd:sequence>
<xsd:element name=”salutation” type=”contactSalutationEnum”/>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name=”contactSalutationEnum”>
<xsd:restriction base=”xsd:string”>
<xsd:enumeration value=”Mr”/>
<xsd:enumeration value=”Mrs”/>
<xsd:enumeration value=”Ms”/>
<xsd:enumeration value=”Dr”/>
</xsd:restriction>
</xsd:simpleType>
<select netui:bind=”$context.contact.salutation”>
任意の値を明確に宣言することができる。
<select netui:bind=”$context.contact.salutation”>
<option value=”Mr”>Mr</option>
<option value=”Ms”>Ms</option>
<option value=”Mrs”>Mrs</option>
<option value=”Dr”>Dr</option>
</select>
<select netui:bind=”$context.contact.salutation” iterator=”i”>
<netui:repeater source=”$globalApp.schema(contactSalutationEnum')”>
<option value=”{$i.@value}”>{$i.@value}</option>
</netui:repeater>
</select>
netui:bind表現に一致する値は、デフォールトオプションとして選択されることに注意されたい。バインディングされた値がナルである場合には、最初のオプションが選択される。
次の例は、emailコンテクスト変数をテキスト入力フィールドにバインディングする。それに対応するアクションは、フォームのアクション属性を使用して呼び出すこともできるし、又はネスト状のアンカータグで呼び出すこともできる。
<form netui:action=”$pageFlow.inputEmailAddress()”>
<input type=”text” netui:bind=”$context.email”/>
<input type=”submit” value=”Submit”/>
</form>
典型的に、コンテクスト変数は、最初、テンプレートを表示させる先行アクションにおいてインスタンス生成される。次のアンカーは、addContact()アクションを呼び出す。
<a href=”$pageFlow.addContact()”/>Create New Contact</a>
function addContact() {
$context.reset();
$context.account = $current;
$context.salutation = ””;
$context.first = ””;
$context.last = ””;
$context.email = ””;
return [”addContact.tmpl”];
}
<form netui:action=”$pageFlow.createContact()”>
<table><tbody>
<tr>
<td>Title</td>
<td>
<select netui:bind=”$context.salutation”>
<option value=”Mr”>Mr</option>
<option value=”Ms”>Ms</option>
<option value=”Mrs”>Mrs</option>
<option value=”Dr”>Dr</option>
</select>
</td>
</tr>
<tr>
<td>First</td><td><input type=”text” netui:bind=”$context.first”/></td>
</tr>
<tr>
<td>Last</td><td><input type=”text” netui:bind=”$context.last”/></td>
</tr>
<tr>
<td>Email</td><td><input type=”text” netui:bind=”$context.email”/></td>
</tr>
<tr colspan=”2”>
<td><input type=”submit” value=”Create”/></td>
</tr>
</tbody></table>
</form>
function createContact() {
$context.account.@@contacts.create(
<contact>
<salutation>{$context.salutation}</salutation>
<first>{$context.first}</first>
<last>{$context.last}</last>
<email>{$context.email}</email>
</contact>
);
return [”showContacts.tmpl”];
}
<netui:if>タグは、計算された条件に基づきXHTMLセグメントを条件付きで含むように使用することができる。
<netui:if cond=”spath-expr”>...</netui:if>
cond属性は、ページがレンダリングされるときに評価されるSPath表現を定義する。この表現が真と評価される場合には、<netui:if>エレメント内に含まれたXHTMLセグメントがXHTMLページに挿入される。
{true}
{100}
{”some string”}
{<xml>}
{$root}
以下の例は、条件付きテンプレートを実施するために<if>タグを含む。ここで、$current.emailテーブル列は、変数が非ナル(即ち、空又はゼロ長さのテキスト)の場合にのみ表示され、他の全ての値は、真に強制される。
<table><tbody>
<tr>
<td>{$current.salutation}</td>
<td>{$current.first}</td>
<td>{$current.last}</td>
<netui:if cond=”$current.email”>
<td>{$current.email}</td>
</netui:if>
</tr>
</tbody></table>
条件付きテンプレートは、テンプレート設計におけるプロパティシートとして表示できることに注意されたい。
テンプレートは、データグラフ及びシステム変数からの普通のXHTMLエレメント及びデータを合体する。又、それらは、レンダリングされるときにXHTMLを発生するエレメントを含んでもよい(JSPにおけるTaglibsと同様に)。
リピータは、エレメントリスト(例えば、アカウントのノードリスト)にわたって中継するHTMLジェネレータタグである。<netui:repeater>は、エレメントに対して同じHTMLを中継するのに使用されるタグであり、<netui:repeater>エレメントの全ての子エレメントは、評価されたSPath表現の各エレメントに対して中継される。
<netui:repeater
id=”tag-id”
source=”spath-expr”
[iterator=”variable-name”]
[selected=”spath-expr”]
[orderBy=”orderBy-expr”]/>
各<netui:repeater>エレメントは、それが繰り返さねばならないところの1組のノードを記述するsource属性を有する。概念的には、テンプレート内部の全てのXHTMLは、source属性により記述される各ノードに対して中継される。中継されるXHTMLセグメントは、iterator属性により参照される繰り返されるノードインスタンスにアクセスすることができる。
次のテンプレートセグメントは、アカウントkeyrefにより定義されるノードのリストを表示するリピータを定義する。
<ul>
<netui:repeater id=”$repeater1” source=”$current.@@accounts.*” iterator=”$i”>
<li>{$i.label()}</li>
</netui:repeater>
</ul>
これは、次の出力を生成する。
<netui:repeater>エレメント内に含まれた全てのXHTMLエレメントは、source属性により定義されたノードリスト内の各ノード(即ち、各アカウントノード)に対して中継される。
中継されたセクションは、アクション又はシステムファンクションを呼び出すアンカーを含んでもよい。例えば、以下のリピータは、アカウントのリストを表示し、アンカー(ハイパーテキスト)を各アカウントのラベルと共に表示する。
<ul>
<netui:repeater id=”$repeater1” source=”$current.@@accounts.*” iterator=”$i”>
<li><a href=”$pageFlow.navigate($i, showDetail.tmpl')”>{$i.label()}</a></li>
</netui:repeater>
</ul>
<ul>
<netui:repeater id=”$repeater1” source=”$current.@@accounts.*” iterator=”$i”>
<li><a href=”$repeater1.select($i)”>{$i.label()}</a></li>
</netui:repeater>
</ul>
<ul>
<netui:repeater id=”$repeater1” source=”$current.@@accounts.*” iterator=”$i”>
<li>
<a href=”$repeater1.select($i) ”
style='{$repeater1.selected.contains($i) ? ”background-color:yellow”:””}>
{$i.label()}</a>
</li>
</netui:repeater>
</ul>
<p>Type: {$repeater1.selected.type}<p>
上記<a>アンカーは、関連アイテムが選択された場合にエレメントのバックグランドカラーを変更するSPath表現を含むスタイル属性を宣言する。
selected属性は、他のリピータ(チェーンとして知られている)及びその後に呼び出されるアクションによりアクセスすることができる。又、中継されるHTMLセクションは、selected属性を参照して、現在選択されたアイテムを視覚指示することもできる。
リピータは、親リピータにおけるエレメントの選択が子リピータにおいて表示されるものに影響するように、一緒にチェーン接続することができる。例えば、次のリピータは、手前のリピータにおいて選択されたノード(Contact)に関連したメッセージのリストを表示する。
<ul>
<netui:repeater id=”$repeater1” source=”$current.@@accounts.*” iterator=”$i”>
<li><a href=”$repeater1.select($i)”>{$i.label()}</a></li>
</netui:repeater>
</ul>
<br/>
<ul>
<netui:repeater id=”$repeater2” source=”$repeater1.selected.@@contacts.*” iterator=”$j”>
<li>$j.label()</li>
</netui:repeater>
</ul>
<table><tbody>
<tr>
<td>App</td><td>Repeater 1</td><td>Repeater 2</td><td>Contacts</td>
</tr>
<tr>
<td>{$current}</td>
<td><ul>
<netui:repeater id=”$x” source=”$current.@@keyref('*')” iterator=”$i”>
<li><a href=”$x.select($i)”>{$i}</a></li>
</netui:repeater>
</ul></td>
<td><ul>
<netui:repeater id=”$y” source=”$x.selected.*” iterator=”$j”>
<li><a href=”$y.select($j)”>{$j}</a></li>
</netui:repeater>
</ul></td>
<td><ul>
<netui:repeater source=”$y.selected.@@contacts.*” iterator=”$k”>
<li>{$k}</li>
</netui:repeater>
</ul></td>
</tr>
</tbody></table>
ノードのテーブルを表わすようにUIを更に変更することができる。例えば、
<td>
<table><tbody>
<netui:repeater source=”$y.@@contacts.*” iterator=”$k”>
<tr>
<td>{$k.email}</td>
<td>{$k.label()}</td>
</tr>
</netui:repeater>
</tbody></table>
</td>
又、リピータは、「焦点が当てられる」ように定義されてもよく、これは、source属性により定義されたエレメントの全集合にわたって繰り返すのではなく、リピータが一度に1つのエレメントしか示さず、カーソルを維持することを意味する。
次の付加的なファンクションは、焦点型リピータオブジェクトにおいてコールされてもよい。
function selectContacts($account) {
$context.cursor = $account.*[0];
return [$account.*, ”focusedContacts.tmpl”];
}
<netui:repeater id=”$s” source=”$current” iterator=”$i”>
<netui:if cond=”$s.position($context.cursor) == $i.count()”>
<td>first</td><td>{$i.first}</td>
<td>last</td><td>{$i.last}</td>
<td>email</td><td>{$i.email}</td>
</netui:if>
</netui:repeater>
<netui:if cond=”$s.position($context.cursor) > 0”>
<a href=”$context.cursor = $current[$s.position($context.cursor)-1]”>previous</a>
</netui:if>
<netui:if cond=”$s.position($context.cursor) < ($s.length()-1)”>
<a href=”$context.cursor = $current[$s.position($context.cursor)+1]”>next</a>
</netui:if>
<netui:repeater id=”$s” source=”$current” iterator=”$i” selected=”$context.selected”>
<td>first</td><td>{$i.first}</td>
<td>last</td><td>{$i.last}</td>
<td>email</td><td>{$i.email}</td>
</netui:repeater>
リピータは、orderBy属性を宣言することによりエレメントが列挙される順序を指定できる。orderBy属性は、XQuery状の表現を含むストリングである。
<netui:repeater id=”id” source=”source” iterator=”var”
orderBy=”OrderByClause”>
orderByClauseが次のBNF文法に合致する場合(SPath表現は、特定のリピータアイテムに対するフィールド値を表わす):
OrderByClause ::= OrderSpec (”,” OrderSpec)*
OrderSpec ::= SPath OrderModifier
OrderModifier ::= (”ascending” | ”descending”) ?
((”empty” ”greatest”) | (”empty” ”least”)) ?
(”collation” StringLiteral)?
例えば、次のリピータは、コンタクトのラストネーム(即ち、$i.last)の降下する値によりコンタクトをリストする。
<netui:repeater id=”$s” source=”$current.@@contacts.*” iterator=”$i”
orderBy=”$i.last descending”>
<td>last</td><td>{$i.last}</td>
<td>first</td><td>{$i.first}</td>
<td>email</td><td>{$i.email}</td>
</netui:repeater>
<netui:repeater id=”$s” source=”$current.@@contacts.*” iterator=”$i”
orderBy=”$i.last empty least, $i.first descending”>
上記例では、空きのラストネーム値は、最下位とみなされることに注意されたい。
又、リピータは、データモデルにより定義されたメタデータにわたって繰り返すように使用することもできる。
例えば、node.keyref(‘*’)ファンクションは、対応するnodetypeからの考えられるナビゲーションを記述するkeyrefエレメントのリストを返送する。これは、keyrefのリストを表示するためにリピータのソースとして使用されてもよい。
<ul>
<netui:repeater id=”$repeater1” source=”$current.@@keyref(*')” iterator=”$i”>
<li>{$i.label()}</li>
</netui:repeater>
</ul>
−owner
−subAccount
−contacts
−notes
−events
−qutotes
<netui:repeater id=”repeater1” source=”$current.meta().schema()”
showNull=”true” iterator=”$i”>
<tr>
<td>{$current.meta().schema().getFieldLabel($i)}</td>
<td>{$i)</td>
</tr>
</netui:repeater>
映像タグ
標準的なXHTML<img>タグは、映像を表示するのに使用される。
<img
[src=”filename”]
[netui:content=”spath-expr”]
[netui:type=”content-type”]/>
映像タグは、次の属性を定義する。
例えば、以下のコンタクトスキーマは、<image>データエレメントを合体するように拡張されている。
<xsd:complexType name=”contactType”>
<xsd:sequence>
<xsd:element name=”salutation” type=”contactSalutationEnum”/>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
<xsd:element name=”image” type=”xsd:base64Binary”/>
</xsd:sequence>
</xsd:complexType>
<img netui:content=”$current.contact.image” netui:type=”bmp”/>
includeタグ
標準的な<netui:include>タグは、参照されたものを挿入するのに使用される。
<netui:include template=”templateFile” [$current=”spath-expr”]/>
includeタグは、現在ページへ挿入されるべきテンプレートを命名するtemplate属性を定義する。任意のcurrent属性は、$currentを、挿入されたテンプレートの範囲内にセットするのに使用される。
<td><ul>
<netui:repeater id=”$z” source=”$y.@@contacts.*” iterator=”$k”>
<li><a href=”select($k)”>{$k}</a></li>
</netui:repeater>
</ul></td>
<td>
<netui:include current=”$z.selected” template=”detail.tmpl”/>
</td>
<td>
<table><tbody>
<tr><td>Detail</td></tr>
<tr><td>{$current.label()}</td></tr>
<tr><td>{$current.email}</td></tr>
</tbody></table>
</td>
これは、次の出力を生じる。
<netui:html>タグは、生のXHTMLを現在ページに挿入するのに使用される。
<netui:html>{spath-expr}</netui:html>
通常、SPath表現が評価され、そしてそれにより生じる値がストリングとして解釈され、HTMLとして処理されない。しかしながら、オープニングとクロージングの<netui:html>タグ間に含まれた全ての評価されたSPath表現は、ブラウザにより処理されるべきHTMLとしてページに挿入される。
$current.productDesc = ”<p>A <b>great</b> new product.</p>”;
次のテンプレートHTMLは、以下の出力を返送する。
<netui:html>{$current.productDesc}</netui:html>
優れた新規製品
HTML及び表現は、<netui:html>エレメント内に合成されてもよい。例えば、次のテンプレートHTMLは、以下の出力を返送する。
<netui:html>
<ul><li>{$current.productDesc}</li><li>{$current.productDetail}</li><ul>
</netui:html>
−優れた新規製品
−あなたにウェブロジックを運ぶ人々から
コントローラは、外部同期メッセージに応答してユーザインターフェイス及びデータベースにより引き起こされた事象を処理する責任をもつことができる。コントローラは、アクションスクリプトを実行させ、且つテンプレートをブラウザによりインスタンス生成して表示させることができる。コントローラのデフォールト振舞いは、XMLに対してECMAScriptで書かれ且つ本質的にJPFのECMAScriptバージョンであるcontroller.xpfを実施することにより、拡張できる。
コントローラファイルは、アクション及び普通のECMAScriptファンクション、並びにグローバルな変数定義を含むことができる。
controller.xpfファイルは、アプリケーションに関するページフローを定義することができる。アプリケーションのクライアント部分は、コントローラ定義、アクション、及び1組のテンプレートで構成される。
function begin()
{
return [”home.tmpl”];
}
フォワードアレーは、XScriptオブジェクト(即ち、ストリング、変数、SPath表現)のアレーであり、これらは、表示すべき次のテンプレート(即ち、$page変数)を決定しそして$currentシステム変数の値をセットするためにコントローラにより解釈される。
return [”BACK”]
return [”home.tmpl”];
return [”home.tmpl”, $root.@@accounts.*];
return [nextAction];
return [];
以下の例では、アクションは、コンテクスト変数を使用して計算を実行すると共に、それが成功すると、showOrderテンプレートへナビゲーションする。アラーが生じると、アクションは、エラーコンテクスト変数をセットし、そして現在テンプレートに留まるようにコントローラに指令する。
function calulateTotal() {
if ($context.order.qty <= 0) {
$context.error = ”Error: Quantity not set.”;
return [”CONTINUE”];
}
$context.order.total = $context.order.price * $context.order.qty;
return [”showOrder.tmpl”];
}
アクションは、アプリケーションがデータを変更し、現在テンプレートを変更し、又はナビゲーションに影響を及ぼすためのメカニズムを与えることができる。例えば、アクションは、データノードを生成又は更新し、特定のnodesetにおける合計を計算し、或いはブラウザをデータモデルの異なる部分へ向け直してもよい。一実施形態では、テンプレートは、ローカルデータキャッシュ(又は$context)に記憶されたデータしかアクセスできないので、アクションは、外部システムと対話する(オンターネットを経て)メカニズムを与える。
$pageFlow.actionName([param1[, param2[, ...]]])
例
次のアンカー宣言は、foo()アクションを呼び出し、ストリングパラメータにおいて通過させる。
<a href=”$pageFlow.foo(World')”>Foo</a>
The action definition (defined in controller.xpf) is show below.
function foo($p) {
$context.bar = <hello>{$p}</hello>;
return [”CONTINUE”];
}
この場合、アクションは、$context変数(入力パラメータを含むXMLオブジェクト)をセットし、そしてコントロールを現在テンプレートへ戻す。
function example1($p) {
...
return [$root.@@accounts.*];
}
次の例は、$currentをルートノードにおけるポイントへ変化させ、そして現在テンプレートも変化させる。
function example2($p) {
...
return [$root, ”bar.tmpl”];
}
タイマーは、簡単な事象発生メカニズムを実施する。addTimer()ファンクションは、指定の遅延の後に、任意であるが規則的な間隔で呼び出されるコールバックファンクションを登録するのに使用される。
var timerId = $pageFlow.addTimer(callback, delay[, period]);
このファンクションは、$pageflowオブジェクトにおいてコールされ、そしてタイマーインスタンスを独特に識別する識別子を返送する。
$pageFlow.addTimer(timerId);
このファンクションは、$pageflowオブジェクトにおいてコールされ、そしてタイマーインスタンスを独特に識別する識別子を返送する。
次の例において、ファンクションfoo()は、タイマーをセットし、該タイマーは、bar()ファンクションを直ちにスケジュールし、次いで、1秒間隔で繰り返しスケジュールする。
function foo() {
var timerId = $pageFlow.addTimer(bar, 0, 1000);
}
function bar(timerId, count) {
$root.select(@@accounts.*.@@contacts.*.@@tasks.*.where(.priority == 1));
if (count == 10) {
$pageFlow.cancelTimer(timerId);
}
}
ブラウザは、単一スレッドの実行モデルを実施し、それ故、コールバックファンクションは、少なくともコールファンクションが戻るまで実行されない。
ナビゲーションが行われるたびに、<$current x $context x $page>タプルが、$historyシステム変数によりアクセスできる経歴スタックに入れられる。
back()システムアクションをコールすると、これらの値を以前の経歴状態へロールバックさせ、同様に、forward()は、これらの値を次の経歴状態へ移動させる。ユーザが後方に移動しそして異なるナビゲーションを生じさせる場合には(即ち、前方に移動するのではなく)、全フォワード経歴が裁断される。
$historyオブジェクトについて定義されるファンクションは、前記で定義された。
図10は、CRMアプリケーション1000の一部分の簡単なページフローを示し、ダイアグラムa)は、データモデルの一部分(スキーマ及びkeyref)を表わし、そしてダイアグラムb)は、$current nodetypeを指示する点線を各々もつ4つのテンプレートで構成されたページフローを表わす。このシナリオは、特定のアカウントに対するクオテ(quote)要求を開始するためにカスタムオペレーションを実施する。この例は、セレクトオペレーションのコンテクストとして使用されるカスタムオブジェクト(クオテ要求)を生成するプロセスを示す。
<a href=”$pageFlow.createQuoteRequest()”>Create Quote Request</a>
function createQuoteRequest() {
$context.quoteRequest.prodId = ””;
$context.quoteRequest.qty = 0;
return [”createQuoteRequest.html”];
}
このアクションは、現在コンテクスト内の<quoteRequest>XMLオブジェクトを生成し、そしてprodId及びqty子エレメントに対する値をセットする。これは、充分に形成された<quoteRequest>エレメントを生成し、次の表現と同等である。
$context.quoteRequest = <quoteRequest><prodId/></qty>0<qty></quoteRequest>;
<p>Quote Request for {current.label()}</p>
<table><tbody>
<tr>
<td>Product ID</td>
<td><input netui:bind=”$context.quoteRequest.prodId”/></td>
</tr>
<tr>
<td>Quantity</td>
<td><input netui:bind=”$context.quoteRequest.qty”/></td>
</tr>
<tr>
<td colspan=”2”>
<input type=”submit” value=”Submit” onClick=”submitQuoteRequest()”/>
</td>
</tr>
</tbody></table>
function submitQuoteRequest() {
if ($context.quoteRequest.prodId != ”” || $context.quoteRequest.qty <= 0) {
return [”CONTINUE”];
}
else {
$current.@@quoteRequests.create($context.quoteRequest);
return [”BACK”];
}
}
<quoteRequest>
<prodId>Widget-Z</prodId>
<qty>1000</qty>
</quoteRequest>
<p>Account: {$current}</p>
<td>Product ID</td><td>Quantity</td><td>Price</td>
<netui:repeater source=”$current.@@quoteRequests.*” iterator=”i”>
<td>{$i.prodId}</td>
<td>{$i.qty}</td>
<td>{$i.@@quote.price}</td>
</netui:repeater>
<a href=”$pageFlow.createQuoteRequest()}”>Create Quote Request</a>
前記のsubmitquoteRequestアクションは、直ちに戻り、従って、新たなquoteRequestノードは、サーバーが同期されたquoteノードで応答するまで、価格フィールドを表示しないことに注意されたい。
プロートタイプを構築して実行するために、次のアプリケーションをインストールする必要がある:Apache Ant、Sun java JDK、Perforce client、BEA Workshop 8.1。又、次の環境変数もセットしなければならない。
C:\alchemy\mas> p4 sync
C:\alchemy\mas> ant rebuild
プロートタイプブラウザは、ブラウザのant構築ファイル(\alchemy\mas\src\browser\build.xml)を経て呼び出すことができる。
次のランタイム変数が定義される。
ant f ..\..\src\browser\bulid.xml Dmas.appname=crm Dclient.geometry=400x200
run
このコマンドを呼び出すためにバッチファイル(例えば、run.bat)を生成するのが便利である。
又、ブラウザは、次の環境変数を設定することにより構成できる。
set MAS_PROPS=-Dmas.singleproc=false Dpersistent=true
サービス定義(コンジットメタファイル)において定義されたウェブサービスURLは、ウインドウズ(登録商標)ホストファイル(C:\WINDOWS\SYSTEM32\DRIVERS\ETC\host)において物理的IPアドレスを宣言することにより物理的サーバーへマップすることができ、例えば、次のホストファイルは、上記ウェブサービスを、alchemyテストサーバーへマップする。
172.17.33.34 example.com
全てのエラー及びトレース情報は、\alchemy\mas\alchemy.logファイルへ書き込まれる。
アプリケーションパッケージング
以下のテーブルは、個々のMASアプリケーションに対してファイル及びディレクトリー構造を表わす。
アプリケーションルートディレクトリー(/apps)は、mas.approot及びmas.cliant.approotのランタイムプロパティ(上述した)に対応する。
アプリケーションは、MAS(ワークショップ内で実行される)からクライアントへ配備することができる。
1.ワークショップは、アプリケーションマネージャーサーバーにおいて実行されねばならない(以下を参照)。
2.アプリケーションコンポーネント(上述したコントローラテンプレート、メタファイル、及びスキーマファイル)は、先ず、単一ファイルに(app.zip)にジップされねばならず、これを行うために、新たなジップファイルを生成し、全appフォルダー(例えば、\mas\apps\crm)をWinZipへドラグする(NOTチェック状態で「全経路infoをセーブする」のを確保する)。
3.アプリケーションadminページ:http://www.localhost.com:7001/masを見る。これは、しばらくの間を要してもよいことに注意されたい。
a.”ブラウズ・・・”をクリックし、そしてジップファイルを選択する。
b.”配備”をクリックし、アプリケーションをサーバーへアップロードする(上述したmass.approotプロパティにより定義された位置において)。
4.adminページは、各アプリケーションに対して配備URLを表示する。
5.クライアントにアプリケーションを「インストール」するために、移動ブラウザを単一プロセスモードで実行する(mas.appプロパティを指定せずに;これは、appセレクタダイアログを呼び出す)。
set MAS_PROPS=-Dmas.singleproc=false
ant f ..\..\src\browser\bulid.xml run
6.アプリケーションURLを適当な編集ボックスにエンターし、そしてOKをクリックする。
1.次のグローバル環境変数をセットする。
set JAVA_OPTIONS=-Dmas.approot=c:\alchemy\mas\apps
2.\alchemy\mas\src\masjws.workをワークショップへロードする。
3.プロジェクトパンにおいてcontroller.jpfファイルをダブルクリックする。
4.ライブラリーアップグレードについて促された場合には、イエスと言い、次いで、Installをクリックする。赤い”could not be replaced”警報は、安全に無視できる。
5.サーバーをスタートする(ツール→WebLogicサーバー→スタートWebLogicサーバー)。
6.サーバーがスタートした後、次のコマンドを実行する。(WebLogic配備エラーは安全に無視できる)。
C:\alchemy\mas > ant deploy
8.クライアントアプリケーション配備についてc:\temp\appを生成する。
9.次の環境変数をセットする。
set MAS_PROPS=-Dmas.client.approot=c:\temp\apps -Dmas.singleproc=false
10.次のコマンドを実行する。
C:\alchemy\mas\src\browser > ant run
11.ウェブページ(上述した)にリストされたURLをダイアログにペーストしそしてInstallをクリックする。最終的に、アプリケーションは、コンボボックスにいっぱいにリストされ、そしてログインが可能となる
アプリケーションスキーマ定義は、次のスキーマディレクティブを使用して、パブリックMASスキーマファイルをインポートしなければならない。
<xsd:import namespace=”urn:bea.mas” schemaLocation=”mas.xsd”/>
MASスキーマファイルは、全てのフレームワークXMLタイプに対する定義を含む。
<?xml version=”1.0” encoding=”UTF-8”?>
<xsd:schema targetNamespace=”urn:bea.mas” xmlns=”urn:bea.mas”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”>
<xsd:simpleType name=”idType”>
<xsd:restriction base=”xsd:anySimpleType”/>
</xsd:simpleType>
<xsd:complexType name=”nodeSetType”>
<xsd:sequence>
<xsd:any minOccurs=”1” maxOccurs=”1”/>
</xsd:sequence>
<xsd:attribute name=”keyref” type=”xsd:string” use=”required”/>
</xsd:complexType>
<xsd:complexType name=”rootType”/>
<xsd:element name=”root” type=”rootType”/>
<xsd:complexType name=”graphType”>
<xsd:sequence>
<xsd:element ref=”root”/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”errorType”>
<xsd:sequence minOccurs=”0” maxOccurs=”unbounded”>
<xsd:choice>
<xsd:element name=”pkey” type=”idType”/>
<xsd:element name=”system” type=”systemErrorType”/>
<xsd:element name=”message” type=”xsd:string”/>
<xsd:element name=”field” type=”fieldErrorType”/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”systemErrorType”>
<xsd:sequence>
<xsd:element name=”code” type=”xsd:anySimpleType”/>
<xsd:element name=”message” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”fieldErrorType”>
<xsd:sequence>
<xsd:element name=”code” type=”xsd:anySimpleType”/>
<xsd:element name=”message” type=”xsd:string”/>
</xsd:sequence>
<xsd:attribute name=”xpath” type=”xsd:string”/>
</xsd:complexType>
</xsd:schema>
フレームワークは、ノードグラフをトラバースするのに使用できる自動ブラウザ(ナビゲータと称される)を合体する。以下の出力は、次のコマンドラインシンタックスを使用して、CRM例から発生される。
ant f ..\..\src\browser\bulid.xml -Dmas.app=crm Dmas.client.app=navigator
run
自動的なUIは、2つのテンプレートで構成され、即ち第1は、現在「焦点の合わされた」ノード($current)と、ユーザがナビゲートできるkeyrefのリストとを表示する「ナビゲータ」テンプレートであり、そして第2のテンプレートは、特定ノードの「詳細」フォームビューである。
<table><tbody>
</tr>
<td><b>{$current}</b></td>
</tr>
<tr>
<netui:repeater id=”$x” source=”$current.keyref('*').*” iterator=”$i”>
<td><img src=”bullet.gif”></td>
<td><a href=”select($i)”>{$i}</a></td>
</netui:repeater>
</tr>
<tr>
<netui:repeater id=”$y” source=”$x.selected.*” iterator=”$j”>
<td><a href=”$pageFlow.navigate($j, 'navigator.tmpl')”>NAV</a></td>
<td><a href=”$pageFlow.navigate($j, 'detail.tmpl')”>{$j}</a></td>
</netui:repeater>
</tr>
</tbody></table>
<table><tbody>
<tr colspan=”2”>
<td><b>{$current.label()}</b></td>
</tr>
<netui:repeater id=”$i1” source=”$current.*” iterator=”$i”>
<tr>
<td>{$current.name()}</td>
<td>{$i}</td>
</tr>
</netui:repeater>
</tbody></table>
CRM例をナビゲーションする自動ブラウザの出力を以下に示す。
ブラウザのバックボタンは、ユーザが詳細なテンプレートからナビゲータテンプレートへナビゲーションして戻すことができるようにする。
このセクションは、サンプルCRMアプリケーションの全てのアプリケーションコンポーネントを詳述する。
データモデル
上述したように、図5は、CRMアプリケーションに関するエンティティ関係ダイアグラム(ERD)を示す。
ルートノードは、アカウントノードを含み、そしてアカウントkeyrefを定義する。各アカウントノードは、コンタクト、事象、ノート及びタスクノードを含んでもよく、そしてそれに対応するkeyrefを定義する。同様に、各コンタクトノードは、事象、ノート及びタスクノードを含んでもよい。又、アカウントノードは、サブアカウントを含んでもよく、そしてsubAccount keyrefを定義する。
スキーマ及びkeyref定義
次のセクションは、5つのアプリケーションスキーマを詳述し、これらは、全て、/schema/crm.xsdファイルにおいて定義される。
<?xml version=”1.0”?>
<xsd:schema targetNamespace=”http://example.com/”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:mas=”urn:bea.com”
xmlns=”http://example.com/”>
account nodetypeは、次のスキーマにより定義される。
<xsd:complexType name=”accountType”>
<xsd:all>
<xsd:element name=”name” type=”xsd:string”/>
<xsd:element name=”type” type=”accountTypeEnum”/>
</xsd:all>
<xsd:attribute name=”id” type=”xsd:string” mas:type=”pkey”/>
<xsd:attribute name=”timestamp” type=”xsd:string” mas:type=”seq”/>
<xsd:attribute name=”ownerId” type=”xsd:string”/>
<xsd:attribute name=”parentAccountId” type=”xsd:string”/>
</xsd:complexType>
<xsd:simpleType name=”accountTypeEnum”>
<xsd:restriction base=”xsd:string”>
<xsd:enumeration value=”Direct”/>
<xsd:enumeration value=”Web”/>
<xsd:enumeration value=”Channel”/>
<xsd:enumeration value=”Partner”/>
</xsd:restriction>
</xsd:simpleType>
次のセクションは、第1の宣言されたkeyrefを示す/conduit/crm.jsxファイルの最上部を示す。アプリケーションは、app namespaceにおいて宣言されることに注意されたい。
<?xml version=”1.0”?>
<graphMeta xmlns=”run:bea.com”
xmlns:mas=”run:bea.com”
xmlns:app=”http://example.com/”>
<keyref name=”account” sourceType=”mas:root” targetType=”app:account”>
...
</keyref>
...
</graphMeta>
<keyref name=”accounts” sourceType=”mas:root” targetType=”app:account”/>
次のkeyref定義は、account nodetypeに関連している(即ち、その全てがapp:accountをsourceType属性として宣言している)。アカウントは、サブアカウント(subAccounts)と、コンタクト、ノート、事象、タスク及びクオテ要求に対するノードの組とを含む。
<keyref name=”subAccounts” sourceType=”app:account” targetType=”app:account”/>
<keyref name=”contacts” sourceType=”app:account” targetType=”app:contact”/>
<keyref name=”notes” sourceType=”app:account” targetType=”app:note”/>
<keyref name=”events” sourceType=”app:account” targetType=”app:event”/>
<keyref name=”tasks” sourceType=”app:account” targetType=”app:task”/>
<keyref name=”quotes” sourceType=”app:account” targetType=”app:quoteRequest”/>
<keyref name=”owner” sourceType=”app:account” targetType=”mas:user”
minOccurs=”1” maxOccurs=”1”/>
contact nodetypeは、次のスキーマにより定義される。
<xsd:element name=”contact” type=”contactType”>
<xsd:annotation>
<xsd:appinfo>
<mas:nodeAnnotation>
<mas:label>$node.first + ” ” + $node.last</mas:label>
</mas:nodeAnnotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name=”contactType”>
<xsd:sequence>
<xsd:element name=”salutation” type=”contactSalutationEnum”/>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”xsd:string”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name=”contactSalutationEnum”>
<xsd:restriction base=”xsd:string”>
<xsd:enumeration value=”Mr”/>
<xsd:enumeration value=”Mrs”/>
<xsd:enumeration value=”Ms”/>
<xsd:enumeration value=”Dr”/>
</xsd:restriction>
</xsd:simpleType>
次のkeyref定義は、contact nodetypeに関連する(即ち、その全ては、app:contactをsourceType属性として宣言している)。アカウントは、ノート、事象及びタスクに対するノードの組を含む。
<keyref name=”notes” sourceType=”app:contact” targetType=”app:note”/>
<keyref name=”events” sourceType=”app:contact” targetType=”app:event”/>
<keyref name=”tasks” sourceType=”app:contact” targetType=”app:task”/>
<keyref name=”owner” sourceType=”app:contact” targetType=”mas:user”
minOccurs=”1” maxOccurs=”1”/>
note nodetypeは、次のスキーマにより定義される。
<xsd:element name=”note” type=”noteType”>
<xsd:annotation>
<xsd:appinfo>
<mas:nodeAnnotation>
<mas:label>$node.title</mas:label>
</mas:nodeAnnotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name=”noteType”>
<xsd:sequence>
<xsd:element name=”title” type=”xsd:string”/>
<xsd:element name=”body” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
ノートは、keyref定義を含まない。
event nodetypeは、次のスキーマにより定義される。
<xsd:element name=”event” type=”eventType”>
<xsd:annotation>
<xsd:appinfo>
<mas:nodeAnnotation>
<mas:label>$node.title</mas:label>
</mas:nodeAnnotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name=”eventType”>
<xsd:sequence>
<xsd:element name=”title” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
<keyref name=”assigned” sourceType=”app:event” targetType=”mas:user”
minOccurs=”1” maxOccurs=”1”/>
task nodetypeは、次のスキーマにより定義される。
<xsd:element name=”task” type=”taskType”>
<xsd:annotation>
<xsd:appinfo>
<mas:nodeAnnotation>
<mas:label>$node.title</mas:label>
</mas:nodeAnnotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name=”taskType”>
<xsd:sequence>
<xsd:element name=”title” type=”xsd:string”/>
<xsd:element name=”status” type=”taskStatusEnum”/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name=”taskStatusEnum”>
<xsd:restriction base=”xsd:string”>
<xsd:enumeration value=”Not started”/>
<xsd:enumeration value=”In progress”/>
<xsd:enumeration value=”Completed”/>
<xsd:enumeration value=”Deferred”/>
</xsd:restriction>
</xsd:simpleType>
<keyref name=”assigned” sourceType=”app:task” targetType=”mas:user”
minOccurs=”1” maxOccurs=”1”/>
QuoteRequest nodetypeは、次のスキーマにより定義される。
<?xml version=”1.0”?>
<xsd:schema targetNamespace=”http://example.com/”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:mas=”run:bea.com”
xmlns=”http://example.com/”>
<xsd:element name=”quoteRequest” type=”quoteRequestType”/>
<xsd:complexType name=”quoteRequestType”>
<xsd:sequence>
<xsd:element name=”prodId” type=”xsd:string”/>
<xsd:element name=”qty” type=”xsd:integer”/>
<xsd:element name=”response” minOccurs=”0” type=”quoteRequestResponseType”/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”quoteRequestResponseType”>
<xsd:sequence>
<xsd:element name=”price” type=”xsd:double”/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
次のセクションは、クライアントプログラミングモデルによりアクセスされる仮想データグラフに対するアプリケーションデータを示す。
フレームワークは、アプリケーションデータについて次のXMLスキーマ定義を発生する。
<?xml version=”1.0”?>
<xsd:schema targetNamespace=”http://example.com/”
elementFormDefault=”qualified” attributeFormDefault=”unqualified”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:mas=”run:bea.com”
xmlns=”http://example.com/”>
<xsd:element name=”graph”>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref=”root” minOccurs=”1” maxOccurs=”1”>
<xsd:element ref=”account” maxOccurs=”unbounded”>
<xsd:element ref=”contact” maxOccurs=”unbounded”>
<xsd:element ref=”note” maxOccurs=”unbounded”>
<xsd:element ref=”event” maxOccurs=”unbounded”>
<xsd:element ref=”task” maxOccurs=”unbounded”>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
</xsd:schema>
次のタイプ定義は、アプリケーションスキーマ及びkeyref定義から発生される。
<xsd:element name=”account”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”name” type=”xsd:string”/>
<xsd:element name=”type” type=”accountType”/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name=”contact”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”salutation” type=”contactSalutationEnum”/>
<xsd:element name=”first” type=”xsd:string”/>
<xsd:element name=”last” type=”addressType”/>
<xsd:element name=”email” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
<xsd:element name=”note”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”title” type=”xsd:string”/>
<xsd:element name=”body” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name=”event”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”title” type=”xsd:string”/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name=”task”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”title” type=”xsd:string”/>
<xsd:element name=”status” type=”taskStatusEnum”/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
システムは、3人のユーザ、”alex”、”bob”及び”carol”を有する(これらは、仮想グラフに示されないシステムオブジェクトである)。
<graph>
<root accounts=”a1 a2”/>
<account id=”a1” owner=”bob” contacts=”c1 c2” notes=”n1” events=”e1” tasks=”t1”>
<name>Acme</name>
<type>Direct</type>
</account>
<account id=”a2” owner=”bob” contacts=”c3”>
<name>Bancroft</name>
<type>Web</type>
</account>
<contact id=”c1” owner=”bob” events=”e2” tasks=”t2”>
<salutation>Mr</salutation>
<first>Roger</first>
<last>Reed</last>
<email>roger@acme.com</email>
</contact>
<contact id=”c2” owner=”bob” notes=”n2”>
<salutation>Ms</salutation>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>
<contact id=”c2” owner=”bob” notes=”n2”>
<salutation>Ms</salutation>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>
<note id=”n1”>
<title>ROI information</title>
<body>Attached document details ROI for product</body>
</note>
<note id=”n2”>
<title>Customer requirements</title>
<body>Attached document presents customer's current and anticipated needs</body>
</note>
<event id=”e1” assigned=”fred”>
<title>Sales meeting</title>
</event>
<event id=”e2” assigned=”fred”>
<title>Product demonstration</title>
</event>
<task id=”t1” assigned=”fred”>
<title>Prepare RFP for sales call</title>
<status>Not started</status>
</task>
<task id=”t2” assigned=”fred”>
<title>Send white paper to customer</title>
<status>Completed</status>
</task>
</graph>
次のセクションは、幾つかのSPath表現と、上述したサンプルデータに基づいて予想される値とを示す。
次の表現は、account keyrefに対するnodeset(ノードのリスト)を返送する。
$root.@@accounts.*
<account id=”a1” owner=”bob” contacts=”c1 c2” notes=”n1” events=”e1” tasks=”t1”>
<name>Acme</name>
<type>Direct</type>
</account>
<account id=”a2” owner=”bob” contacts=”c3”>
<name>Bancroft</name>
<type>Web</type>
</account>
$root.@@accounts.*.name
Acme
Bancroft
$root.@@accounts.*.where(name == ”Acme”).@@contacts.*
<contact id=”c1” owner=”bob” events=”e2” tasks=”t2”>
<salutation>Mr</salutation>
<first>Roger</first>
<last>Reed</last>
<email>roger@acme.com</email>
</contact>
<contact id=”c2” owner=”bob” notes=”n2”>
<salutation>Ms</salutation>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>
var $contactX = $root.@@accounts.*.@@contacts where(email == ”sarah@acme.com”)
<contact id=”c2” owner=”bob” events=”e2” tasks=”t2”>
<salutation>Ms</salutation>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>
$contactX.salutation = ”Mrs”
<contact id=”c2” owner=”bob” events=”e2” tasks=”t2”>
<salutation>Mrs</salutation>
<first>Sarah</first>
<last>Smith</last>
<email>sarah@acme.com</email>
</contact>
$accountX.@@contacts.create(
<contact ownerId=”$globalApp.user”>
<salutation>Dr</salutation>
<first>David</first>
<last>Daniels</last>
<email>david@acme.com</email>
</contact>
);
var $newTask = <task>
<title>Perpare RFP</title>
<status>Not started</status>
</task>
$contactX.@@tasks.create($newTask);
$newTask.@@assigned = $root.@@users.*.where(.username == ”fred”);
このセクションは、例示的CRMウェブサービスに対するWSDL(ワークショップにより発生された)の部分を示す。
<?xml version=”1.0” encoding=”utf-8”?>
<definitions xmlns=”http://schemas.xmlsoap.org/wsdl/”
xmlns:conv=”http://www.openuri.org/2002/04/soap/conversation/”
xmlns:cw=”http://www.openuri.org/2002/04/wsdl/conversation/”
xmlns:http=”http://schemas.xmlsoap.org/wsdl/http/”
xmlns:jms=”http://www.openuri.org/2002/04/wsdl/jms/”
xmlns:mime=”http://schemas.xmlsoap.org/wsdl/mime/”
xmlns:s=”http://www.w3.org/2001/XMLSchema”
xmlns:s0=”http://www.openuri.org/”
xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/”
xmlns:soapenc=”http://schemas.xmlsoap.org/soap/encoding/”
targetNamespace=”http://www.openuri.org/”>
...
WSDLは、2種類のタイプ定義、即ちメッセージパラメータに対する入力及び出力タイプ定義と、フィールドタイプ定義(個々の複雑なタイプに対する)とを含む。
<types>セクションは、オペレーション入力及び出力タイプと、オペレーションパラメータとして通された複雑なエレメントとに対するスキーマ定義を含む。
次のタイプ定義は、getAccountsByUserウェブサービスオペレーションに対する入力(getAccountsByUser)及び出力(getAccountsByUserResponse)メッセージタイプに関する。
<types>
<s:schema xmlns:s=”http://www.w3.org/2001/XMLSchema”
mlns:ope=”http://www.openuri.org/” elementFormDefault=”qualified”
trgetNamespace=”http://www.openuri.org/”>
<s:element name=”getAccountsByUser”>
<s:complexType>
<s:sequence>
<s:element name=”userId” type=”s:string” minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name=”getAccountsByUserResponse”>
<s:complexType>
<s:sequence>
<s:element name=”getAccountsByUserResult” type=”ope:ArrayOfAccount”
minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name=”ArrayOfAccount”>
<s:sequence>
<s:element name=”Account” type=”ope:Account” nillable=”true”
minOccurs=”0” maxOccurs=”unbounded”/>
</s:sequence>
</s:complexType>
<s:element name=”Account” nillable=”true” type=”ope:Account”/>
<s:complexType name=”Account”>
<s:sequence>
<s:element name=”id” type=”s:string”/>
<s:element name=”timestamp” type=”s:string”/>
<s:element name=”name” type=”s:string” minOccurs=”0”/>
<s:element name=”type” type=”s:string” minOccurs=”0”/>
<s:element name=”ownerId” type=”s:string” minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:schema>
<s:element name=”getContactsByAccount”>
<s:complexType>
<s:sequence>
<s:element name=”accountId” type=”s:string” minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name=”getContactsByAccountResponse”>
<s:complexType>
<s:sequence>
<s:element name=”getContactsByAccountResult” type=”ope:ArrayOfContact”
minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name=”addContactToAccount”>
<s:complexType>
<s:sequence>
<s:element name=”accountId” type=”s:string” minOccurs=”0”/>
<s:element name=”contact” type=”ope:Contact” minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name=”addContactToAccountResponse”>
<s:complexType>
<s:sequence>
<s:element name=”addContactToAccountResult” type=”s:string”
minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name=”ArrayOfContact”>
<s:sequence>
<s:element name=”Contact” type=”ope:Contact” nillable=”true”
minOccurs=”0” maxOccurs=”unbounded”/>
</s:sequence>
</s:complexType>
<s:element name=”Contact” nillable=”true” type=”ope:Contact”/>
<s:complexType name=”Contact”>
<s:sequence>
<s:element name=”id” type=”s:string”/>
<s:element name=”timestamp” type=”s:string”/>
<s:element name=”first” type=”s:string” minOccurs=”0”/>
<s:element name=”last” type=”s:string” minOccurs=”0”/>
<s:element name=”email” type=”s:string” minOccurs=”0”/>
</s:sequence>
</s:complexType>
</s:schema>
</types>
各ウェブサービスオペレーションは、入力及び出力のタイプを定義する一対のメッセージを定義する。
<message name=”getAccountsByUserSoapIn”>
<part name=”parameters” element=”s0:getAccountsByUser”/>
</message>
<message name=”getAccountsByUserSoapOut”>
<part name=”parameters” element=”s0:getAccountsByUserResponse”/>
</message>
コンジットは、portType定義と構造的に同様であり、portTypeオペレーションは、コンジットオペレーションへマップされ、入力及び出力エレメントは、transformOut及びtransformInのXQuery宣言に対応する。
<portType name=”CRMSoap”>
<operation name=”getAccountsByUser”>
<input message=”s0:getAccountsByUserSoapIn”/>
<output message=”s0:getAccountsByUserSoapOut”/>
</operation>
...
</portType>
<binding name=”CRMSoap” type=”s0:CRMSoap”>
<soap:binding transport=”http://schemas.xmlsoap.org/soap/http” style=”document”/>
<operation name=”getAccountsByUser”>
<soap:operation soapAction=”http://www.openuri.org/getAccountsByUser”
style=”document”/>
<input>
<soap:body use=”literal”/>
</input>
<output>
<soap:body use=”literal”/>
</output>
</operation>
...
</binding>
<service name=”CRM”>
<port name=”CRMSoap” binding=”s0:CRMSoap”>
<soap:address location=”http://BISHAMON:7001/CRMWeb/CRM.jws”/>
</port>
</service>
次のコンジットファイルは、SalesForce.comウェブサービスと接続するコンジットの一部分を実施する。
/**
* @mas:stateful shared=”false”
* @common:xmlns namespace=”http://schemas.xmlsoap.org/soap/envelope/” prefix=”soap”
* @common:xmlns namespace=”urn:partner.soap.sforce.com” prefix=”sfdc”
* @common:xmlns namespace=”http://example.com/” prefix=”app”
*/
/**
* @common:control
* @jc:location http-url=”http://enterprise.soap.sforce.com/”
*/
ws = new WebServiceControl();
// session object returned from web service
var sessionId = null;
// create and send login message and process results
function login() {
var body =
<login>
<username>{$user.username}</username>
<password>{$user.password}</password>
</login>;
var response = ws.invoke(body);
// set session id
sessionId = string(response.body.sfdc:result.sfdc:sessionId);
// set URL for subsequent calls (from this conduit)
ws.endPoint = string(response.body.sfdc:result.sfdc:serverUrl);
}
// create conversational header
function createHeader() {
if (sessionId == null) {
login();
}
return
<SessionHeader>
<sessiondId>{sessionId}</sessiondId>
</SessionHeader>;
}
/**
* select contacts for an account: $account.@@contacts.*
* @mas:operation type=”select” keyref=”app:contactAccountRef” inverse=”true”
* @mas:transform type=”request” function=”selectContacts_request”
* @mas:transform type=”response” function=”selectContacts_response”
*/
function selectContacts($msg, $source) {
$msg.header += createHeader();
return ws.invoke($msg);
}
/**
* @mas:namespace target=”sfdc”
* @mas:field xpath=”@id”
* @language:body type=”xquery”
*/
function selectContacts_request($source) {
<query>
<queryString>
SELECT * FROM Contact
WHERE AccountId = ”{string($source/@id)}”
</queryString>
</query>
}
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function selectContacts_response($response) {
for $i in $response/sfdc:queryResponse/sfdc:result/sfdc:records
return
<contact id=”{string($i/sfdc:Id)}” accountId=”{string($i/sfdc:AccountId)}”>
<modified>{string($i/sfdc:SystemModstamp)}</modified>
<fist>{string($i/sfdc:FistName)}</first>
<last>{string($i/sfdc:LastName)}</last>
<email>{string($i/sfdc:Email)}</email>
</contact>
}
/**
* insert contact: $root.create(<contact>...</contact>);
* @mas:operation type=”insert” node=”app:contact”
* @mas:transform type=”request” function=”insertContact_request”
* @mas:transform type=”response” function=”insertContact_response”
*/
function insertContact($msg, $node) {
$msg.header += createHeader();
var response = ws.invoke($msg);
var id = response.sfdc:createResponse.sfdc:result.sfdc:Id;
// retrieve sequence number
var $msg2 = createMessage(
<query>
<queryString>
SELECT SystemModstamp FROM Contact
WHERE Id = ”{id}”
</queryString>
</query>
);
$msg2.header += createHeader();
var response2 = ws.invoke($msg2);
// return both responses
response.body += response2.body.sfdc:queryResponse;
return response;
}
/**
* @mas:namespace target=”sfdc”
* @language:body type=”xquery”
*/
function insertContact_request($node) {
<create>
<sObjects xsi:type=”Contact”>
<AccountId>{string($node/app:@accountId})</AccountId>
<FirstName>{string($node/app:first})</FistName>
<LastName>{string($node/app:last})</LastName>
<Email>{string($node/app:email)}</Email>
</sObjects>
</create>
}
/**
* @mas:namespace target=”app”
* @language:body type=”xquery”
*/
function insertContact_response($response) {
<contact id=”{string($response/sfdc:createResponse/sfdc:result/sfdc:Id)}”>
<modified>
{string($response/sfdc:queryResponse/sfdc:records/sfdc:SystemModstamp)}
</modified>
</contact>
}
サービスバスは、多数の位置からの情報を得るプロキシーである。サービスバスは、
−エンベローププロトコル、トランスポートプロトコル、セキュリティ機構、ペイロードコンテンツ、一方向及び要求/応答パラダイム、同期及び非同期通信、並びにポイント対ポイント及びpub/subのエリアにおいて送信者が送信しそして受信者が期待するメッセージ間のギャップを橋絡し、
−多行先パブリッシュ、コンテンツベースのルーティング、認証及び許可、並びに証明書マッピングのようなタスクを実行するために媒介物に付加的な計算能力を設け、
−メトリック収集及び表示、警告表示、追跡事象収集及び使用、メッセージアーカイブ及びSLAマネージメントと共に媒介物にモニタリング能力を設ける。
媒介物(プロキシーサービス)及び媒介物により呼び出される外部サービスは、両方とも、サービスとしてモデリングすることができる。
−トランスポートアドレス及び関連コンフィギュレーションを各々もつポーと称される(エンドポイントとも称される)1組の具体的なインターフェイス。1組のポートは、サービスに対する負荷バランス及びフェイルオーバー代替物を構成し、そして特性が同一である。
−単一の任意の抽象的インターフェイス(類似は、javaインターフェイス)であって、オペレーション(類似は、パラメータを伴うjavaインターフェイスのメソッド)によりおそらくブレークダウンされたインターフェイスにおいてメッセージ部分の構造を定義したもの。
−具体的なメッセージに対する抽象的インターフェイスのメッセージ部分のパッケージングを定義する単一のバインディング、及びトランスポートに対するそのメッセージのバインディング。
−WSセキュリティ(WSS)及びWS信頼性メッセージング(WS−RM)に対するポリシー、許可ポリシー、及びバインディングレイヤー(ロギングのような)により透過的に実行する必要のあるアクション。
サービスは、そのインターフェイスにおいてメッセージに適用するセキュリティポリシーを定義することができる。これは、サービスレベル(全てのメッセージに適用する)において指定することもできるし、又はサービスのオペレーションに対して個々にメッセージにおいて指定することもできる。
−変換ステージは、構造をネスト状にすべき場合に、コンテクストに影響する実行されるべき変換を選択するのを許す。ウェブサービスコールアウト又はDBルックアップは、Xquery又はXSLT変換に対する代替物で、出力コンテクスト変数をセットするためのものである。
−ルーティングステージ(要求パイプラインにおいてのみ許された)は、構造及びケース構造を合成(及びネスト状に)すべき場合に、メッセージをルーティングする単一エンドポイント及びオペレーションを定義するのを許す。メッセージを各エンドポイントへパブリッシュする前に、コンテクスト変数に影響を及ぼす1組の変換を定義することができる。ウェブサービスコールアウト又はDBルックアップは、Xquery又はXSLT変換に対する代替物で、コンテクスト変数をセットすることができる。
−WSセキュリティ処理及び許可は、バインディングレイヤーにおいて透過的に実行される。
−アーカイブステージは、経歴及び記録保持の目的でメッセージをアーカイブに書き込む。
−ロギングステージは、デバッギングの目的で選択されたコンテクストをシステムログへロギングするのを許す。
−検証ステージは、MFLスキーマのXMLに対して文書を検証する。
−カスタムステージは、ユーザが、ステージSDKを使用してステージを実施する状態でそれ自身のアクションを定義するのを許す。
あるステージからのウェブサービスコールアウトは、バインディングレイヤー及びそれに続くトランスポートレイヤーを通して進む。コールアウト応答は、逆の経路をたどる。
ユーザは、人間、組織又はアプリケーションのいずれでもよいセキュリティプリンシパルである。ユーザは、UIインターフェイス(コンソールユーザ)、又はメッセージングインターフェイス(サービス消費者又はプロバイダーとしてモデリングされたユーザ)のいずれを呼び出すこともできる。
Claims (21)
- 随時接続サーバーデバイスであって、
前記随時接続サーバーデバイス上に記憶されている一組のデータノードを、前記サーバーデバイスによって提供されたアプリケーションに関してモバイルクライアントデバイス上に記憶されたデータノードと同期させる同期ユニットであって、前記アプリケーションが、前記データノードが前記モバイルクライアントデバイスによって要求される前に、前記モバイルクライアントデバイスによる前記データノードの予想使用を指示する随時接続データモデルを使用するような同期ユニットと、
前記随時接続データモデルにより定義されたデータノードと、前記サーバーデバイス及び前記モバイルクライアントデバイスに対する外部システムからのデータとの間で変換を行うために使用される、前記データノードに関連する一組のコンジットを含むコンジットマネージャーと、
を備え、
前記データノードは、それぞれのデータノードが前記サーバーデバイスと同期したかどうかを示す同期状態に関連し、前記同期状態は、前記サーバーデバイス上の前記データノードを前記モバイルクライアントデバイス上の前記データノードに同期させるために、前記サーバーデバイスと前記モバイルクライアントデバイスとの間をバックグラウンドプロセスによって伝送され、それによって、前記モバイルクライアントデバイスが前記サーバーから切断されている期間の間、前記データノード上で実行された更新動作が、前記データノードに関連する前記同期状態を使用することによって接続が再確立されたときに、前記サーバーデバイス上に反映されるものであり、
前記コンジットマネージャーは、前記サーバーデバイス上のデータノードと前記外部システムに含まれるデータとの間の同期の際に、データ変換を行ってデータを整合させるために、同期状態の前記伝送の間に少なくとも1つのコンジットを呼び出す、ことを特徴とする随時接続サーバーデバイス。 - 前記随時接続サーバーデバイスは、前記随時接続データモデルのメタデータにより指示されたキャッシュにデータノードをキャッシュ記憶する、請求項1に記載の随時接続サーバーデバイス。
- 前記コンジットマネージャーは、前記随時接続データモデルにより定義されたデータと、特定のウェブサービスに対する要求及び応答との間の変換を定義するコンジットを使用する、請求項1に記載の随時接続サーバーデバイス。
- 適応ユーザインターフェイスサーバーを更に備え、前記モバイルクライアントデバイスは、前記データノード及び前記随時接続データモデルを使用して前記適応ユーザインターフェイスサーバーにより構成された前記随時接続サーバーデバイスからのHTMLページを受け取る、請求項1に記載の随時接続サーバーデバイス。
- 前記モバイルクライアントデバイスには、前記データノード及び前記随時接続データモデルが転送されて、クライアントに表示を発生する、請求項1に記載の随時接続サーバーデバイス。
- 前記モバイルクライアントデバイスは、前記随時接続サーバーデバイスにコンタクトせずに、前記データノード及び前記随時接続データモデルを使用してアプリケーションを実行できる、請求項5に記載の随時接続サーバーデバイス。
- サーバー上にキャッシュ記憶されたデータノードを、随時接続データモデルを使用するアプリケーションに関してモバイルクライアント上に記憶されたデータノードと同期させるステップであって、前記随時接続データモデルは、前記データノードが前記モバイルクライアントデバイスによって要求される前に、前記データノードの予想使用を指示するステップと、
外部システムからのデータと、前記随時接続データモデルにより定義されたデータノードとの間で、前記データノードに関連する一組のコンジットを使用することによって変換を行うステップと、を備え、前記データノードは、それぞれのデータノードが前記サーバーと同期したかどうかを示す同期状態に関連し、前記同期状態は、前記サーバー上の前記データノードを前記モバイルクライアント上の前記データノードに同期させるために、前記サーバーと前記モバイルクライアントとの間をバックグラウンドプロセスによって伝送され、それによって、前記モバイルクライアントが前記サーバーから切断されている期間の間、前記データノード上で実行された更新動作が、前記データノードに関連する前記同期状態を使用することによって接続が再確立されたときに、前記サーバー上に反映されるものであり、
少なくとも一つの前記コンジットは、前記サーバー上のデータノードと前記外部システムに含まれるデータとの間の同期の際に、データ変換を行ってデータを整合させるために、同期状態の前記伝送の間に呼び出される、ことを特徴とする方法。 - 前記サーバーは、前記随時接続データモデルのメタデータにより指示されたキャッシュに前記データノードをキャッシュ記憶する、請求項7に記載の方法。
- 前記変換は、前記随時接続データモデルにより定義されたデータと、特定のウェブサービスに対する要求及び応答との間の変換を定義するコンジットを使用する、請求項7に記載の方法。
- 前記クライアントには、前記データノード及び前記随時接続データモデルの両方が転送されて、クライアントに表示を発生する、請求項7に記載の方法。
- 随時接続データモデルを記憶するためのメモリと、
前記随時接続データモデルにより定義されるデータノードを記憶するためのキャッシュであって、サーバーが、前記随時接続データモデルのメタデータにより指示されたキャッシュにデータノードをキャッシュ記憶し、前記随時接続データモデルは、サーバー上に記憶されている前記データノードを、前記サーバーによって提供されたアプリケーションに関してモバイルクライアント上に記憶されたデータノードと同期させるために使用され、前記アプリケーションは前記随時接続データモデルを使用し、前記随時接続データモデルは、前記データノードが前記モバイルクライアントによって要求される前に、前記モバイルクライアントによる前記データノードの予想使用を指示するキャッシュと、
前記随時接続データモデルによって定義される前記データノードと前記外部システムに含まれるデータとの間の同期の際に、データ変換を行ってデータを整合させる、前記データノードに関連する一組のコンジットを記憶するメモリーと、を含み、
前記データノードは、それぞれのデータノードが前記サーバーと同期したかどうかを示す同期状態に関連し、前記同期状態は、前記サーバー上の前記データノードを前記モバイルクライアント上の前記データノードに同期させるために、前記サーバーと前記モバイルクライアントとの間をバックグラウンドプロセスによって伝送され、それによって、前記モバイルクライアントが前記サーバーから切断されている期間の間、前記データノード上で実行された更新動作が、前記データノードに関連する前記同期状態を使用することによって接続が再確立されたときに、前記サーバー上に反映されるものであり、
少なくとも一つの前記コンジットは、前記サーバー上のデータノードと前記外部システムに含まれるデータとの間の同期の際に、データ変換を行ってデータを整合させるために、同期状態の前記伝送の間に呼び出される、ことを特徴とするシステム。 - 前記外部システムと、前記随時接続データモデルにより定義された前記データノードとの間でデータを変換するように構成される、請求項11に記載のシステム。
- 前記データノードはXMLを含む、請求項11に記載のシステム。
- 前記随時接続データモデルにより定義されたデータと、特定のウェブサービスに対する要求及び応答との間の変換を定義するコンジットを使用するように構成されたコンジットマネージャーを更に備えた、請求項11に記載のシステム。
- 適応ユーザインターフェイスサーバーを更に備え、少なくとも1つの前記モバイルクライアントは、前記データノード及び前記随時接続データモデルを使用して前記適応ユーザインターフェイスサーバーにより構成された前記サーバーからのHTMLページを受け取る、請求項11に記載のシステム。
- 前記モバイルクライアントには、前記データノード及び前記随時接続データモデルが転送されて、前記モバイルクライアントに表示を発生する、請求項11に記載のシステム。
- 前記モバイルクライアントは、前記サーバーにコンタクトせずに、前記データノード及び前記随時接続データモデルの両方を使用してアプリケーションを実行できる、請求項16に記載のシステム。
- 前記サーバと前記モバイルクライアントとの間で通過させられる前記同期状態は、
前記データノードがローカルで生成又は変更されたかという指示、
前記データノードがローカルで生成又は変更されそしてサーバーとの同期の準備ができたかという指示、
前記データノードが保留中のサーバー同期を有するかという指示
前記データノードが前記サーバーと同期させられたかという指示、
同期が前記サーバーによって拒絶されたかという指示、及び
ローカルの変更とサーバーの更新との間に競合があるかという指示、
という指示から構成される、請求項1に記載の随時接続サーバーデバイス。 - 同期の要求が前記モバイルクライアントデバイスによって受信され、前記モバイルクライアントデバイス上のページ上に現在表示されているデータが、ページデータバインディングを再計算することによってリフレッシュされて、前記ページが、現在ユーザ入力、脱字記号又は焦点を維持したまま増分的に再表示される、請求項1に記載のサーバーデバイス。
- 前記サーバーデバイスは、前記モバイルクライアントデバイスから同期要求を受信し、前記サーバーが前記要求に関連する前記データをキャッシュ記憶していた場合は前記サーバーデバイスは直ちに応答し、そうではなく、前記サーバー上にキャッシュ記憶された前記データが古い場合は前記コンジットマネージャーは更新されたデータを配送するために1つ以上の前記コンジットを呼び出す、請求項1に記載のサーバーデバイス。
- 前記モバイルクライアントデバイス上のユーザーインターフェース動作は、前記モバイルクライアントデバイスと前記サーバーデバイスの間の接続性に関して非同期で実行され、前記同期状態を通過する同期要求が前記モバイルクライアントデバイス上のブラウザに関して非同期で実行される、請求項1に記載のサーバーデバイス。
Applications Claiming Priority (3)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
US57307704P | 2004-05-20 | 2004-05-20 | |
US11/122,294 US7650432B2 (en) | 2004-05-20 | 2005-05-04 | Occasionally-connected application server |
PCT/US2005/017822 WO2005114489A2 (en) | 2004-05-20 | 2005-05-20 | Occasionally-connected application server |
Publications (2)
Publication Number | Publication Date |
---|---|
JP2007524933A JP2007524933A (ja) | 2007-08-30 |
JP4551899B2 true JP4551899B2 (ja) | 2010-09-29 |
Family
ID=35429049
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
JP2006542905A Active JP4551899B2 (ja) | 2004-05-20 | 2005-05-20 | 随時接続アプリケーションサーバー |
Country Status (5)
Country | Link |
---|---|
US (1) | US7650432B2 (ja) |
EP (1) | EP1754175A4 (ja) |
JP (1) | JP4551899B2 (ja) |
AU (1) | AU2005246392B2 (ja) |
WO (1) | WO2005114489A2 (ja) |
Families Citing this family (134)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
WO2002059773A1 (en) * | 2000-12-04 | 2002-08-01 | Thinkshare Corp. | Modular distributed mobile data applications |
WO2003058483A1 (en) | 2002-01-08 | 2003-07-17 | Seven Networks, Inc. | Connection architecture for a mobile network |
US7606881B2 (en) * | 2002-04-25 | 2009-10-20 | Oracle International Corporation | System and method for synchronization of version annotated objects |
US7076567B1 (en) * | 2002-04-25 | 2006-07-11 | Oracle International Corporation | Simplified application object data synchronization for optimized data storage |
US7787489B2 (en) * | 2002-10-07 | 2010-08-31 | Oracle International Corporation | Mobile data distribution |
US7908286B2 (en) * | 2004-12-08 | 2011-03-15 | Oracle International Corporation | Techniques for providing XQuery access using web services |
US8438633B1 (en) * | 2005-04-21 | 2013-05-07 | Seven Networks, Inc. | Flexible real-time inbox access |
US8464317B2 (en) * | 2005-05-06 | 2013-06-11 | International Business Machines Corporation | Method and system for creating a protected object namespace from a WSDL resource description |
CN1869932A (zh) * | 2005-05-24 | 2006-11-29 | 中国银联股份有限公司 | 实现数据升级的计算机处理系统以及数据升级方法 |
US7970386B2 (en) | 2005-06-03 | 2011-06-28 | Good Technology, Inc. | System and method for monitoring and maintaining a wireless device |
WO2006136660A1 (en) | 2005-06-21 | 2006-12-28 | Seven Networks International Oy | Maintaining an ip connection in a mobile network |
US7877420B2 (en) * | 2005-06-24 | 2011-01-25 | Microsoft Corporation | Methods and systems for incorporating meta-data in document content |
US8171394B2 (en) * | 2005-06-24 | 2012-05-01 | Microsoft Corporation | Methods and systems for providing a customized user interface for viewing and editing meta-data |
US20070016577A1 (en) * | 2005-07-13 | 2007-01-18 | Rivergy, Inc. | System for building a website |
US7912871B2 (en) * | 2005-07-27 | 2011-03-22 | Technion Research And Development Foundation Ltd. | Incremental validation of key and keyref constraints |
US7668836B2 (en) * | 2005-09-02 | 2010-02-23 | International Business Machines Corporation | IMS SOAP gateway deployment utility |
US8972423B2 (en) * | 2006-09-26 | 2015-03-03 | Siemens Product Lifecycle Management Software Inc. | Opaque mechanism for web service interoperability |
US20070112791A1 (en) * | 2005-11-09 | 2007-05-17 | Harvey Richard H | Method and system for providing enhanced read performance for a supplemental directory |
US8321486B2 (en) * | 2005-11-09 | 2012-11-27 | Ca, Inc. | Method and system for configuring a supplemental directory |
US8326899B2 (en) * | 2005-11-09 | 2012-12-04 | Ca, Inc. | Method and system for improving write performance in a supplemental directory |
US8458176B2 (en) * | 2005-11-09 | 2013-06-04 | Ca, Inc. | Method and system for providing a directory overlay |
US20070112812A1 (en) * | 2005-11-09 | 2007-05-17 | Harvey Richard H | System and method for writing data to a directory |
US20070171923A1 (en) | 2005-12-01 | 2007-07-26 | Firestar Software, Inc. | System and method for exchanging information among exchange applications |
US7788223B2 (en) * | 2005-12-05 | 2010-08-31 | Microsoft Corporation | Resource freshness and replication |
KR100717520B1 (ko) | 2005-12-06 | 2007-05-11 | 주식회사 인프라웨어 | 무선인터넷 서비스를 제공하는 이동 단말기 및 그 사용자인터페이스 방법 |
US7631017B2 (en) * | 2005-12-08 | 2009-12-08 | Motorola, Inc. | Method and system for maintaining current data for wireless devices |
US20070168535A1 (en) * | 2005-12-22 | 2007-07-19 | Ilmo Ikonen | System and method for data communication between devices |
WO2007083954A1 (en) * | 2006-01-23 | 2007-07-26 | Lg Electronics Inc. | Method for scheduling device management and terminal thereof |
US8086756B2 (en) * | 2006-01-25 | 2011-12-27 | Cisco Technology, Inc. | Methods and apparatus for web content transformation and delivery |
US7676786B2 (en) | 2006-02-02 | 2010-03-09 | Research In Motion Limited | System and method and apparatus for using UML tools for defining web service bound component applications |
US9152928B2 (en) * | 2006-06-30 | 2015-10-06 | Triplay, Inc. | Context parameters and identifiers for communication |
US20090210631A1 (en) * | 2006-09-22 | 2009-08-20 | Bea Systems, Inc. | Mobile application cache system |
US8239522B1 (en) * | 2006-11-16 | 2012-08-07 | Adobe Systems Incorporated | Dynamic variables for tracking wireless device website usage |
US8499044B2 (en) * | 2006-12-07 | 2013-07-30 | Microsoft Corporation | Formatted message processing utilizing a message map |
US7983249B2 (en) * | 2007-01-23 | 2011-07-19 | Oracle America, Inc. | Enterprise web service data to mobile device synchronization |
US7899917B2 (en) * | 2007-02-01 | 2011-03-01 | Microsoft Corporation | Synchronization framework for occasionally connected applications |
US20080234987A1 (en) * | 2007-02-23 | 2008-09-25 | Autodesk, Inc. | Amalgamation of data models across multiple applications |
US10387130B1 (en) * | 2007-02-23 | 2019-08-20 | Sugarcrm Inc. | Metadata driven distributed application behavior system and method |
US20080215664A1 (en) * | 2007-03-01 | 2008-09-04 | Microsoft Corporation | Occasionally connected edge application architecture |
US8453136B1 (en) * | 2007-03-06 | 2013-05-28 | Cadence Design Systems, Inc. | Change tracking and incremental synchronization of EDA design and technology data |
US9729843B1 (en) | 2007-03-16 | 2017-08-08 | The Mathworks, Inc. | Enriched video for a technical computing environment |
US8005812B1 (en) * | 2007-03-16 | 2011-08-23 | The Mathworks, Inc. | Collaborative modeling environment |
US20080235258A1 (en) * | 2007-03-23 | 2008-09-25 | Hyen Vui Chung | Method and Apparatus for Processing Extensible Markup Language Security Messages Using Delta Parsing Technology |
US7853669B2 (en) | 2007-05-04 | 2010-12-14 | Microsoft Corporation | Mesh-managing data across a distributed set of devices |
US8805425B2 (en) * | 2007-06-01 | 2014-08-12 | Seven Networks, Inc. | Integrated messaging |
US8819080B2 (en) * | 2007-06-13 | 2014-08-26 | The Boeing Company | System and method for collection, retrieval, and distribution of data |
KR100916244B1 (ko) * | 2007-09-03 | 2009-09-10 | 전자부품연구원 | Soap 오퍼레이션을 이용한 질의된 컨텐츠 서비스방법 |
US8112460B2 (en) * | 2007-09-28 | 2012-02-07 | Xcerion Aktiebolag | Framework for applying rules |
US8886779B2 (en) * | 2007-10-19 | 2014-11-11 | Oracle America, Inc. | Performance modeling for SOA security appliance |
US9002828B2 (en) * | 2007-12-13 | 2015-04-07 | Seven Networks, Inc. | Predictive content delivery |
EP2250791B1 (en) * | 2008-01-11 | 2016-08-10 | Telefonaktiebolaget LM Ericsson (publ) | Securing contact information |
US8862657B2 (en) | 2008-01-25 | 2014-10-14 | Seven Networks, Inc. | Policy based content service |
US20090193338A1 (en) * | 2008-01-28 | 2009-07-30 | Trevor Fiatal | Reducing network and battery consumption during content delivery and playback |
US8875306B2 (en) * | 2008-02-12 | 2014-10-28 | Oracle International Corporation | Customization restrictions for multi-layer XML customization |
US8788542B2 (en) * | 2008-02-12 | 2014-07-22 | Oracle International Corporation | Customization syntax for multi-layer XML customization |
US8966465B2 (en) * | 2008-02-12 | 2015-02-24 | Oracle International Corporation | Customization creation and update for multi-layer XML customization |
US7996444B2 (en) * | 2008-02-18 | 2011-08-09 | International Business Machines Corporation | Creation of pre-filters for more efficient X-path processing |
US7831608B2 (en) * | 2008-02-28 | 2010-11-09 | International Business Machines Corporation | Service identification in legacy source code using structured and unstructured analyses |
US20090228542A1 (en) * | 2008-03-06 | 2009-09-10 | Microsoft Corporation | Occasionally-connected support through off-line service-supplied proxies |
US9753712B2 (en) | 2008-03-20 | 2017-09-05 | Microsoft Technology Licensing, Llc | Application management within deployable object hierarchy |
US9298747B2 (en) * | 2008-03-20 | 2016-03-29 | Microsoft Technology Licensing, Llc | Deployable, consistent, and extensible computing environment platform |
US8572033B2 (en) | 2008-03-20 | 2013-10-29 | Microsoft Corporation | Computing environment configuration |
US8484174B2 (en) * | 2008-03-20 | 2013-07-09 | Microsoft Corporation | Computing environment representation |
US20090248737A1 (en) * | 2008-03-27 | 2009-10-01 | Microsoft Corporation | Computing environment representation |
US20090254822A1 (en) * | 2008-04-04 | 2009-10-08 | International Business Machines Corporation | Hi-efficiency wizard framework system and method |
US8799319B2 (en) * | 2008-09-19 | 2014-08-05 | Oracle International Corporation | System and method for meta-data driven, semi-automated generation of web services based on existing applications |
US8996658B2 (en) * | 2008-09-03 | 2015-03-31 | Oracle International Corporation | System and method for integration of browser-based thin client applications within desktop rich client architecture |
US8112470B2 (en) | 2008-09-09 | 2012-02-07 | Microsoft Corporation | Virtual javascript object notation |
US9122520B2 (en) * | 2008-09-17 | 2015-09-01 | Oracle International Corporation | Generic wait service: pausing a BPEL process |
US8909759B2 (en) | 2008-10-10 | 2014-12-09 | Seven Networks, Inc. | Bandwidth measurement |
US8490052B2 (en) * | 2008-10-14 | 2013-07-16 | Microsoft Corporation | Declarative programming model for authoring and execution control and data flow for resource oriented system |
US8438295B2 (en) * | 2008-10-14 | 2013-05-07 | Microsoft Corporation | Declarative programming model for modeling and execution of triggers for resource oriented system |
US8533666B2 (en) * | 2008-10-17 | 2013-09-10 | Microsoft Corporation | Interactive design environments to visually model, debug and execute resource oriented programs |
TWI384378B (zh) * | 2008-12-29 | 2013-02-01 | Ind Tech Res Inst | 網頁應用程式執行方法 |
US20100268784A1 (en) * | 2009-04-17 | 2010-10-21 | Marc Henness | Data synchronization system and method |
US8028070B2 (en) * | 2009-05-18 | 2011-09-27 | Microsoft Corporation | Synchronizing tasks between servers |
US9438448B2 (en) * | 2009-08-18 | 2016-09-06 | Microsoft Technology Licensing, Llc | Maintaining communication connections during temporary network disruptions |
US8768913B2 (en) * | 2009-10-21 | 2014-07-01 | Kana Software, Inc. | Multi-source searching in a data driven application |
US20110149086A1 (en) | 2009-12-23 | 2011-06-23 | Winbush Iii Amos | Camera user content synchronization with central web-based records and information sharing system |
US9244965B2 (en) | 2010-02-22 | 2016-01-26 | Thoughtwire Holdings Corp. | Method and system for sharing data between software systems |
US8595382B2 (en) * | 2010-06-07 | 2013-11-26 | Salesforce.Com, Inc. | System, method and computer program product for performing a synchronization of data |
JP5620578B2 (ja) | 2010-07-26 | 2014-11-05 | セブン ネットワークス インコーポレイテッド | 複数のアプリケーションにわたるモバイルネットワークトラフィック調整 |
US8838783B2 (en) | 2010-07-26 | 2014-09-16 | Seven Networks, Inc. | Distributed caching for resource and mobile network traffic management |
CN102457499B (zh) * | 2010-10-26 | 2015-09-16 | 腾讯科技(深圳)有限公司 | 客户端的离线工作方法和离线工作客户端 |
US8843153B2 (en) | 2010-11-01 | 2014-09-23 | Seven Networks, Inc. | Mobile traffic categorization and policy for network use optimization while preserving user experience |
WO2012060995A2 (en) | 2010-11-01 | 2012-05-10 | Michael Luna | Distributed caching in a wireless network of content delivered for a mobile application over a long-held request |
EP2636268B1 (en) | 2010-11-22 | 2019-02-27 | Seven Networks, LLC | Optimization of resource polling intervals to satisfy mobile device requests |
US9189566B2 (en) * | 2010-12-07 | 2015-11-17 | Sap Se | Facilitating extraction and discovery of enterprise services |
WO2012094675A2 (en) | 2011-01-07 | 2012-07-12 | Seven Networks, Inc. | System and method for reduction of mobile network traffic used for domain name system (dns) queries |
KR101755421B1 (ko) * | 2011-01-10 | 2017-07-10 | 삼성전자주식회사 | 클라이언트 장치를 이용한 호스트 장치의 파일 정보 시스템 편집 방법 및 시스템 |
CA2769775A1 (en) | 2011-03-01 | 2012-09-01 | Weever Apps Inc. | System, method and computer program product for generating browser-executable software program to present web page as mobile application |
US9084105B2 (en) | 2011-04-19 | 2015-07-14 | Seven Networks, Inc. | Device resources sharing for network resource conservation |
US8438474B1 (en) * | 2011-04-27 | 2013-05-07 | Google Inc. | Speculative rendering during cache revalidation |
WO2012149434A2 (en) | 2011-04-27 | 2012-11-01 | Seven Networks, Inc. | Detecting and preserving state for satisfying application requests in a distributed proxy and cache system |
EP2702827A4 (en) | 2011-04-27 | 2014-10-22 | Seven Networks Inc | MOBILE DEVICE DISCHARGING REQUESTS MOBILE APPLICATION TO REMOTE ENTITY TO KEEP MOBILE DEVICE RESOURCES AND NETWORK RESOURCES AND RELATED METHODS |
FR2976379B1 (fr) * | 2011-06-08 | 2019-04-26 | Schneider Electric Industries Sas | Systeme et procede de partage de donnees stockees dans une base de donnees |
US9578114B2 (en) | 2011-09-27 | 2017-02-21 | Microsoft Technology Licensing, Llc | External service application discovery method |
US8954942B2 (en) * | 2011-09-30 | 2015-02-10 | Oracle International Corporation | Optimizations using a BPEL compiler |
US9069844B2 (en) | 2011-11-02 | 2015-06-30 | Sap Se | Facilitating extraction and discovery of enterprise services |
US8934414B2 (en) | 2011-12-06 | 2015-01-13 | Seven Networks, Inc. | Cellular or WiFi mobile traffic optimization based on public or private network destination |
US8977755B2 (en) | 2011-12-06 | 2015-03-10 | Seven Networks, Inc. | Mobile device and method to utilize the failover mechanism for fault tolerance provided for mobile traffic management and network/device resource conservation |
EP2788889A4 (en) | 2011-12-07 | 2015-08-12 | Seven Networks Inc | FLEXIBLE AND DYNAMIC INTEGRATION SCHEMES OF A TRAFFIC MANAGEMENT SYSTEM WITH VARIOUS NETWORK OPERATORS TO REDUCE NETWORK TRAFFIC |
WO2013086447A1 (en) | 2011-12-07 | 2013-06-13 | Seven Networks, Inc. | Radio-awareness of mobile device for sending server-side control signals using a wireless network optimized transport protocol |
WO2013090212A1 (en) | 2011-12-14 | 2013-06-20 | Seven Networks, Inc. | Mobile network reporting and usage analytics system and method using aggregation of data in a distributed traffic optimization system |
US11216454B1 (en) * | 2011-12-19 | 2022-01-04 | Actian Sub Iii, Inc. | User defined functions for database query languages based on call-back functions |
RU2605047C2 (ru) * | 2012-02-09 | 2016-12-20 | Общество с ограниченной ответственностью "Колловэар" | Способ синхронизации объектов персонального информационного менеджера и внешнего сервера |
US8812695B2 (en) | 2012-04-09 | 2014-08-19 | Seven Networks, Inc. | Method and system for management of a virtual network connection without heartbeat messages |
US9177289B2 (en) | 2012-05-03 | 2015-11-03 | Sap Se | Enhancing enterprise service design knowledge using ontology-based clustering |
US8874682B2 (en) * | 2012-05-23 | 2014-10-28 | Sybase, Inc. | Composite graph cache management |
US8775631B2 (en) | 2012-07-13 | 2014-07-08 | Seven Networks, Inc. | Dynamic bandwidth adjustment for browsing or streaming activity in a wireless network based on prediction of user behavior when interacting with mobile applications |
US20140082586A1 (en) * | 2012-08-09 | 2014-03-20 | FatFractal, Inc. | Application development system and method for object models and datagraphs in client-side and server-side applications |
US9298391B2 (en) | 2012-12-19 | 2016-03-29 | Dropbox, Inc. | Application programming interfaces for data synchronization with online storage systems |
US9398090B2 (en) | 2013-01-07 | 2016-07-19 | Dropbox, Inc. | Synchronized content library |
US8874761B2 (en) | 2013-01-25 | 2014-10-28 | Seven Networks, Inc. | Signaling optimization in a wireless network for traffic utilizing proprietary and non-proprietary protocols |
KR101772781B1 (ko) * | 2013-01-30 | 2017-08-29 | 세이코 엡슨 가부시키가이샤 | Pos 제어 시스템, pos 제어 시스템의 제어 방법, 및, 제어 장치 |
JP6149416B2 (ja) * | 2013-02-07 | 2017-06-21 | 日本電気株式会社 | サービスバス装置、サービスバス装置の制御方法、メッセージ送受信システム、及びプログラム |
US9326185B2 (en) | 2013-03-11 | 2016-04-26 | Seven Networks, Llc | Mobile network congestion recognition for optimization of mobile traffic |
US9742843B2 (en) | 2013-03-14 | 2017-08-22 | Thoughtwire Holdings Corp. | Method and system for enabling data sharing between software systems |
US9614932B2 (en) | 2013-03-14 | 2017-04-04 | Microsoft Technology Licensing, Llc | Managing and implementing web application data snapshots |
US10372442B2 (en) | 2013-03-14 | 2019-08-06 | Thoughtwire Holdings Corp. | Method and system for generating a view incorporating semantically resolved data values |
US10313433B2 (en) | 2013-03-14 | 2019-06-04 | Thoughtwire Holdings Corp. | Method and system for registering software systems and data-sharing sessions |
KR20140128737A (ko) * | 2013-04-29 | 2014-11-06 | 삼성전자주식회사 | 어플리케이션 결함을 관리하기 위한 장치 및 방법 |
US9065765B2 (en) | 2013-07-22 | 2015-06-23 | Seven Networks, Inc. | Proxy server associated with a mobile carrier for enhancing mobile traffic management in a mobile network |
JP6382819B2 (ja) | 2013-08-21 | 2018-08-29 | 株式会社東芝 | データベースシステム、ノード、管理装置、プログラムおよびデータ処理方法 |
US10762276B2 (en) * | 2013-08-27 | 2020-09-01 | Paper Software LLC | Cross-references within a hierarchically structured document |
WO2015029139A1 (ja) | 2013-08-27 | 2015-03-05 | 株式会社東芝 | データベースシステム、プログラムおよびデータ処理方法 |
US10769143B1 (en) | 2014-07-31 | 2020-09-08 | Open Text Corporation | Composite index on hierarchical nodes in the hierarchical data model within case model |
US10515124B1 (en) * | 2014-07-31 | 2019-12-24 | Open Text Corporation | Placeholder case nodes and child case nodes in a case model |
US10599718B2 (en) * | 2015-10-09 | 2020-03-24 | Software Ag | Systems and/or methods for graph based declarative mapping |
US10929174B2 (en) * | 2016-12-15 | 2021-02-23 | Ecole Polytechnique Federale De Lausanne (Epfl) | Atomic object reads for in-memory rack-scale computing |
US11714811B2 (en) | 2017-09-27 | 2023-08-01 | Salesforce, Inc. | Run-time querying of multi-tenant non-relational platform objects |
US10579692B2 (en) * | 2017-09-27 | 2020-03-03 | Salesforce.Com, Inc. | Composite keys for multi-tenant non-relational platform objects |
US10579691B2 (en) | 2017-09-27 | 2020-03-03 | Salesforce.Com, Inc. | Application programming interface representation of multi-tenant non-relational platform objects |
US10579722B1 (en) * | 2018-07-25 | 2020-03-03 | Sprint Communications Company, L.P. | Structured metadata for dynamic data encapsulation |
Family Cites Families (123)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US5159592A (en) * | 1990-10-29 | 1992-10-27 | International Business Machines Corporation | Network address management for a wired network supporting wireless communication to a plurality of mobile users |
US5250789A (en) * | 1991-10-31 | 1993-10-05 | Johnsen Edward L | Shopping cart |
US5566225A (en) * | 1994-11-21 | 1996-10-15 | Lucent Technologies Inc. | Wireless data communications system for detecting a disabled condition and simulating a functioning mode in response to detection |
US5758257A (en) * | 1994-11-29 | 1998-05-26 | Herz; Frederick | System and method for scheduling broadcast of and access to video programs and other data using customer profiles |
US6571279B1 (en) * | 1997-12-05 | 2003-05-27 | Pinpoint Incorporated | Location enhanced information delivery system |
US5664110A (en) * | 1994-12-08 | 1997-09-02 | Highpoint Systems, Inc. | Remote ordering system |
US5812819A (en) * | 1995-06-05 | 1998-09-22 | Shiva Corporation | Remote access apparatus and method which allow dynamic internet protocol (IP) address management |
US5727159A (en) * | 1996-04-10 | 1998-03-10 | Kikinis; Dan | System in which a Proxy-Server translates information received from the Internet into a form/format readily usable by low power portable computers |
US6314406B1 (en) * | 1996-06-26 | 2001-11-06 | Telxon Corporation | Customer information network |
US5828832A (en) * | 1996-07-30 | 1998-10-27 | Itt Industries, Inc. | Mixed enclave operation in a computer network with multi-level network security |
US5931917A (en) * | 1996-09-26 | 1999-08-03 | Verifone, Inc. | System, method and article of manufacture for a gateway system architecture with system administration information accessible from a browser |
US6096096A (en) * | 1996-12-13 | 2000-08-01 | Silicon Graphics, Inc. | Web-site delivery |
US6477527B2 (en) * | 1997-05-09 | 2002-11-05 | International Business Machines Corporation | System, method, and program for object building in queries over object views |
US6314408B1 (en) * | 1997-07-15 | 2001-11-06 | Eroom Technology, Inc. | Method and apparatus for controlling access to a product |
US6112212A (en) * | 1997-09-15 | 2000-08-29 | The Pangea Project Llc | Systems and methods for organizing and analyzing information stored on a computer network |
US6236768B1 (en) * | 1997-10-14 | 2001-05-22 | Massachusetts Institute Of Technology | Method and apparatus for automated, context-dependent retrieval of information |
US6009410A (en) * | 1997-10-16 | 1999-12-28 | At&T Corporation | Method and system for presenting customized advertising to a user on the world wide web |
US6128661A (en) * | 1997-10-24 | 2000-10-03 | Microsoft Corporation | Integrated communications architecture on a mobile device |
US6594682B2 (en) * | 1997-10-28 | 2003-07-15 | Microsoft Corporation | Client-side system for scheduling delivery of web content and locally managing the web content |
US6065120A (en) * | 1997-12-09 | 2000-05-16 | Phone.Com, Inc. | Method and system for self-provisioning a rendezvous to ensure secure access to information in a database from multiple devices |
US6058391A (en) * | 1997-12-17 | 2000-05-02 | Mci Communications Corporation | Enhanced user view/update capability for managing data from relational tables |
US6801916B2 (en) * | 1998-04-01 | 2004-10-05 | Cyberpulse, L.L.C. | Method and system for generation of medical reports from data in a hierarchically-organized database |
US6101483A (en) * | 1998-05-29 | 2000-08-08 | Symbol Technologies, Inc. | Personal shopping system portable terminal |
US6151675A (en) * | 1998-07-23 | 2000-11-21 | Tumbleweed Software Corporation | Method and apparatus for effecting secure document format conversion |
US6925595B1 (en) * | 1998-08-05 | 2005-08-02 | Spyglass, Inc. | Method and system for content conversion of hypertext data using data mining |
US7778260B2 (en) | 1998-10-09 | 2010-08-17 | Netmotion Wireless, Inc. | Method and apparatus for providing mobile and other intermittent connectivity in a computing environment |
ATE260490T1 (de) * | 1998-11-30 | 2004-03-15 | Index Systems Inc | Intelligenter agent basierend auf gewohnheit, statistische inferenz und psychodemografische profilierung |
AU1838200A (en) * | 1998-11-30 | 2000-06-19 | Siebel Systems, Inc. | Client server system with thin client architecture |
US6177905B1 (en) * | 1998-12-08 | 2001-01-23 | Avaya Technology Corp. | Location-triggered reminder for mobile user devices |
US6212640B1 (en) * | 1999-03-25 | 2001-04-03 | Sun Microsystems, Inc. | Resources sharing on the internet via the HTTP |
US6226752B1 (en) * | 1999-05-11 | 2001-05-01 | Sun Microsystems, Inc. | Method and apparatus for authenticating users |
US6681220B1 (en) * | 1999-05-28 | 2004-01-20 | International Business Machines Corporation | Reduction and optimization of information processing systems |
US20030191832A1 (en) * | 1999-06-01 | 2003-10-09 | Ramakrishna Satyavolu | Method and apparatus for controlled establishment of a turnkey system providing a centralized data aggregation and summary capability to third party entities |
US6425022B1 (en) * | 1999-06-11 | 2002-07-23 | Oak Technology, Inc. | System for reading blocks of different sizes by maintaining buffer page pointer when word count is not greater than guardband, and reset word count thereafter |
US6477373B1 (en) * | 1999-08-10 | 2002-11-05 | Research Foundation Of State University Of New York | Method and apparatus to maintain connectivity for mobile terminals in wireless and cellular communications systems |
US6760758B1 (en) * | 1999-08-31 | 2004-07-06 | Qwest Communications International, Inc. | System and method for coordinating network access |
US7392308B2 (en) * | 1999-09-10 | 2008-06-24 | Ianywhere Solutions, Inc. | System, method, and computer program product for placement of channels on a mobile device |
US6725022B1 (en) * | 1999-09-22 | 2004-04-20 | Motorola, Inc. | Method and apparatus for enabling the selection of content on a wireless communication device |
US7020697B1 (en) | 1999-10-01 | 2006-03-28 | Accenture Llp | Architectures for netcentric computing systems |
US6578054B1 (en) | 1999-10-04 | 2003-06-10 | Microsoft Corporation | Method and system for supporting off-line mode of operation and synchronization using resource state information |
US6430624B1 (en) * | 1999-10-21 | 2002-08-06 | Air2Web, Inc. | Intelligent harvesting and navigation system and method |
US6353398B1 (en) * | 1999-10-22 | 2002-03-05 | Himanshu S. Amin | System for dynamically pushing information to a user utilizing global positioning system |
US6647001B1 (en) * | 1999-12-06 | 2003-11-11 | At&T Corp. | Persistent communication with changing environment |
US7047305B1 (en) * | 1999-12-09 | 2006-05-16 | Vidiator Enterprises Inc. | Personal broadcasting system for audio and video data using a wide area network |
WO2001067309A2 (en) * | 2000-03-03 | 2001-09-13 | Radiant Logic, Inc. | System and method for providing access to databases via directories and other hierarchical structures and interfaces |
GB2360173B (en) * | 2000-03-07 | 2004-04-07 | Hewlett Packard Co | Distributed telemetry method and system |
US6618737B2 (en) * | 2000-03-09 | 2003-09-09 | International Business Machines Corporation | Speculative caching of individual fields in a distributed object system |
US6845091B2 (en) * | 2000-03-16 | 2005-01-18 | Sri International | Mobile ad hoc extensions for the internet |
US6701522B1 (en) * | 2000-04-07 | 2004-03-02 | Danger, Inc. | Apparatus and method for portal device authentication |
WO2001080133A2 (en) * | 2000-04-17 | 2001-10-25 | Emtera Corporation | System and method for wireless purchases of goods and services |
AU2001251643A1 (en) * | 2000-04-17 | 2001-10-30 | Circadence Corporation | System and method for providing distributed database services |
WO2001086882A2 (en) * | 2000-05-05 | 2001-11-15 | @ Hand Corporation | System and method for extending an enterprise network to mobile devices |
GB0011426D0 (en) * | 2000-05-11 | 2000-06-28 | Charteris Limited | A method for transforming documents written in different XML-based languages |
US6922685B2 (en) | 2000-05-22 | 2005-07-26 | Mci, Inc. | Method and system for managing partitioned data resources |
US6438575B1 (en) * | 2000-06-07 | 2002-08-20 | Clickmarks, Inc. | System, method, and article of manufacture for wireless enablement of the world wide web using a wireless gateway |
US6990513B2 (en) * | 2000-06-22 | 2006-01-24 | Microsoft Corporation | Distributed computing services platform |
US6615216B1 (en) * | 2000-06-29 | 2003-09-02 | Microsoft Corporation | Lock free data structure maintenance |
US7099926B1 (en) * | 2000-07-06 | 2006-08-29 | International Business Machines Corporation | Object caching and update queuing technique to improve performance and resource utilization |
KR100425494B1 (ko) | 2000-08-21 | 2004-03-30 | 엘지전자 주식회사 | 웹 기반 전송장비의 관리 데이터 동기 방법 |
EP1366435A2 (en) | 2000-08-22 | 2003-12-03 | Symbian Limited | Database for use with a wireless information device |
US20020059345A1 (en) * | 2000-09-12 | 2002-05-16 | Wang Wayne W. | Method for generating transform rules for web-based markup languages |
US20020069263A1 (en) * | 2000-10-13 | 2002-06-06 | Mark Sears | Wireless java technology |
US6542740B1 (en) * | 2000-10-24 | 2003-04-01 | Litepoint, Corp. | System, method and article of manufacture for utilizing a wireless link in an interface roaming network framework |
US6865680B1 (en) * | 2000-10-31 | 2005-03-08 | Yodlee.Com, Inc. | Method and apparatus enabling automatic login for wireless internet-capable devices |
US7600014B2 (en) * | 2000-11-16 | 2009-10-06 | Symantec Corporation | Method and system for monitoring the performance of a distributed application |
US20020099829A1 (en) * | 2000-11-27 | 2002-07-25 | Richards Kenneth W. | Filter proxy system and method |
US7877518B2 (en) * | 2000-11-30 | 2011-01-25 | Access Systems Americas, Inc. | Method and apparatus for updating applications on a mobile device via device synchronization |
US7546298B2 (en) * | 2001-01-09 | 2009-06-09 | Nextair Corporation | Software, devices and methods facilitating execution of server-side applications at mobile devices |
JP3768406B2 (ja) | 2001-01-15 | 2006-04-19 | 株式会社エヌ・ティ・ティ・ドコモ | 移動通信網における情報配信制御方法及びシステム、及び移動通信網における通信ノードでの情報蓄積方法 |
US7017175B2 (en) | 2001-02-02 | 2006-03-21 | Opentv, Inc. | Digital television application protocol for interactive television |
US6714791B2 (en) * | 2001-02-23 | 2004-03-30 | Danger, Inc. | System, apparatus and method for location-based instant messaging |
US6668177B2 (en) * | 2001-04-26 | 2003-12-23 | Nokia Corporation | Method and apparatus for displaying prioritized icons in a mobile terminal |
US20030177175A1 (en) * | 2001-04-26 | 2003-09-18 | Worley Dale R. | Method and system for display of web pages |
US7190956B2 (en) * | 2001-05-15 | 2007-03-13 | Motorola Inc. | Instant message proxy for circuit switched mobile environment |
US7152090B2 (en) * | 2001-06-01 | 2006-12-19 | Sun Microsystems, Inc. | Metadata-aware enterprise application integration framework for application server environment |
US7003566B2 (en) | 2001-06-29 | 2006-02-21 | International Business Machines Corporation | Method and system for predictive directional data caching |
US6813641B2 (en) * | 2001-07-05 | 2004-11-02 | Sun Microsystems, Inc. | Teamware server working over HTTP/HTTPS connections |
US7117225B2 (en) * | 2001-08-13 | 2006-10-03 | Jasmin Cosic | Universal data management interface |
US7149813B2 (en) * | 2001-08-14 | 2006-12-12 | Microsoft Corporation | Method and system for synchronizing mobile devices |
GB2379296B (en) * | 2001-09-01 | 2005-05-25 | Ibm | A data storage system having a unified container layer for an active data store |
US7761535B2 (en) * | 2001-09-28 | 2010-07-20 | Siebel Systems, Inc. | Method and system for server synchronization with a computing device |
US7257649B2 (en) | 2001-09-28 | 2007-08-14 | Siebel Systems, Inc. | Method and system for transferring information during server synchronization with a computing device |
US7032033B1 (en) | 2001-11-30 | 2006-04-18 | Microsoft Corporation | Handling collisions during synchronization of data between client and server computers |
US7062756B2 (en) * | 2001-11-30 | 2006-06-13 | Sun Microsystems, Inc. | Dynamic object usage pattern learning and efficient caching |
US7640491B2 (en) * | 2001-12-05 | 2009-12-29 | Microsoft Corporation | Outputting dynamic local content on mobile devices |
US20030135556A1 (en) * | 2001-12-14 | 2003-07-17 | International Business Machines Corporation | Selection of communication strategies for message brokers or publish/subscribe communications |
US6826568B2 (en) * | 2001-12-20 | 2004-11-30 | Microsoft Corporation | Methods and system for model matching |
US7062515B1 (en) | 2001-12-28 | 2006-06-13 | Vignette Corporation | System and method for the synchronization of a file in a cache |
US7275105B2 (en) * | 2002-01-16 | 2007-09-25 | Laszlo Systems, Inc. | Enabling online and offline operation |
US7159174B2 (en) * | 2002-01-16 | 2007-01-02 | Microsoft Corporation | Data preparation for media browsing |
JP3967141B2 (ja) * | 2002-01-28 | 2007-08-29 | 富士通株式会社 | フレーム中継システムおよびフレーム中継装置 |
US9087319B2 (en) * | 2002-03-11 | 2015-07-21 | Oracle America, Inc. | System and method for designing, developing and implementing internet service provider architectures |
US20040006586A1 (en) * | 2002-04-23 | 2004-01-08 | Secure Resolutions, Inc. | Distributed server software distribution |
US7457810B2 (en) | 2002-05-10 | 2008-11-25 | International Business Machines Corporation | Querying markup language data sources using a relational query processor |
US8255548B2 (en) | 2002-06-13 | 2012-08-28 | Salesforce.Com, Inc. | Offline web services API to mirror online web services API |
US20040001476A1 (en) * | 2002-06-24 | 2004-01-01 | Nayeem Islam | Mobile application environment |
US6941310B2 (en) * | 2002-07-17 | 2005-09-06 | Oracle International Corp. | System and method for caching data for a mobile application |
US7076508B2 (en) | 2002-08-12 | 2006-07-11 | International Business Machines Corporation | Method, system, and program for merging log entries from multiple recovery log files |
TWI231669B (en) * | 2002-11-02 | 2005-04-21 | Ibm | System and method for using portals by mobile devices in a disconnected mode |
US20040098463A1 (en) * | 2002-11-19 | 2004-05-20 | Bo Shen | Transcoding-enabled caching proxy and method thereof |
US6973460B1 (en) | 2002-11-26 | 2005-12-06 | Microsoft Corporation | Framework for applying operations to nodes of an object model |
AU2003298797A1 (en) * | 2002-12-04 | 2004-06-23 | Entriq Inc. | Multiple content provider user interface |
US6964053B2 (en) * | 2002-12-04 | 2005-11-08 | International Business Machines Corporation | Type descriptor language (TDLanguage) metamodel |
WO2004055659A1 (en) * | 2002-12-13 | 2004-07-01 | Bea Systems, Inc. | System and method for mobile communication |
US7644361B2 (en) * | 2002-12-23 | 2010-01-05 | Canon Kabushiki Kaisha | Method of using recommendations to visually create new views of data across heterogeneous sources |
US20040128345A1 (en) * | 2002-12-27 | 2004-07-01 | Robinson Scott H. | Dynamic service registry |
US7366460B2 (en) * | 2003-01-23 | 2008-04-29 | Dexterra, Inc. | System and method for mobile data update |
US7966418B2 (en) * | 2003-02-21 | 2011-06-21 | Axeda Corporation | Establishing a virtual tunnel between two computer programs |
US7516157B2 (en) * | 2003-05-08 | 2009-04-07 | Microsoft Corporation | Relational directory |
US7242925B2 (en) | 2003-05-08 | 2007-07-10 | Bellsouth Intellectual Property Corporation | Wireless market place for multiple access internet portal |
GB0311564D0 (en) * | 2003-05-20 | 2003-06-25 | Ibm | Monitoring operational data in data processing systems |
US20050033767A1 (en) * | 2003-08-04 | 2005-02-10 | Kamentz Joel D. | Computer-implemented system and method for resource caching and execution |
US20050234969A1 (en) | 2003-08-27 | 2005-10-20 | Ascential Software Corporation | Services oriented architecture for handling metadata in a data integration platform |
US20050050142A1 (en) * | 2003-08-28 | 2005-03-03 | Aligo Inc. | Method and framework for transaction synchronization |
US7290034B2 (en) * | 2003-09-18 | 2007-10-30 | Vulcan Portals Inc. | Method and system for polling a server for new emails, downloading the new emails in a background process, and caching the downloaded emails for access by an email application of an electronic device, such as a portable computer |
US20050138143A1 (en) * | 2003-12-23 | 2005-06-23 | Thompson Blake A. | Pre-fetching linked content |
US8751926B2 (en) | 2004-02-12 | 2014-06-10 | Mobileframe, Llc | Intelligent rendering on a mobile computing device |
US7467389B2 (en) * | 2004-11-23 | 2008-12-16 | Sybase, Inc. | System and methodology providing service invocation for occasionally connected computing devices |
US20060155759A1 (en) | 2004-12-29 | 2006-07-13 | Yahoo! Inc. | Scalable cache layer for accessing blog content |
US8175233B2 (en) | 2005-02-07 | 2012-05-08 | Avaya Inc. | Distributed cache system |
US7702318B2 (en) | 2005-09-14 | 2010-04-20 | Jumptap, Inc. | Presentation of sponsored content based on mobile transaction event |
US7548915B2 (en) | 2005-09-14 | 2009-06-16 | Jorey Ramer | Contextual mobile content placement on a mobile communication facility |
US7899917B2 (en) * | 2007-02-01 | 2011-03-01 | Microsoft Corporation | Synchronization framework for occasionally connected applications |
-
2005
- 2005-05-04 US US11/122,294 patent/US7650432B2/en active Active
- 2005-05-20 EP EP05753824.1A patent/EP1754175A4/en not_active Ceased
- 2005-05-20 WO PCT/US2005/017822 patent/WO2005114489A2/en not_active Application Discontinuation
- 2005-05-20 JP JP2006542905A patent/JP4551899B2/ja active Active
- 2005-05-20 AU AU2005246392A patent/AU2005246392B2/en active Active
Also Published As
Publication number | Publication date |
---|---|
AU2005246392B2 (en) | 2008-10-16 |
AU2005246392A1 (en) | 2005-12-01 |
JP2007524933A (ja) | 2007-08-30 |
WO2005114489A3 (en) | 2009-04-09 |
EP1754175A2 (en) | 2007-02-21 |
WO2005114489A2 (en) | 2005-12-01 |
EP1754175A4 (en) | 2013-11-06 |
US7650432B2 (en) | 2010-01-19 |
US20060117073A1 (en) | 2006-06-01 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
JP4551899B2 (ja) | 随時接続アプリケーションサーバー | |
US9398077B2 (en) | Mobile applications | |
CN101421726B (zh) | 偶尔连接的应用服务器 | |
US7827565B2 (en) | Integration architecture for non-integrated tools | |
JP4473128B2 (ja) | ウェブ・ポータルの関連するポートレットが、同期されたコンテンツ表示のために協働することを可能にする方法および装置 | |
JP4456485B2 (ja) | ポータル・サーバにおいてポートレットの集合を管理する方法および装置 | |
US7089295B2 (en) | Customizing content provided by a service | |
AU2001291300B2 (en) | Providing content from multiple services | |
JP4218759B2 (ja) | ポータル・サーバからセッション情報を中継する方法および装置 | |
AU2001293254B2 (en) | Accessing data stored at an intermediary from a service | |
AU2001295024B2 (en) | Developing applications online | |
JP4406609B2 (ja) | 単一のインターフェイスからのデータの多重階層を管理するための手法 | |
US20070220089A1 (en) | Modular distributed mobile data applications | |
JP2006501558A (ja) | ウェブ・アプリケーション用のウェブ・ページのセッションをユーザに表示する装置と方法 | |
US20050262119A1 (en) | Data processing systems and methods | |
AU2001293254A1 (en) | Accessing data stored at an intermediary from a service | |
CN102346685A (zh) | 集成适配器管理系统和方法 | |
US20030188034A1 (en) | Method and apparatus for enabling retargetable application architectures | |
Team | Microservice Application Design | |
Gomez et al. | Second International Workshop on Adaptation and Evolution in Web Systems Engineering (AEWSE’07) |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
A131 | Notification of reasons for refusal |
Free format text: JAPANESE INTERMEDIATE CODE: A131 Effective date: 20090601 |
|
A601 | Written request for extension of time |
Free format text: JAPANESE INTERMEDIATE CODE: A601 Effective date: 20090901 |
|
A602 | Written permission of extension of time |
Free format text: JAPANESE INTERMEDIATE CODE: A602 Effective date: 20090908 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A523 Effective date: 20091001 |
|
A131 | Notification of reasons for refusal |
Free format text: JAPANESE INTERMEDIATE CODE: A131 Effective date: 20100315 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A523 Effective date: 20100615 |
|
TRDD | Decision of grant or rejection written | ||
A01 | Written decision to grant a patent or to grant a registration (utility model) |
Free format text: JAPANESE INTERMEDIATE CODE: A01 Effective date: 20100705 |
|
A01 | Written decision to grant a patent or to grant a registration (utility model) |
Free format text: JAPANESE INTERMEDIATE CODE: A01 |
|
A61 | First payment of annual fees (during grant procedure) |
Free format text: JAPANESE INTERMEDIATE CODE: A61 Effective date: 20100712 |
|
R150 | Certificate of patent or registration of utility model |
Ref document number: 4551899 Country of ref document: JP Free format text: JAPANESE INTERMEDIATE CODE: R150 Free format text: JAPANESE INTERMEDIATE CODE: R150 |
|
FPAY | Renewal fee payment (event date is renewal date of database) |
Free format text: PAYMENT UNTIL: 20130716 Year of fee payment: 3 |
|
S111 | Request for change of ownership or part of ownership |
Free format text: JAPANESE INTERMEDIATE CODE: R313113 |
|
S531 | Written request for registration of change of domicile |
Free format text: JAPANESE INTERMEDIATE CODE: R313531 |
|
FPAY | Renewal fee payment (event date is renewal date of database) |
Free format text: PAYMENT UNTIL: 20130716 Year of fee payment: 3 |
|
R350 | Written notification of registration of transfer |
Free format text: JAPANESE INTERMEDIATE CODE: R350 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |