チュートリアル : 初めてのデータ トランスフォーメーション構築

     前  次    新しいウィンドウで目次を開く     
ここから内容

手順 4 : 繰り返し要素のマッピング - 結合の作成

この手順では、既存のクエリにさらにマッピングを追加します。これまでの節では、PriceQuote.xsd XML スキーマで定義されたソースの型から、Quote.xsd XML スキーマで定義された対象の型に一部のデータをマップしました。この節では、次の図のように、PriceQuote.xsd XML スキーマ、AvailQuote.xsd XML スキーマ、および Java float プリミティブ taxRate で定義されたソースの型から、Quote.xsd XML スキーマで定義された対象の型にさらにデータをマップします。

図 5-1 ソースの型からのデータの追加

ソースの型からのデータの追加

この節で作成されるマッピングでは、ソース XML スキーマおよび対象 XML スキーマの繰り返し要素間の結合が作成されます。以下のタスクを実行して、結合を作成、テスト、および変更します。

結合クエリで呼び出すユーザ定義 Java メソッドを作成するには

このタスクでは、MyTutorialJoin トランスフォーメーション ファイルに、要求されたウィジェットの税込みの合計金額を計算するユーザ定義 Java メソッドを作成します。「calculateTotalPrice ユーザ メソッドをクエリで呼び出すには」では、このメソッドを呼び出すようにクエリを変更します。

  1. [ナビゲーター] ペインで、src/requestquote フォルダを参照し、MyTutorialJoin.java を選択します。
  2. MyTutorialJoin トランスフォーメーションのソースを右クリックします。
  3. ショートカット メニューから、[トランスフォーメーションユーザ メソッドの追加] を選択します。
  4. ユーザ メソッドが MyTutorialJoin トランスフォーメーション ファイルに作成されます。

  5. newusermethod1 という新しいメソッドがソースに追加されます。このメソッドの名前を calculateTotalPrice に変更します。
  6. MyTutorialJoin トランスフォーメーション ファイルを編集して、生成された次の calculateTotalPrice Java メソッドに移動します。
  7. 	 public java.lang.String calculateTotalPrice() {
    return "";
    }

    このメソッドを次の calculateTotalPrice Java メソッドに置き換えます。

    public static float calculateTotalPrice(float taxRate, int quantity, float price, boolean fillOrder)
    {
    float totalTax, costNoTax, totalCost;
    if (fillOrder)
    {
    // 合計税額を計算する
    totalTax = taxRate * quantity * price;
    // 税抜きの合計代金を計算する
    costNoTax = quantity * price;
    // 税額と代金とを加算して、合計金額を取得する
    totalCost = totalTax + costNoTax;
    		}
    		else
    		{
    			    totalCost = 0;
    		}
    		return totalCost;
       }
注意 : calculateTotalPrice 関数の戻り値の型を、必ず String から float に変更してください。
  1. このアプリケーションのすべてのファイルを保存します。Oracle Workshop for WebLogic メニューから、[ファイルすべて保管] を選択します。
  2. 注意 : XQuery Mapper は、XQuery で使用されるユーザ定義 Java メソッドが静的である場合のみ、Java メソッドを実行します。
繰り返し要素の 2 つのセットを結合するには
  1. デザイン ビューに myJoin.xq を表示します。
    1. [ナビゲーター] ペインで、Tutorial_Process_Application_Web\src\requestquote\myJoin.xq をダブルクリックし、[デザイン] を選択します。
  2. [ソース] ペインで、shipAddress ノードを折りたたみます。
  3. [ソース] ペインの priceQuote1\priceRequests\priceRequest ノードを [対象] ペインの quote\quoteResponse ノードにドラッグ アンド ドロップします。
  4. これらのノードは両方とも繰り返しノードです。繰り返しノードでは、このノードの複数のインスタンスを指定できます。繰り返しノードはノードの右側に + 記号が付くことで表されます。

    警告 : priceRequests ノードではなく、priceRequest ノードを選択する必要があります。

    次の図のように、2 つの繰り返しノードをつなぐ破線が表示されます。

    短い線の破線は、構造的なリンク (データを直接マップしない 2 つの親構造間のリンク) を表します。

    XML の繰り返しノードの詳細については、「XML の繰り返しノードについて」を参照してください。

  5. [ソース] ペインの availQuote1\availRequest ノードを [対象] ペインの quote\quoteResponse ノードにドラッグ アンド ドロップします。
  6. 次の図のように、2 つの繰り返し要素をつなぐ破線が表示されます。

    図 5-2 繰り返し要素の 2 つのセットの結合


    繰り返し要素の 2 つのセットの結合

  7. [ソース] タブを選択して、クエリに対する変更を表示します。
  8. [ソース] に次のクエリが表示されます。

    declare namespace xf = "http://tempuri.org/Tutorial_Project_Web/src/requestquote/myJoin/";
    declare namespace ns0 = "http://www.example.org/price";
    declare namespace ns1 = "http://www.example.org/avail";
    declare namespace ns2 = "http://www.example.org/quote";
    declare function xf:myJoin($priceQuote1 as element(ns0:priceQuote),
        $availQuote1 as element(ns1:availQuote),
        $taxRate as xs:float)
        as element(ns2:quote) {
            <ns2:quote>
                <name>{ data($priceQuote1/ns0:customerName) }</name>
                <address>{ concat($priceQuote1/ns0:shipAddress/@street ,",", $priceQuote1/ns0:shipAddress/@city ,",", fn:upper-case($priceQuote1/ns0:shipAddress/@state) , ",",$priceQuote1/ns0:shipAddress/@zip) }</address>
                {
    for 
    $priceRequest in $priceQuote1/ns0:priceRequests/ns0:priceRequest,
                        $availRequest in $availQuote1/ns1:availRequest
                    return
                        <quoteResponse/>
                }
            </ns2:quote>
    };
    declare variable $priceQuote1 as element(ns0:priceQuote) external;
    declare variable $availQuote1 as element(ns1:availQuote) external;
    declare variable $taxRate as xs:float external;
    xf:myJoin($priceQuote1,
        $availQuote1,
        $taxRate)

    上のクエリでは、繰り返しノードの子の間のデータ リンクは存在しません。そのため、quoteResponse 要素は空になっています (文字列 <quoteResponse/> は空のノードです)。

    繰り返しノード間の構造的なリンクでは、for ループが生成されます (for ループは上のクエリのリストで太字で示されています)。この XQuery for ループは、priceRequest 繰り返し要素と availReqest 繰り返し要素のセットを反復処理します。たとえば、このクエリのソース XML データに priceRequest 要素の 3 つのインスタンスと availRequest 要素の 3 つのインスタンスが含まれている場合、for ループは以下の合計 9 回の結合を実行します。

    • priceRequest 要素の最初のインスタンスと、availRequest 要素の最初のインスタンスを結合する。
    • priceRequest 要素の最初のインスタンスと、availRequest 要素の 2 番目のインスタンスを結合する。
    • priceRequest 要素の最初のインスタンスと、availRequest 要素の 3 番目のインスタンスを結合する。
    • priceRequest 要素の 2 番目のインスタンスと、availRequest 要素の最初のインスタンスを結合する。
    • priceRequest 要素の 2 番目のインスタンスと、availRequest 要素の 2 番目のインスタンスを結合する。
    • priceRequest 要素の 2 番目のインスタンスと、availRequest 要素の 3 番目のインスタンスを結合する。
    • priceRequest 要素の 3 番目のインスタンスと、availRequest 要素の最初のインスタンスを結合する。
    • priceRequest 要素の 3 番目のインスタンスと、availRequest 要素の 2 番目のインスタンスを結合する。
    • priceRequest 要素の 3 番目のインスタンスと、availRequest 要素の 3 番目のインスタンスを結合する。
    • トランスフォーメーションではクエリを使用してすべての可能な結合を生成できますが、トランスフォーメーションによっては次の手順で説明するように結合に制約を付けることもできます。

  9. [デザイン] タブを選択します。
  10. [ソース] ペインの priceQuote1/priceRequests/priceRequest/widgetId ノードを availQuote1/availRequest/widgetId ノードにドラッグ アンド ドロップします。これらの要素は両方とも、[ソース] ペインにあります。
  11. 次の図のように、2 つの widgetId ノード間にリンクが表示されます。

    図 5-3 2 つの WidgetId ノード間のリンク


    2 つの WidgetId ノード間のリンク

  12. [ソース] タブをクリックして、クエリに対する変更を表示します。
  13. 次のクエリが表示されます。

    declare namespace xf = "http://tempuri.org/Tutorial_Process_Application_Web/src/requestquote/myJoin/";
    declare namespace ns0 = "http://www.example.org/price";
    declare namespace ns1 = "http://www.example.org/avail";
    declare namespace ns2 = "http://www.example.org/quote";
    declare function xf:myJoin($priceQuote1 as element(ns0:priceQuote),
       $availQuote1 as element(ns1:availQuote),
       $taxRate as xs:float)
       as element(ns2:quote) {
    <ns2:quote>
                <name>{ data($priceQuote1/ns0:customerName) }</name>
                  <address>{ concat($priceQuote1/ns0:shipAddress/@street ,",",                 $priceQuote1/ns0:shipAddress/@city ,",",                 fn:upper-case($priceQuote1/ns0:shipAddress/@state) , ",",                 $priceQuote1/ns0:shipAddress/@zip) }</address>
                {
    for $priceRequest in $priceQuote1/ns0:priceRequests/ns0:priceRequest,
        $availRequest in $availQuote1/ns1:availRequest
    where 
    data($priceRequest/ns0:widgetId) = data($availRequest/ns1:widgetId)
    
    
    return
                        <quoteResponse/>
                }
            </ns2:quote>
    };
    declare variable $priceQuote1 as element(ns0:priceQuote) external;
    declare variable $availQuote1 as element(ns1:availQuote) external;
    declare variable $taxRate as xs:float external;
    xf:myJoin($priceQuote1,
        $availQuote1,
        $taxRate)

    widgetId ノード間のリンクによって、for ループ内に where 句が生成されます (where 句は上のクエリのリストで太字で示されています)。この where 句は for ループの出力に制約や制限を付けます。特に where 句は、where 句内の式が true の場合に、for ループが return の内容を出力することを指定します。この例では、availRequest 要素の widgetIdpriceQuestwidgetId と一致する場合に、次の XML データが返されます。

    <quoteResponse/>

    空の quoteReponse 要素はあまり使いやすくありません。次のタスク「quoteResponse 要素に入れるリンクを追加するには」では、quoteResponse 要素に入れるデータ リンクを追加します。

quoteResponse 要素に入れるリンクを追加するには
  1. [デザイン] タブを選択します。
  2. [ソース] ペインの priceQuote1/priceRequests/priceRequest/widgetId ノードを [対象] ペインの quote/quoteResponse/widgetId ノードにドラッグ アンド ドロップします。
  3. [ソース] ペインの priceQuote1/priceRequests/priceRequest/price ノードを [対象] ペインの quote/quoteResponse/unitPrice ノードにドラッグ アンド ドロップします。
  4. [ソース] ペインの availQuote1/availRequest/requestedQuantity ノードを [対象] ペインの quote/quoteResponse/requestedQuantity ノードにドラッグ アンド ドロップします。
  5. [ソース] ペインの availQuote1/availRequest/quantityAvail ノードを [対象] ペインの quote/quoteResponse/fillOrder ノードにドラッグ アンド ドロップします。
  6. [ソース] ペインの availQuote1/availRequest/shipDate ノードを [対象] ペインの quote/quoteResponse/shipDate ノードにドラッグ アンド ドロップします。
  7. [ソース] ペインの taxRate Java プリミティブを [対象] ペインの quote/quoteResponse/taxRate ノードにドラッグ アンド ドロップします。
  8. [ソース] ペインの taxRate Java プリミティブを [対象] ペインの quote/quoteResponse/totalCost ノードにドラッグ アンド ドロップします。
  9. 注意 : 次の節では、注文の合計金額を計算するため、taxRate Java プリミティブと quote/quoteResponse/totalCost ノードの間のリンクを編集します。

    デザイン ビューに、次の図のようにリンクが表示されます。

    図 5-4 [ソース] ペインと [対象] ペインのリンク


[ソース] ペインと [対象] ペインのリンク

  1. このアプリケーションのすべてのファイルを保存します。Oracle Workshop for WebLogic メニューから、[ファイルすべて保管] を選択します。
calculateTotalPrice ユーザ メソッドをクエリで呼び出すには
  1. [デザイン] タブを選択します。
  2. taxRate Java プリミティブと quote/quoteResponse/totalCost ノードの間のリンクを選択します。
  3. [式の関数] パレットで、[ユーザ関数] フォルダを見つけます。
  4. [ユーザ関数] フォルダで calculateTotalPrice 関数を選択し、それを [一般式] ペインにドラッグ アンド ドロップします。
  5. [ソース] ペインから taxRate ノードを選択して、[一般式] ペインの $float-var パラメータの上にドラッグ アンド ドロップします。
  6. [一般式] ペインで、デフォルト引数 $float-var$taxRate 引数に置き換えられて、次の引数が選択されます。

    [一般式] ペインで $int-var を選択します。

  7. [ソース] ペインで availQuote1/availRequest/requestedQuantity を選択し、それを [一般] ペインの選択されている $int-var 引数にドラッグ アンド ドロップします。
  8. [一般式] ペインで、デフォルト引数 $int-var$availRequest/ns1:requestedQuantity 引数に置き換えられて、次の引数が選択されます。

    [一般式] ペインで $float-var を選択します。

  9. [ソース] ペインで priceQuote1/priceRequests/priceRequest/price を選択し、それを [一般式] ペインの選択されている $float-var 引数にドラッグ アンド ドロップします。
  10. [一般式] ペインで、デフォルト引数 $float-var$priceRequest/ns0:price 引数に置き換えられて、次の引数が選択されます。

    [一般式] ペインで $boolean-var を選択します。

  11. [ソース] ペインで availQuote1/availRequest/quantityAvail を選択し、それを [一般式] ペインの選択されている $boolean-var 引数にドラッグ アンド ドロップします。
  12. 図 5-5 に示すように、[一般式] ペインで、デフォルト引数 $boolean-var$availRequest/ns1:quantityAvail 引数に置き換えられます。

    図 5-5 [一般式] ペイン


[一般式] ペイン

  1. [適用] をクリックします。
  2. デザイン ビューで、図 5-6 のように表示されます。

    図 5-6 [ソース] ペインと [対象] ペインの間のリンク


    [ソース] ペインと [対象] ペインの間のリンク

  3. このアプリケーションのすべてのファイルを保存します。Oracle Workshop for WebLogic メニューから、[ファイルすべて保管] を選択します。
生成されたクエリを表示するには
  1. [ソース] タブを選択します。
  2. ソース ビューに、次のクエリが表示されます。

    declare namespace xf = "http://tempuri.org/Tutorial_Process_Application_Web/src/requestquote/myJoin/";
    declare namespace ns0 = "http://www.example.org/price";
    declare namespace ns1 = "http://www.example.org/avail";
    declare namespace ns2 = "http://www.example.org/quote";
    declare function xf:myJoin($priceQuote1 as element(ns0:priceQuote),
        $availQuote1 as element(ns1:availQuote),
        $taxRate as xs:float) as element(ns2:quote)
        {
          <ns2:quote>
    {
    <name>{ data($priceQuote1/ns0:customerName) }</name>
                <address>{ concat($priceQuote1/ns0:shipAddress/@street ,",", $priceQuote1/ns0:shipAddress/@city ,",", fn:upper-case($priceQuote1/ns0:shipAddress/@state) , ",", $priceQuote1/ns0:shipAddress/@zip) }</address>
                {
                    for $priceRequest in                    $priceQuote1/ns0:priceRequests/ns0:priceRequest,
                        $availRequest in $availQuote1/ns1:availRequest
                    where data($priceRequest/ns0:widgetId) =                    data($availRequest/ns1:widgetId)
                    return
    <quoteResponse>
    <widgetId>{ data($priceRequest/ns0:widgetId) }</widgetId>
                     <unitPrice>{ data($priceRequest/ns0:price) }</unitPrice>
                     <requestedQuantity>{                  data($availRequest/ns1:requestedQuantity) }</requestedQuantity>
    <fillOrder>{ data($availRequest/ns1:quantityAvail) }</fillOrder>

    {
    for $shipDate in $availRequest/ns1:shipDate
    return
    <shipDate>{ data($shipDate) }</shipDate>
    }
    <taxRate>{ $taxRate }</taxRate>
    <totalCost>{ calculateTotalPrice($taxRate,
    $availRequest/ns1:requestedQuantity,
    $priceRequest/ns0:price,
    $availRequest/ns1:quantityAvail) }</totalCost>
    </quoteResponse>
    }
    </ns2:quote>

前の手順で追加されたリンクによって、<quoteResponse> タグと </quoteResponse> タグの間に追加の XQuery ソース コードが生成されています (追加ソースは上のクエリのリストで太字で示されています)。

クエリをテストするには
  1. [テスト ビュー] タブを選択します。
  2. myJoin トランスフォーメーション メソッドに渡す重要な 3 つのパラメータ、$priceQuote1、$availQuote1、および $taxRate があります。「単純なクエリをテストするには」のタスクで、$priceQuote1 パラメータのソース データとして PriceQuote.xml をインポートしました。

  3. ソース パラメータ $availQuote1 用に AvailQuote.xml をインポートします。
    1. [ソース データ] ペインのドロップダウン メニューから、availQuote1 を選択します。
    2. [インポート] をクリックします。
    3. [ファイルのインポート] ダイアログ ボックスが表示されます。

    4. src フォルダをダブルクリックします。
    5. testxml フォルダをダブルクリックします。
    6. AvailQuote.xml ファイルをダブルクリックします。
    7. AvailQuote.xml ファイルのグラフィカルな表現が [ソース データ] ペインに表示されます。

  4. [ソース データ] ペインのドロップダウン メニューから taxRate を選択します。
  5. taxRate ノードの [ノード値] フィールドで、既存の値をダブルクリックし、「0.08」と入力してからキーボードで〔Enter〕を押します。
  6. [結果データ] ペインで [XQuery のテスト] をクリックします。
  7. テスト XML データを使用して、クエリが実行されます。図 5-7 のように、生成された XML データのグラフィカルな表現が [結果データ] ペインの [XML デザイン ビュー] に表示されます。

    図 5-7 [結果データ] ペイン


    [結果データ] ペイン

    このクエリは、ソース繰り返し要素の 2 つのセット (availRequest および priceRequest) を、1 つの繰り返し要素 (quoteResponse) に結合します。

  8. クエリから生成された XML データが、関連付けられた XML スキーマに対して有効であることを確認するには、[結果データ] ペインで [検証] をクリックします。
  9. XML データが対象の XML スキーマに対して有効であるかどうかが、[出力] タブに表示されます。この例では、生成された XML データが Quote.xsd ファイルの XML スキーマに対して有効であるかどうか確認されます。

MyTutorialJoin コントロールのインスタンスを作成するには

このタスクでは、MyTutorialJoin.java コントロールのインスタンスを作成します。

注意 : XQuery トランスフォーメーション パースペクティブからプロセス パースペクティブに切り替えて、コントロールを作成します。[ウィンドウ|パースペクティブを開く|その他|プロセス パースペクティブ] をクリックします。
  1. デザイン ビューに、RequestQuote ビジネス プロセスを表示します。
    1. [パッケージ・エクスプローラー] ペインで、Tutorial_Process_Application_Web\src\requestquote\RequestQuote.java に移動し、RequestQuote.java をダブルクリックします。
    2. myTutorialJoin.java トランスフォーメーション ファイルを、src/requestquote フォルダから [データ パレット] の [コントロール] フォルダにドラッグ アンド ドロップします。
    3. MyTutorialJoin.java というインスタンスがプロジェクト内に作成され、次の図のように [コントロール] ペインに表示されます。

      図 5-8 MyTutorialJoin.java のインスタンス


      MyTutorialJoin.java のインスタンス

トランスフォーメーションを呼び出すノードを編集するには

このタスクでは、RequestQuote ビジネス プロセス内の [Combine Price and Avail Quotes] ノードを編集し、このノードによって呼び出されるインスタンスを、TutorialJoin.java のインスタンスから MyTutorialJoin.java のインスタンスに変更します。さらに、MyTutorialJoin コントロールの myJoin() メソッドを呼び出すように、[Combine Price and Avail Quotes] ノードの設計を変更します。myJoin() メソッドは、異なるシステムからビジネス プロセスに返されるデータを結合して、1 つの XML 応答ドキュメント (見積もり) を作成します。作成されたドキュメントはビジネス プロセスのクライアントに返されます。

  1. RequestQuote ビジネス プロセスで、[Combine Price and Avail Quotes] ノードをダブルクリックし、ノード ビルダを開きます。
  2. ノード ビルダの [一般的な設定] ペインが表示されます。

  3. [コントロール] フィールドのドロップダウン メニューから myTutorialJoin を選択します。
  4. [メソッド] フィールドから QuoteDocument myJoin() を選択します。
  5. [データの送信] をクリックして、ノード ビルダの 2 番目のペインを開きます。
  6. [割り当てる変数を選択します] フィールドにデフォルトの変数が表示されます。次のリストに示すように、データ型は myJoin() メソッドのソース パラメータで想定されているデータ型と一致します。

    priceQuote には、ビジネス プロセスの For Each ループにある priceProcessor サービスから返される、価格の見積もりデータが保持されます。

    availQuote には、ビジネス プロセスの For Each ループにある availProcessor サービスから返される、在庫の見積もりデータが保持されます。

    taxRate は、taxCalculation サービスからビジネス プロセスに返された、出荷先に基づく消費税率を保持します。

    次の図に示すように、[コントロールが予期する値] フィールドに、MyTutorialJoin コントロールの myJoin() メソッドで予期されるデータ型が表示されます。


    MyTutorialJoin.java のインスタンス

  7. [データの受信] をクリックして、ノード ビルダの 3 番目のペインを開きます。
  8. [データの受信] タブの [割り当てる変数を選択します] フィールドにデフォルトの変数 Quote が表示されます。データ型は myJoin() メソッドの対象パラメータで想定されているデータ型と一致します。次の図に示すように、[コントロールが返す値] フィールドに、myJoin() メソッドによって返されたデータ型 QuoteDocument が表示されます。


    MyTutorialJoin.java のインスタンス

  9. ノード ビルダで、[閉じる] をクリックし、指定した内容を保存してノード ビルダを閉じます。
  10. RequestQuote ビジネス プロセスを含む、このアプリケーションのすべてのファイルを保存します。Oracle Workshop for WebLogic メニューから、[ファイル|すべて保管] を選択します。
ビジネス プロセスを実行するには

このチュートリアルでは、クエリの実行対象となる XML データを入力しました。実行時に、ビジネス プロセスは XML データを構築し、それをこのチュートリアルで構築されたクエリに渡します。ビジネス プロセスを実行して、クエリを呼び出すには、『チュートリアル : 初めてのビジネス プロセス設計』にある、「手順 12 : RequestQuote ビジネス プロセスの実行」の手順に従います。


  ページの先頭       前  次