フローサービスでは独自のマッパー関数をJavaで開発し追加することが可能になっています。
マッパー関数開発を行う場合、以下の作業が必要になります。
jarファイルの作成に関しては実際にはJavaInterpreter関数付属のSDKウィザードでほぼ自動化されています。
ここではFunctionクラスのソースコードの書き方に絞って説明します。
定義ファイルの作成に関しては定義ファイルリファレンスを、
jarファイルの作成とそのインストールに関してはツールガイドを参照してください。
マッパー関数の開発はJDK5.0以降の環境で行ってください。
また、「DESIGNER_HOME/lib」にある以下のjarファイルにクラスパスを通す必要があります。
実際にはウィザードで生成されるANT用のbuild.xmlでは「DESIGNER_HOME/lib/**.*.jar」にクラスパスが通っています。
作成するプログラムの内容によってはさらに別のjarファイルがコンパイル/実行に必要になる場合があるので、通常はbuild.xmlの設定を変更する必要はありません。
Valueとはフローサービスの基本データ型をラップするバリアント型の変数クラスのことです。
このクラスを使用することで変数の値をStringとして取り出したり、intとして取り出したりということが簡単にできます。
マッパー関数では入力されたフィールドの値がValueの配列として取得されます。
メソッドがMapperExceptionをthrowした場合はMapperコンポーネントのExceptionとしてフローのExceptionフレームワークに処理されます。
以下にexecuteメソッドの実装例を何パターンか示します。
//入力2つの文字列を結合する
public void execute(ExecuteContext context, Value[] in, Value out) throws MapperException {
out.setValue(in[0].strValue() + in[1].strValue());
}
//入力2つを整数として足す
public void execute(ExecuteContext context, Value[] in, Value out) throws MapperException {
out.setValue(in[0].longValue() + in[1].longValue());
}
//入力2つの文字列を結合する
public void execute(ExecuteContext context, Value[] in, Value out) throws MapperException {
out.setValue(in[0].strValue() + in[1].strValue());
}
ex7. Exceptionの使用
//入力文字列がLengthプロパティ値よりも長い場合はExceptionにする
public void execute(ExecuteContext context, Value[] in, Value out) throws MapperException {
int len = (int)getPropertyInteger("Length");
if (in[0].strValue().length() >= len)
throw new MapperException("入力が長すぎます。");
else
out.setValue(in[0]);
}
マッパー関数名(getFunctionNameメソッドの返り値)には「<会社名>.」というプレフィクスをつけてください。
Infoteria以外の会社が「.」を含まない名前を関数名に使用することは禁止事項とします。
以下のメソッドは必要に応じてオーバーライドします。
getMinInputCount()/getMaxInputCount()以外のメソッドはほとんどの場合実装する必要はありませんが、
処理を行うタイミングをコントロールすることでパフォーマンスが向上する可能性があります。
マッパー関数もコンポーネントと同じく、フローのリクエスト時にcloneメソッドによって複製が作られますが、その実装は
コンポーネントとは異なり、Object#cloneメソッドにより実装されています。
つまりpostCompileメソッド内でインスタンス変数に設定したObjectは複製時にポインタがコピーされます。
プロパティの登録はinternalInitメソッド内でregistPropertyメソッドを呼び出すことによって行います。
private static final String PROPERTY_DATA = "Data";
private static final String PROPERTY_ENABLE_METACHARACTER = "EnableMetaCharacter";
protected void internalInit() {
registProperty(PROPERTY_DATA, Value.TYPE_STRING, false);
registProperty(PROPERTY_ENABLE_METACHARACTER, Value.TYPE_BOOLEAN, false);
}
プロパティ値を取得するにはgetPropertyメソッドを使用します。
あるいはgetPropertyXXXXメソッドを使用することでValueオブジェクトとしてではなく、プリミティブ型として取得することもできます。
マッパー関数のプロパティには「入力がn本以上ある場合にはプロパティの設定値の代わりにm番目の入力値を使用する」という仕様のものがありますが、このためのメソッドも標準で提供されています。
この場合はgetPropertyまたはgetPropertyXXXXメソッドの第2引数に入力値の配列(executeメソッドの引数 in)を、第3引数に何番目の値がプロパティを置換するのかを指定します。
//Dataプロパティの内容をValueとして取得
Value v = getProperty("Data");
//入力値の配列(executeメソッドの引数 in)が2つ以上あればその2番目を、
//それがない場合はCountプロパティの値をintとして取得
int count = (int)getPropertyInteger("Count", in, 1);
MultiOutputFunctionとは出力が複数あるマッパー関数のことです。
出力がひとつだけの通常のマッパー関数とは次の点が異なります。
setSubValueCountメソッドはマッパー関数の出力数を設定するメソッドです。
通常はコンストラクタの中で実行して出力数を設定します。
引数となる数字には2番目以降のサブ出力の数を設定することに注意してください。
つまり全部で4つの出力があるマッパー関数を作成する場合、設定する値は3です。
同様にgetSubValueメソッドの引数も2番目の出力以降のインデックスとなっています。
つまりgetSubValue(0)は全体で2番目の出力値です。
//出力が4つあるマッパー関数
public class FourOutputFunction extends MultiOutputFunction {
public FourOutputFunction() {
setSubValueCount(3);
}
public void execute(ExecuteContext context, Value[] in, Value out) {
out.setValue("a");
getSubValue(0).setValue("b");
getSubValue(1).setValue("c");
getSubValue(2).setValue("d");
}
}
JavaInterpreterのようにプロパティ値によって動的に出力数の変わるマッパー関数ではコンストラクタでbDynamicをtrueにした上で postCompileメソッドで出力数を設定します。
//JavaInterpreter(抜粋)
public class JavaInterpreter extends MultiOutputFunction
{
private static final String PROPERTY_COUNT = "Count";
public JavaInterpreter() {
super(true);
}
protected void postCompile(AbstractCompiler compiler) {
int count = (int)getPropertyInteger(PROPERTY_COUNT);
if (count > 1)
setSubValueCount(count);
}
...
}
MultiOutputFunctionではメインの出力とサブ出力の複数の出力コネクタが画面に表示されるわけですが、そのうちのどれかひとつのコネクタに対してリンクがあればその関数は実行されます。
例えばDateSplit関数で曜日(4番目の出力コネクタ)にのみリンク線を繋いで、残りのコネクタは空であっても何の問題もありません。
このことをさらに進めて考えると「空のコネクタは画面に表示されていなくても良い」ということになります。
DateSplit関数もプロパティ値によって動的に出力数が変わる関数ですが、こちらはJavaInterpterとは違いコンストラクタ内で静的に出力数を設定しています。(サンプル参照)
つまり実際にはDateSplit関数の出力は常に8つあるわけですが、定義ファイルの設定で画面に4つしか見えてないことがあるということです。
もちろんJavaInterpreterのように動的にコネクタ数の増減する関数として作成することもできますが、そこは好みの問題でありどちらを選択した場合でもほとんど差はありません。
サンプルとして標準で提供されているマッパー関数のいくつかのソースを公開します。