本項では、XMLデータ仕様記述での項目仕様の記述方法を説明します。項目仕様は、XMLデータ仕様記述のsectionタグ内に記述します。
XMLデータ仕様記述の例
<?xml version="1.0" encoding="Shift_JIS" ?> <eSpec xmlns=http://interstage.fujitsu.com/schemas/uji/eSpec xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://interstage.fujitsu.com/schemas/uji/eSpec http://interstage.fujitsu.com/schemas/uji/espec.xsd"> <config> <version>6.0</version> </config> <specification name="sampleCheck" > <section name="sect1" > <verify property="sampleNumber" op="GE" operand="#0" exception="#ERR01" info="#0以上" /> <verify property="sampleNumber" op="LE" operand="#10" exception="#ERR01" info="#10以下" /> </section> </specification> </eSpec>
上記の例では、sectionタグ内に2つのverifyタグがあり、それぞれがプロパティsampleNumberに対する項目仕様となっています。
項目の値をチェックする
項目の値をチェックするためには、verifyタグを利用します。
<verify property="sampleNumber" op="GE" operand="#0" exception="#ERR01" info="#0以上" />
property
データBeanのプロパティ名を指定します。
op
判定のための関係演算を指定します。GT(より大)、GE(以上)、LT(より小)、LE(以下)、EQ(等しい)、NE(等しくない)を指定します。
operand
演算対象を指定します。定数の場合は、先頭に#を記述します。%nullや%emptyなどの予約オブジェクトを利用することもできます。
exception
エラーコードを記述します。文字列定数の場合は、先頭に#を記述します。exceptionアトリビュートを記述した場合は、エラーを検出した時点でESpecResultExceptionがスローされます。
info
エラーの補足情報を記述します。文字列定数の場合は、先頭に#を記述します。
property(プロパティ)、op(関係演算)、operand(演算対象)は、プロパティと演算対象を比較するという条件式を表します。
verifyタグでは、この条件式が正常条件を表すように、項目仕様を記述します。上述の例では、プロパティsampleNumberの値が0以上が正常条件であり、値が0未満で比較結果が偽となる場合にエラーとして例外を発生します。
演算はプロパティの型によって行われます。例えば演算対象に"#0"と記述した場合、プロパティの型がStringなら文字列の"0"として、プロパティがintなら整数の0として演算が行われます。同様に演算対象に"#true"と記述した場合、boolean型のプロパティと比較する場合はboolean値のtrueとして演算が行われます。
演算対象に別の項目の値を指定することができます。propertyアトリビュートと同様にoperandアトリビュートにプロパティ名を記述します。同様に、infoやexceptionなどのアトリビュートにもプロパティ名が記述できます。
階層のあるデータBeanを利用する場合には、プロパティ名に"xyz/abc"のような"/"で区切った階層表記ができます。HashMapの場合も同様に階層表記として処理されます。XMLデータBeanの場合はXPathになります。
文字列定数中、XMLで予約された文字列は、エンティティ記述にする必要があります(例"<"→"<")。また、カンマ(",")は",,"(カンマ2個)と記述します。
複数項目のエラーを同時にチェックする
errorアトリビュートを利用することで、複数項目のチェックを行うことができます。exceptionアトリビュートを用いた場合は、チェックがエラーになった場合にすぐ例外を発生しますが、errorアトリビュートは継続してチェックを行います。
<verify property="sampleNumber" op="GE" operand="#0" error="#ERR01" info="#0以上" />
error
エラーコードを記述します。文字列定数の場合は、先頭に#を記述します。errorアトリビュートを記述した場合は、エラー情報は蓄積されるのみで、継続してXMLデータ仕様記述を実行します。
exceptionアトリビュートを記述した場合は、チェックの結果がエラーになった時に、すぐにエラー情報をESpecResultExpceptionとしてスローします。一方、errorアトリビュートを記述した場合は、チェックの結果がエラーになった場合にもその情報を蓄積するのみで、XMLデータ仕様記述の処理を継続します。
specificationで指定された一組の項目仕様の実行が終了した時点で、errorアトリビュートで蓄積されたエラー情報があれば、ESpecResultExpceptionがスローされます。発生したエラーの一覧は、ESpecResultExpceptionのgetErrorInfoメソッドにより、ESpecResultExceptionオブジェクトの集合(java.util.Vector)として取得することができます。
exceptionアトリビュートを持つタグのチェックによってESpecResultExpceptionがスローされた場合に、errorアトリビュートで蓄積されたエラー情報があれば、例外オブジェクトに添付されます。ESpecResultExpceptionのgetErrorInfoメソッドで取得できます。
ビルトインメソッドを利用して項目をチェックする
項目値のチェックを支援するために、文字列長、文字パターンなどをチェックするビルトインメソッドが準備されています。
<verify property="numberString" function="pattern([0-9]+)" op="EQ" operand="#true" error="#ERR02" info="#数値チェック" /> <verify function="errorcount" op="EQ" operand="#0" exception="#ERR99" info="#例外あり" />
function
適用するメソッドを指定します。
ビルトインメソッドは、関係演算の前にプロパティ値を変換する動作をします。例の1行目では、プロパティnumberStringの値に対してメソッド"pattern([0-9]+)"を実行し、その結果を演算対象(operandのtrue)と比較(op="EQ")します。
ビルトインメソッドには、以下のものがあります。
形式 | 動作 |
---|---|
int, long, double, boolean, String | 指定の型に変換します。 |
stringLength | 文字列長を返します。 |
enum(n,m,…) | 列挙された値n,m,…のいずれかに一致するかどうか判定します。 |
pattern(re) | 正規表現に一致するかどうか判定します。 |
errorcount | errorアトリビュートによって蓄積されているエラー情報の数を返します。このメソッドはプロパティ値を無視します(propertyアトリビュートを省略可能です)。 |
ポイント
ビルトインメソッドstringLengthでの補助文字の数え方を初期化パラメタuji.espec.awareOfSupplementaryCharで設定できます。詳細は“13.2 初期化パラメタ”を参照してください。
注意
ビルトインメソッドpatternについては以下の注意事項があります。
正規表現中に補助文字を含めることはできません。
文字列を正規表現とマッチさせる際、文字列中に補助文字が含まれている場合は、その補助文字は1文字としては扱われず2文字として扱われます。
利用者定義メソッドで項目をチェックする
項目値のチェックや変換に、利用者定義メソッドを利用することができます。利用者定義メソッドには、static形式と継承形式があります。
<verify property="prop" function="?mypackage.MyClass.myCheck" op="EQ" operand="#true" error="#ERR11" info="#myCheck" /> <verify property="prop1,prop2,prop3,#1" function="?localCheck" op="EQ" operand="#0" error="#ERR12" info="#localCheck" />
function
利用者定義メソッドを指定する場合は、メソッド名の先頭に"?"を付加した文字列を指定します。
static形式の利用者定義メソッドを利用する場合は、functionアトリビュートに"?パッケージ名.クラス名.メソッド名"を記述します。メソッドは、任意のクラスのstaticメソッドとして実装します。
継承形式の利用者定義メソッドを利用する場合は、functionアトリビュートに"?メソッド名"を記述します。メソッドは、ESpecValidatorクラスを継承したサブクラス内に実装します。ESpecValidatorクラスの代わりに、作成したサブクラスのインスタンスで、validateメソッドを実行します。
propertyアトリビュートで指定したプロパティの値が利用者定義メソッドの引数となります。カンマ(",")で区切ってプロパティを複数記述することで、複数の値を引数とできます。また、プロパティ値と定数が混在することもできます。引数の数が不定の場合は、Object[]型の引数とします。
利用者定義メソッドからは、任意の型やオブジェクトを返却できます。
以下は利用者定義メソッドの記述例です。
package mypackage; public class MyClass { public static boolean myCheck(String prop) { .... return true; } }
import com.fujitsu.uji.xscript.ESpecValidator; public class CheckClass extends ESpecValidator { public CheckClass() {} public int localCheck(String prop1, int prop2, String prop3, int param) { // int localCheck(Object[] props) でも可 .... return 0; } }
データ項目に値を代入する
データ項目に値を代入する場合は、termタグを利用します。
<!-- sample1を無条件にtargetProp1に代入 --> <term property="sample1" target="targetProp1" /> <!-- sample2の文字列長が0の場合に文字列"none"をtargetProp2に代入 --> <term property="sample2" function="stringLength" op="EQ" operand="#0" value="#none" target="targetProp2" /> <!-- sample3に1を足してtargetProp3に代入 --> <term property="sample3" op="ADD" operand="#1" target="targetProp3" /> <!-- sample4にmyFormatを適用した結果をtargetProp4に代入 --> <term property="sample4" valueFunction="?myFormat" target="targetProp4" />
property
データBeanのプロパティ名を指定します。
target
代入先のデータBeanのプロパティ名を指定します。
value
代入する値が演算結果と異なる場合、valueアトリビュートで指定します。
op(関係演算)
opアトリビュートに関係演算を指定した場合は、関係演算の結果が真の場合にのみ代入が実行されます。
op(算術演算)
ADD(加算)、SUB(減算)、MUL(乗算)、DIV(除算)、REM(剰余)をopアトリビュートに指定することで、operandとの演算結果をtargetに設定します。算術演算の場合はvalueアトリビュートは記述せず、演算結果が代入対象となります。
valueFunction
valueFunctionで指定した利用者定義メソッドで変換などの操作を行った結果をtargetに設定します。利用者定義メソッドの指定方法は、functionアトリビュートと同じです。
ESpecValidatorクラスのvalidateメソッドを呼ぶ時に、データBeanを2つ(bean, targetBean)指定する形式のメソッドを利用した場合は、targetBeanに指定したデータBeanにデータが書き込まれます。データBeanを1つ指定する形式のメソッドでは、同じデータBeanに書き戻されます。
validator.validate("spec1", bean); // beanの内容に従ってbean自体を更新します validator.validate("spec2", bean, targetBean); // beanの内容に従ってtargetBeanを更新します
処理の中間結果を一時的に保持する
targetやpropertyで、中間変数を指定することができます。変数名の先頭に"^"を付加して指定します。
<term property="sampleValue" op="ADD" operand="#1" target="^tempValue" /> <term property="^tempValue" op="DIV" operand="#4" target="targetProp" />
中間変数には、"/"で区切った階層表記は利用できません。