マッパー
マッパーとはコンポーネント同士を接続してストリーム、変数、コンポーネントプロパティの情報を設定するコンポーネントです。
ここでは、マッピングウィンドウの入力、出力の各フィールドの説明とレコードセットを受けたマッパーが実際にどのように動作するかについて説明します。
入出力フィールドとマッパー関数
マッピングウィンドウで左側に表示される入力フィールド、右側に表示される出力フィールドと中央のマッピング領域に配置するマッパー関数について説明します。
入力
ストリーム
フィールド
マッパーでは入力ストリームのレコード値を用いて値をマッピングします。 画面左側「ストリーム」の項に入力ストリームのフィールド定義が表示されます。
入力ストリームがコンテナの場合、コンテナ内の各ストリームの総和が入力レコード件数となります。例えば3レコード、5レコード、7レコードのCSVがコンテナ化されている場合、入力レコード数は15レコードとなります。
入力ストリームが複数の場合、それぞれのストリームに対してマッピングが行えます。レコード件数は入力ストリームのうち最大のレコード件数になります。マッパーは1レコードマッピングを行うと、すべての入力レコードのポインタを1レコード動かします。レコード数が他のストリームより少ないストリームでは、自身のレコードを処理した後のフィールド値はnullとなります。
入力ストリームがコンテナまたはレコードストリームの場合に、ストリームまたはストリームのフィールドを1つもマッピングしないと、最初の1件のみマッピングされます。
レコード番号
入力レコードの1ベースのインデックスを返します。
レコード件数
入力レコードのレコード総数を返します。
出力ストリームへの値のマッピングは入力ストリームのレコード件数と同じ回数行われます。 入力ストリームのレコード数が0件でかつ、「入力が無い場合エラー」プロパティが「はい」の場合、エラーになります。「いいえ」の場合は1回だけマッピングが行われます。この場合、ストリームの各フィールド値はnullになります。 「ループを開始」プロパティを「はい」にするとMapperコンポーネントを起点にレコード件数回ループが始まります。この場合、1レコードのストリームが入力レコード件数回出力されることになります。
ストリーム変数
ストリームにストリーム変数が付加されている場合は、その値もマッパーで参照できます。
コンポーネント
入力コンポーネントのプロパティがマッパーで参照することができます(ただしプロパティによってはマッパーで使用できないものもあります)。
実行回数
リクエストされたフローの開始から終了までの間にあるすべてのループ処理でコンポーネントを実行した回数を参照することができます。ループ処理の中にさらにループ処理があるような場合でも、内側のループ処理で実行回数がリセットされることはありません。
エラーメッセージ
任意のコンポーネントでエラーが発生した場合、エラーを無視するか、またはエラー処理フローから次のコンポーネントへ処理の順序が遷移したとき、そのコンポーネントの次にマッパーを配置してこのフィールドで実行後のエラーメッセージを取得することができます。
変数類
入力側ではマッパー変数、フロー変数、外部変数セット、システム変数が参照できます。
出力
ストリーム
出力ストリームのレコード数はマッピングが行われた回数と同じになります。ただし、Binary、Textなどの単一レコードのストリームを出力する場合は、入力の各レコードの情報は連結されていきます。
「入力をそのまま出力」プロパティが「はい」の場合は、入力ストリームがそのまま出力ストリームとなります。この場合、出力ストリームに対するマッピングは行えません。
コンポーネント
マッパーの次のコンポーネントのプロパティがマッパーで設定することができます (ただしプロパティによってはマッパーで使用できないものもあります) 。
出力側のコンポーネントプロパティへの値の差込みは入力ストリームのレコード数に関わらず1回しか行われません。つまり10レコードを持つ入力ストリームのフィールドからマッピングした場合、その値は最初のレコードの値になります。ただし、「ループを開始」プロパティが「はい」の場合は、マッパーが処理を行うごとにマッピングが行われます。
変数類
出力側ではマッパー変数以外の変数への値の設定はコンポーネントプロパティの場合と同様に、1回のマッパーの実行では一度しか行われません。マッパー変数への値の設定のみレコードの行数分行われます。システム変数、外部変数セットの定数と変更不可のフロー変数には値を設定することができません。(出力側には表示されません。)
ステータス
「ステータス」フィールドに対してマッピングした内容がステータス文字列として記録されます。
処理に時間がかかるリクエストを実行中の場合に、処理がどこまで行われているか確認するために記録、参照すると便利です。管理コンソールの「状態」-「フロー」-「リクエスト一覧」でリクエストの詳細情報を表示すると、ステータス文字列を確認することができます。また、flow-ctrlコマンドなどの外部クライアントから確認することができます。flow-ctrlコマンドでは、show requestまたはshow workerコマンドで確認することができます。
ログ
「ログ」フィールドに対してマッピングした内容は実行ログに出力されます。
初期状態ではFlowService.logに出力されます。アプリケーションログを設定している場合、アプリケーションログに出力されます。
マッパー関数
関数を配置することでその出力を出力側のフィールドに差し込むことができます。関数は1レコードのマッピングの間に一度だけ実行されます。 例としてUUID関数を以下のように2つのフィールドに対してマッピングした場合を考えます。
UUID → Field1 → Field2
ここで入力ストリームは10レコードのストリームだったとします。この場合、各レコードの処理においてUUID関数は一度だけ実行されるので、それぞれのレコードでField1、Field2の値は同じになりますが、各レコードでの値は異なります。
マッパーの動作
入力側でのXMLの展開
XMLのレコード数はフィールド定義中の繰り返し出現するノードの数で決まります。 例えば、以下のようなXMLインスタンスを考えます。
<root> <注文伝票> <注文番号>1111</注文番号> <商品><商品名>携帯型CDプレーヤ</商品名><金額>1000</金額></商品> <商品><商品名>ラジカセ</商品名><金額>2000</金額></商品> </注文伝票> <注文伝票> <注文番号>2222</注文番号> <商品><商品名>ビデオカメラ</商品名><金額>3000</金額></商品> <商品><商品名>デジカメ</商品名><金額>4000</金額></商品> <商品><商品名>スキャナー</商品名><金額>5000</金額></商品> </注文伝票> </root>
この中で繰り返し出現するノードは「注文伝票」と「商品」です。
このインスタンスでは注文伝票要素は2つあり、それぞれが2個と3個の商品要素を持っています。つまりレコード数としては 2+3=5レコードとなり、値を持つ要素だけをフラットに展開すると以下のようになります。
1111, 携帯型CDプレーヤ,1000 1111,ラジカセ,2000 2222,ビデオカメラ,3000 2222,デジカメ,4000 2222,スキャナー,5000
これがマッパーの入力側で使用されるレコードセットになります。 ただし、マッパーではマッピングに使用されていないフィールド定義は無視されるので、参照されている要素が「注文番号」のみであり、商品以下の要素は参照されていない場合、入力のインスタンスは以下のように解釈されます。
<root> <注文伝票> <注文番号>1111</注文番号> </注文伝票> <注文伝票> <注文番号>2222</注文番号> </注文伝票> </root>
この場合、入力のレコードセットは以下の2レコードとなります。
1111 2222
逆から言えば、注文番号だけを使用したいが、レコード数としては5レコードとして扱いたい場合は、商品以下の要素をダミーのフロー変数などにマッピングする必要があります。
出力側でのXMLの構成
出力側でのXMLのフィールド定義には最低でも文書要素の定義が必要です。 マッパーの処理の結果として、フラットなレコードセットが準備されているので、出力側では以下のルールに従ってそのレコードセットをXMLに構成します。
- 文書要素は必ず生成される。
- マッピングが行われなかったノードは生成しない。
- マッピングが行われても値がnullであるノードは生成しない。
- 自分よりも上位ノードに繰り返し可能なノードがない場合はそこにマッピングされた値は随時上書きされる。
- 繰り返し可能なノードの以下にマッピングが行われた場合は、既に作成されたXMLの中から自分のレコードと構成要素が同じノードを検索する。完全に構成要素の同じノードが既に存在する場合は、同一のレコードであるとみなしマッピングを行わない(つまり、レコードとなる要素にはキーが必要)。繰り返し可能でない構成要素がすべて同じノードが存在する場合は、レコードはそのノードに属するとみなし、そこに繰り返し可能なノードを生成する。それもない場合は完全に新しいレコードとして新たにノードを生成する。
先の入力インスタンスに対して要素を属性に変換する以下の2つのフィールド定義の例を考えてみます。
A
Root Element 注文伝票 Element(Repeat=True) 注文番号 Attribute 商品 Element(Repeat=True) 商品名 Attribute 金額 Attribute
B
Root Element 注文伝票 Element(Repeat=True) 注文番号 Attribute 商品 Element 商品名 Attribute 金額 Attribute
AとBのフィールド定義の違いは商品要素が繰り返し出現するか否かだけです。 先に結果を示すとA,Bそれぞれの結果は以下のようになります。
A
<root> <注文伝票 注文番号="1111"> <商品 商品名="携帯型CDプレーヤ" 金額="1000"/> <商品 商品名="ラジカセ" 金額="2000"/> </注文伝票> <注文伝票 注文番号="2222"> <商品 商品名="ビデオカメラ" 金額="3000"/> <商品 商品名="デジカメ" 金額="4000"/> <商品 商品名="スキャナー" 金額="5000"/> </注文伝票> </root>
B
<root> <注文伝票 注文番号="1111"> <商品 商品名="携帯型CDプレーヤ" 金額="1000"/> </注文伝票> <注文伝票 注文番号="1111"> <商品 商品名="ラジカセ" 金額="2000"/> </注文伝票> <注文伝票 注文番号="2222"> <商品 商品名="ビデオカメラ" 金額="3000"/> </注文伝票> <注文伝票 注文番号="2222"> <商品 商品名="デジカメ" 金額="4000"/> </注文伝票> <注文伝票 注文番号="2222"> <商品 商品名="スキャナー" 金額="5000"/> </注文伝票> </root>
A、Bいずれの場合でも最初の1レコード目がマッピングされた時点での結果は同じで、そのインスタンスは以下のようになっています。
<root> <注文伝票 注文番号="1111"> <商品 商品名="携帯型CDプレーヤ" 金額="1000"/> </注文伝票> </root>
ここに対して、2レコード目、
1111,ラジカセ,2000
を差し込む場合の処理が、それぞれ以下のようになります。
Aの場合
Bの場合
繰り返し可能なノードの階層構造が深くなった場合や並列に存在するような複雑なXMLの生成にも、上記の処理が繰り返すことで対応可能です。
特殊なNamespace
出力XMLのフィールド定義中に「http://www.infoteria.com/asteria/mapper/void」というNamespaceに属するAttributeがある場合、そのAttributeは出力されるXMLのインスタンスには含まれなくなります。 そのフィールドへの値のマッピング自体は行われるので、これを利用して(出力内容としては)構成要素の同じノードを別ノードのとして出力することができます。
例として、1フィールドで同一の値が5行繰り返される以下のようなCSVをXMLにマッピングする場合を考えます。
11111 11111 11111 11111 11111
このCSVを以下のようなXMLのフィールド定義に対してマッピングしたとします。
Root Element Field1 Element(Repeat=True) ←ここにCSVのフィールドをマッピング
出力結果は先の説明に従い、
<Root> <Field1>11111</Field1> </Root>
のようになります。5回のレコード処理でField1の内容が全て同じになるので、それらは全て同一ノードにまとめられます。
次に出力のフィールド定義とマッピングを以下のように変更してみます。
Root Element Field1 Element(Repeat=True) ※1 recNo Attribute ※2
※1 ここにCSVのフィールドをマッピング
※2 ここにRecordNoをマッピング
結果は以下のようになります。
<Root> <Field1 recNo="0">11111</Field1> <Field1 recNo="1">11111</Field1> <Field1 recNo="2">11111</Field1> <Field1 recNo="3">11111</Field1> <Field1 recNo="4">11111</Field1> </Root>
レコード処理ごとにrecNo属性の値が異なるので、各フィールドはまとめられません。
最後にNamespace定義として「x=http://www.infoteria.com/asteria/mapper/void」を追加して、出力のフィールド定義を以下のように変更します。
Root Element Field1 Element(Repeat=True) ※1 x:recNo Attribute ※2
※1 ここにCSVのフィールドをマッピング
※2 ここにRecordNoをマッピング
内部的なマッパーの動作としては先の場合と全く同じですが、
「http://www.infoteria.com/asteria/mapper/void」に属する属性である「x:recNo」は出力されなくなるので、結果は以下のようになります。
<Root> <Field1>11111</Field1> <Field1>11111</Field1> <Field1>11111</Field1> <Field1>11111</Field1> <Field1>11111</Field1> </Root>