値の形式を調べなければならない項目はほかにもある。

今日取り上げるのは、発信ポートと宛先ポートだ。
これは両方同じ形式であり、全てのポートを示す 「*」、
または 0 から 65535 までの数値を取る。

少し複雑な条件だが、正規表現を使って無理やり書いてみよう。
正規表現さえ使えれば mask ルールを適用することができる。

(?:\*|6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}|[0-5]?\d{1,4})

長っ。…まあいいか。

さて、これを発信ポートと宛先ポートに指定するのだが、
これらは同じ条件なので、同じ内容の mask 変数になる。

上記正規表現を 2 箇所に書き加えても構わないのだが、
結構複雑な正規表現なので、記述ミス等の心配がある。
それに、この正規表現は、ポートを表す汎用表現なので、
ほかの所でも使う機会があるかもしれない。

こんな時に便利なのが、<constant> 要素だ。
<constant> を使うと、「定数」を定義することができ、
その値を別の場所で利用することができる。

では定数を定義してみよう。

========== /WEB-INF/validation.xml ==========
(…省略…)
<form-validation>
    <formset>
        <constant>
            <constant-name>FILTER_PORT</constant-name>
            <constant-value>
                (?:\*|6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}||[0-5]?\d{1,4})
            </constant-value>
        </constant>

        <form name="filterRuleForm">
(…省略…)
========== end of /WEB-INF/validation.xml ==========

これで、定数「FILTER_PORT」が定義された。

定数を使う場合、<formset> の子要素として追加する。
<constant> 要素自体はいくつでも並べることができるが、
順序が厳密に決められているため、
<form> 要素よりも前でなければならない。

<constant> の中身は一目瞭然だ。
<var> 要素の親戚のようなつくりである。
例によって、<constant-name> が先で、
<constant-value> が後という決まりがある。

<constant> 要素をこの位置に定義した場合、
この定数は、「ローカル定数」となり、
同じ <formset> 要素内の <form> 要素からのみ参照でき、
別の <formset> からは参照できない。

では、この定数を使って、
発信ポートと宛先ポートの検証条件を書いてみよう。

========== /WEB-INF/validation.xml ==========
(…省略…)
            <!-- 発信ポートは必須で * か 0-65535 -->
            <field property="rule.source.port"
                    depends="required,mask">

                <var>
                    <var-name>mask</var-name>
                    <var-value>^${FILTER_PORT}$</var-value>
                </var>

                <arg name="required" position="0"
                        key="property.FilterRule.source.port" />
                <arg name="mask" position="0"
                        key="property.FilterRule.source.port" />

            </field>

            <!-- 宛先ポートは必須で * か 0-65535 -->
            <field property="rule.destination.port"
                    depends="required,mask">

                <var>
                    <var-name>mask</var-name>
                    <var-value>^${FILTER_PORT}$</var-value>
                </var>

                <arg name="required" position="0"
                        key="property.FilterRule.destination.port" />
                <arg name="mask" position="0"
                        key="property.FilterRule.destination.port" />

            </field>
(…省略…)
========== end of /WEB-INF/validation.xml ==========

${定数名} と EL 式風に記述することで、
定数を部分的に展開することができる。

上記では、正規表現の記号が混ざって読みにくいが、
<var-value> の内容は、FILTER_PORT 定数の前後に、
^ と $ をつけた文字列となっている。

定数は、<field> の property 属性、<msg> の key 属性、
<var-value> 要素内で利用することができるので、
よく使う値があるなら、設定ファイルが少し読みやすくなる。

ちなみに、定数には「グローバル定数」もある。
<formset> の内側ではなく、<form-validation> 要素内の
さらに <global> 要素内に <constant> を書けば、
どこからでも参照できる定数として利用することができる。

グローバル定数は、ローカル定数の <constant-value> でも
参照することができるので、表現の幅は広がるが、
設定ファイルがややこしくなるので多用はしない方が良い。