Velocity - Velocityを使った差込み変換

Velocityテンプレートを用いてデータの変換を行います。
Velocityについての詳細はhttps://velocity.apache.org/を参照してください。

■ストリーム情報

入力フォーマットすべて
接続数無制限
説明 複数のストリームを直接差し込むことができます。
入力したストリームは$in.arrayメソッドを使用してアクセスします。
出力フォーマットText,XML,CSV,HTML,JSON

■コンポーネントプロパティ

名前プロパティ型マッピング説明
テンプレートの指定方法choice- Velocityテンプレートをファイルで指定するか直接入力するかを指定します。
選択された指定方法によって使用する以下のプロパティが異なります。指定方法を選択すると、プロパティの表示が切り替わります。
ファイル [File] - 外部ファイルから読み込みます。
直接入力 [Inline] - テンプレートの内容 から直接読み込みます。
テンプレートの内容string入力&出力テンプレートの指定方法 が「直接入力」の場合にVelocityテンプレートを直接入力します。
ファイルパスremoteFile入力&出力テンプレートの指定方法 が「ファイル」の場合にVelocityテンプレートのパスを指定します。
テンプレートパスには絶対パスを指定することはできません。
ファイルパスの起点pathResolver-テンプレートの指定方法 が「ファイル」の場合にテンプレートファイルパスのベースフォルダーを指定します。
プロジェクトフォルダー [Relative] - プロジェクトファイルと同じフォルダーを起点にします。
ホームフォルダー [ProjectOwner] - ユーザーのホームフォルダーを起点にします。
ファイルのエンコーディングchoice入力&出力テンプレートの指定方法 が「ファイル」の場合にVelocityテンプレートファイルのエンコーディングを指定します。
XPath式のプレフィックスstring入力&出力 XPath式の中で変数を使う場合のプレフィクスを指定します。
ローカル変数category入力&出力 コンポーネント内でのみ有効な変数を定義します。
Velocityテンプレート内では$localとして参照できます。
拡張クラスcategory入力&出力 テンプレートで使用するjavaクラスを追加します。
例えばVelocityToolsのDateToolを使用する場合には定義名に「date」、Javaクラスに「org.apache.velocity.tools.generic.DateTool」を指定すれば、Velocityテンプレート内では$dateとして参照できます。指定するクラスには引数を取らないコンストラクタが必要です。

外部ライブラリを使用する場合、そのjarファイルは[INSTALL_DIR]/flow/lib/userlibに配置してください。
(VelocityToolsを使用する場合も同じ場所にjarファイルをコピーする必要があります。)

■ループ処理

なし。

■トランザクション処理

コミット何もしません。
ロールバック何もしません。

■エラー処理

タイプパラメーターエラー処理フロー
へのストリーム
エラー
コード
説明
汎用 なし コンポーネントの入力ストリーム なし テンプレートファイルが見つからなかった場合
文法エラーなどテンプレート処理でエラーが発生した場合
1拡張クラスJavaクラスに指定したクラスが見つからなかった場合
2拡張クラスJavaクラスに指定したクラスのインスタンス化に失敗した場合

■テンプレートの編集画面

コンポーネントをダブルクリックするか、右クリックメニューの「テンプレートの編集」を実行することでテンプレートの編集画面が開きます。
この画面ではテンプレート内容やローカル変数、入力ストリーム定義などの設定をまとめて行うことができます。
また、テンプレートをあらかじめ保存してある一覧から読み込んだり、テストデータを使用してのプレビューを表示することも可能です。

「テンプレート」テキストボックス

テンプレート内容を記述します。
テンプレート内容はテンプレートの指定方法 が「直接入力」の場合は テンプレートの内容 に、「改行コード」に指定した改行コードで保存され、「ファイル」の場合は指定のファイルに、「改行コード」に指定した改行コードで保存されます。

「ローカル変数」タブ

インスペクタのローカル変数 をここでも設定することができます。

「入力ストリーム」タブ

直前に接続されているコンポーネントのストリーム定義をここでも設定することができます。
ストリーム型は変更することができません。また、直前に接続されているコンポーネントがない場合や、そのストリーム型がAnyの場合はこのタブは表示されません。

「テストデータ」タブ

プレビューで使用するテストデータを指定することができます。
入力ストリームがRecord、CSV、FixedLengthまたはParameterListの場合はテストデータはCSV形式で指定してください。XMLやJSONやTextの場合はそのままテキスト形式で指定してください。

入力ストリーム定義がない場合はこのタブは表示されません。また、テストデータの内容は保存されないため一度プロジェクトを閉じて再度開いた場合には空になります。

「一覧から読み込み」「一覧に保存」ボタン

テンプレート内容、ローカル変数、入力ストリームのフィールド定義、テストデータをセットにして名前をつけて保存しておくことができます。一度保存したデータはいつでも「一覧から読み込み」ボタンで読み込むことができます。

「プレビュー」ボタン

テンプレート内容とテストデータを使用して、結果のプレビューを表示します。プレビューファイルはクライアント環境で作成してファイルにするため、以下の制限があります。

■テンプレートで使用可能なオブジェクト

値(Value)

変数やレコードのフィールド値は値オブジェクトとなります。
値オブジェクトには以下のメソッドが実装されています。

メソッド名引数返り値の型説明
strValue()なしStringString型としての値。
intValue()なしintInteger型としての値。
longValue()なしlongInteger型としての値。
doubleValue()なしdoubleDouble型としての値。
decimalValue()なしBigDecimalDecimal型としての値。
dateValue()なしDateDateTime型としての値。
booleanValue()なしbooleanBoolean型としての値。
byteValue()なしbyte[]Binary型としての値。
isNull()なしboolean値がnullの場合にTrueを返します。

値オブジェクト自体はstrValue()と同じ値を返します。

変数

フローの各変数とコンポーネントで定義されたローカル変数はそれぞれ変数オブジェクトとして参照可能です。
以下のリファレンス表記で変数を参照することができます。

変数の種類リファレンス表記
フロー変数$flow.<フロー変数名>
外部変数セット$exvar.<外部変数セット名>.<変数名>
システム変数$system.<システム変数名>(英語名)
ローカル変数$local.<ローカル変数名>

変数オブジェクトには以下のメソッドが実装されています。

メソッド引数返り値の型説明
get()String (変数名)Value変数名に対応する値が返ります。
「$flow.var1」のように変数名を直接記述する記法も有効です。

変数オブジェクト自体は変数の一覧を返します。
つまりテンプレート中に「$system」とのみ記述した場合、システム変数の一覧が出力されます。

未定義の変数を参照する場合に $flow.var1 と記述しておくと参照されずにそのまま出力されます。 この場合に参照を $!{flow.var1} と記述しておくことで変数が参照できない場合には $flow.var1 と出力されるかわりに空白文字列を出力することが可能です。

サンプル
フロー変数「var1」の値は「$flow.get("var1")」です。
getを省略して「$flow.var1」と記述することもできます。
また、「${flow.var1}」のように波括弧で括ることもできますので、直後に "." が続くような記述が必要な場合、
例えば、「${flow.var1}.csv」のような場合はこちらを使用してください。

#if ($flow.var2.intValue() == 1)
     フロー変数「var2」の値が1の場合だけこの文字が出力されます。
#end

#if ($exvar.exvar1.var3.strValue() == "abc")
    ifの中で文字列や数値と比較を行う場合はstrValue()やintValue()を用いて比較するオブジェクト
    の型をそろえる必要があります。
    「$exvar.exvar1.var3 == "abc"」と記述しても比較する型が異なるため、結果がtrueになること
    はありません。
#end

ストリーム配列($in)

コンポーネントに入力されたストリームはすべて$inに格納されます。
arrayメソッドを用いて各ストリームにアクセスすることができます。
このオブジェクトではCollectionとなっているのでforeachを用いて各ストリームにアクセスすることもできます。

メソッド名引数返り値の型説明
array()intStreamインデックスを指定して入力ストリームを取得します。
array()StringStreamコンポーネント名、またはリンク名を指定して入力ストリームを取得します。
size()なしint配列中に含まれるストリームの数。

$in自体はすべてのストリームの情報を文字列化した値を返します。
$inは自身のメソッドではないメソッドが使用された場合、array(0)に対してフォワードします。
つまり「$in.array(0).〜」という書式と「$in.〜」は同じ意味です。

ストリーム(Stream)

入力ストリームオブジェクトです。XMLとJSON以外のストリームはすべてこのオブジェクトとなります。
recordメソッドを用いてストリーム内の各レコードにアクセスすることができます。

メソッド名引数返り値の型説明
recordsなしCollectionRecordにアクセスするためのCollectionを返します。
record()intRecordインデックスを指定してレコードを取得します。
text()なしStringストリームの文字列値。
size()なしintストリーム中に含まれるレコードの数。
variable()StringValueストリーム変数を返します。
variablenames()なしIteratorストリーム変数名の反復子を返します

Stream自体はtext()と同じ値を返します。
Streamは自身のメソッドではないメソッドが使用された場合、record(0)に対してフォワードします。
つまり「$in.array(0).record(0).〜」という書式と「$in.array(0).〜」は同じ意味です。
これらの省略記法は入力ストリームがParameterList 1つの場合に「$in.field1」のように書けるので便利です。

ストリーム変数を取得する場合は下のように記述します。

$in.variable("FilePath")

#set ($data = $in.array(2))
$data.variable("FilePath")

レコード(Record)

レコードオブジェクトです。
fieldメソッドを用いてレコード中の各フィールド値にアクセスすることができます。
このオブジェクトではCollectionとなっているのでforeachを用いて各フィールド値にアクセスすることもできます。

メソッド名引数返り値の型説明
fieldsなしCollection各フィールド値(Value)にアクセスするためのCollectionを返します。
field()intValueインデックスを指定してフィールド値を取得します。
field()StringValueフィールド名を指定してフィールド値を取得します。
「field("field1")」と書く変わりに直接「field1」とする指定も可能です。
name()intStringインデックスを指定してフィールド名を取得します。
getNo()なしintレコードの行番号(0ベース)を取得します。
size()なしintレコード中に含まれるフィールド数。

Record自体は各フィールド名とフィールド値をすべて文字列化した値を返します。

サンプル
---
$in.text()
---
$in.array(0).text()
---
$in.array("FileGet1")
---
入力ストリームが「FileGet1」コンポーネント1つだけの場合は上の3つの出力はすべて同じになります。


#foreach ($data in $in)
    #foreach ($r in $data.records)
        $r.name(0) = $r.field(0)
        $r.name(1) = $r.field("Field2")
        $r.name(2) = $r.Field3
    #end
#end
---
入力ストリームが複数ある場合は上のようにすべてのストリーム、すべてのレコードにアクセスする
ことができます。
入力ストリームが1つだけであるなら「#foreach ($r in $in.records)」でもOKです。

XMLストリーム

ストリームがXMLの場合、それはXMLストリームとなります。
XMLストリームでは通常のストリームのメソッドに加えて「doc」というメソッドでXMLのDocumentに対してJDOMオブジェクトとしてアクセスすることができます。
JDOMについてはhttp://www.jdom.org/を参照してください。

メソッド名引数返り値の型説明
docなしorg.jdom.DocumentJDOMのドキュメントオブジェクト。
サンプル
$in.doc.rootElement.getChild("record").getChild("field").text
文書要素の最初の子要素「record」の最初の子要素「field」の値を表示します。


#foreach ($r in $in.doc.rootElement.getChildren("record"))
  $r.getChild("field").text
#end
record要素が複数ある場合、foreachでループを回すこともできます。


ネームスペースが使用されている場合はNamespaceを第2引数とするメソッドを使用します。
#set ($ns = $in.doc.rootElement.namespace )
#foreach ($r in $in.doc.rootElement.getChildren("record", $ns))
  $r.getChild("field", $ns).text
#end
record要素とfield要素のネームスペースが文書要素と同じであれば上のようにして値を取得できます。

XPath($xpath)

XMLストリームに対してXPathを適用するためのユーティリティクラスです。

メソッド名引数返り値の型説明
createXPath()StringXPathXPath式を引数としてXPathオブジェクトを作成します。作成されるのはJAXENのXPathクラスです。
booleanValueOf()String, ObjectbooleancreateXPath(expr).booleanValueOf(object)と同じです。
numberValueOf()String, ObjectNumbercreateXPath(expr).numberValueOf(object)と同じです。
selectNodes()String, ObjectListcreateXPath(expr).selectNodes(object)と同じです。
selectSingleNode()String, ObjectObjectcreateXPath(expr).selectSingleNode(object)と同じです。
stringValueOf()String, ObjectStringcreateXPath(expr).stringValueOf(object)と同じです。
valueOf()String, ObjectObjectcreateXPath(expr).valueOf(object)と同じです。

XPath式の中での名前空間定義は入力XMLストリームの名前空間定義に従います。

XPath式の中で変数を参照する場合は「/root/field1[@name=$fv:flow.var1]」のように変数にXPath式のプレフィックスプロパティで指定したプレフィクスをつけて参照します。
「$flow.var1」のようにプレフィクスなしで使用した場合、式がXPathクラスに解釈される前にVelocityによって変換されます。

サンプル
$xpath.stringValueOf("/root/record[1]/field[1]", $in.doc)
root要素直下の最初record要素の最初のfield要素の値を取得します。

$xpath.booleanValueOf("count(/root/record)=5", $in.doc)
root要素直下のrecord要素の数が5つの場合、trueが返ります。

#foreach ($r in $xpath.selectNodes("/root/record", $in.doc))
    $r.getChild("field").text
#end
selectNodesではListが返るのでforeachで使用することができます。

$xpath.stringValueOf("/root/record[@name='$flow.var1']/field", $in.doc)
上記の「$flow.var1」はVelocityによって変換されてからXPathに渡されます。
変数をXPath内で処理したい場合は

$xpath.stringValueOf("/root/record[@name=$fv:flow.var1]/field", $in.doc)
のようにXPath式のプレフィックスプロパティで指定したPrefixを付けて指定します。
前者は変数を「''」で括っていて、後者は括っていない点に注意してください。

$xpath.stringValueOf("/ns:root/ns:record[1]/ns:field", $in.doc)
ネームスペースを使用したXPath。
NamespacePrefix「ns」は入力ストリームのフィールド定義で行われていなければなりません。

$xpath.stringValueOf("field[1]", $in.doc.rootElement.getChild("record"))
第2引数に任意のNodeを指定することによりそこをコンテキストとしたXPathを使用することができます。

#set ($expr = $xpath.createXPath("field[1]"))
#foreach ($r in $in.rootDocument.getChildren("record"))
    $expr.stringValueOf($r)
#end
createXPathで作成したXPathオブジェクトをループの中で使いまわすことができます。
ループ中の「$expr.stringValueOf($r)」は「$xpath.stringValueOf("field[1]", $r)」と同じですが、
XPathオブジェクトの作成を毎回行わない分高速です。

JSONストリーム

JSONストリームでは通常のストリームのメソッドに加えて、JsonPathを使用してJSONストリームから値を取得することができます。JsonPathはJsonPath仕様(正確にはそのJava実装)に準拠しています。

メソッド名引数戻り値の型説明
jsonpathなしcom.jayway.jsonpath.DocumentContextJsonPathのオブジェクト

JsonPath(jsonpath)

JsonPathを使用するためのオブジェクトです。
readメソッドを用いてJsonPath式でストリーム内のJSON文字列にアクセスすることができます。

メソッド名引数戻り値の型説明
readJsonPath式ObjectJsonPath式で評価された値

JSONストリームに、次のようなJSON文字列が格納されていたとします。

{
	"住所録": [
		{
			"番号": 1,
			"名前": {
				"姓": "佐藤",
				"名": "渚"
			}
		},
		{
			"番号": 2,
			"名前": {
				"姓": "鈴木",
				"名": "かおる"
			}
		}
	]
}
「鈴木」を取得するためには、次のように記述します。
$in.jsonpath.read("$.住所録[1].名前.姓")

システム($sys)

いくつかの汎用的な関数が$sysのメソッドとして提供されます。

メソッド名引数返り値の型説明
escape()ValueまたはStringString文字列中の「>」「<」「&」「"」をそれぞれ「&gt;」「&lt;」「&amp;」「&quot;」に変換します。
outputXML()org.jdom.DocumentStringJDOMドキュメントを文字列化します。
outputXML()org.jdom.Document, booleanStringJDOMドキュメントを文字列化します。第2引数はインデントの有無です。
outputXML()org.jdom.ElementStringJDOMエレメントを文字列化します。
outputXML()org.jdom.Element, booleanStringJDOMエレメントを文字列化します。第2引数はインデントの有無です。
strToInt()Stringint文字列をintに変換します。
strToDouble()Stringdouble文字列をdoubleに変換します。
getCurrentDate()なしDate現在の日時を返します。
formatDecimal()Valueまたは任意の数値型, StringString第1引数の数値を第2引数の書式で文字列化します。
formatDate()ValueまたはDate, StringString第1引数の日付を第2引数の書式で文字列化します。
regexpReplace()String, String, String, boolean, boolean, booleanString第1引数の文字列の中から第2引数の正規表現にマッチした部分を第3引数の文字列で置換します。第4引数は英大文字小文字の区別するかどうか、第5引数はマッチする文字列をすべて置換するかどうか、第6引数は第3引数の文字列でメタ文字(REGEXPREPLACE関数を参照)を使用できるかどうかをそれぞれ指定します。第4〜6引数は省略時でき、省略時の値はtrueとなります。

以前のバージョンにあったconvertDomToStringメソッドはインデントの有無を指定できるoutputXMLメソッドに置き換えられました。
convertDomToStringメソッドも従来同様使用できますが、今後はoutputXMLを使用するようにしてください。

サンプル
$sys.escape($in.text())
入力ストリーム全体をエスケープして出力します。

$sys.outputXML($in.doc, true)
入力のXMLをインデントして出力します。

$sys.outputXML($in.doc.rootElement.getChild("record"))
入力のXMLの最初のレコード要素以下を出力します。

$sys.formatDate($sys.getCurrentDate(), "yyyy/MM/dd")
現在日時をフォーマットして出力します。

#set ($num = 50000)
$num
$sys.formatDecimal($num, $local.FORMAT.strValue())
$sys.formatDecimal($flow.Num1, $local.FORMAT.strValue())
## Velocityでは「##」がコメント行の先頭文字として定義されているため「#,##0」のような
## 書式文字列を直接テンプレートに埋め込むことはできません。
## そのような書式を使用する場合はLocal変数を使用するなどの方法を用いてください。

$sys.regexpReplace($contents, "(s?https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)", '<a href="$1">$1</a>')
文字列中のURLにリンクを張るように置換します。(上記URLの正規表現は簡易的なものです)

出力エンコーディング($encoding)

出力ストリームのエンコーディングを出力します。
HTMLのcharsetを指定する場合などに使用してください。

■備考