カスタムバリデータ

前回に続きバリデータについて。

今のところ組み込みのバリデータは required,minlength,maxlength,min,max の5つしか無いようなので、正規表現にマッチするかどうか検証する pattern バリデータを作ってみます。

  1. org.apache.tapestry.Validator インターフェースを実装したクラスを作る
  2. AppModule クラスに contributeFieldValidatorSource メソッドを追加する
  3. バリデーションメッセージをメッセージカタログに追加する

org.apache.tapestry.Validator インターフェースを実装したクラスを作る

package org.example.myapp.validators;

import static org.apache.tapestry.TapestryUtils.quote;

import org.apache.tapestry.Field;
import org.apache.tapestry.MarkupWriter;
import org.apache.tapestry.PageRenderSupport;
import org.apache.tapestry.ValidationException;
import org.apache.tapestry.Validator;
import org.apache.tapestry.ioc.MessageFormatter;

public class Pattern implements Validator<String, String> {

    public Class<String> getConstraintType() {
        return String.class;
    }

    public String getMessageKey() {
        return "pattern";
    }

    public Class<String> getValueType() {
        return String.class;
    }

    public boolean invokeIfBlank() {
        return false;
    }

    public void render(
            Field              field,
            String             constraintValue,
            MessageFormatter   formatter,
            MarkupWriter       writer,
            PageRenderSupport  pageRenderSupport) {

        pageRenderSupport.addScript(
                "MyValidator.pattern('%s', %s, %s);",
                field.getClientId(),
                quote(constraintValue),
                quote(buildMessage(formatter, field)));
    }

    public void validate(
            Field             field,
            String            constraintValue,
            MessageFormatter  formatter,
            String            value) throws ValidationException {

        if (!value.matches(constraintValue)) {
            throw new ValidationException(buildMessage(formatter, field));
        }
    }

    private String buildMessage(MessageFormatter formatter, Field field) {
        return formatter.format(field.getLabel());
    }

}
  • getConstraintType メソッドは、@Validate アノテーションで指定する制約値の型を返します。@Validate("pattern=正規表現") としたいので、getConstraintType メソッドは String.class を返します。
  • getMessageKey メソッドはメッセージカタログのキーを返します。
  • getValueType メソッドはバリデーション対象となる値の型を返します。
  • invokeIfBlank メソッドは入力値が空のときもバリデーションを実行するかどうかの指定です。通常は false を返します。
  • render メソッドでクライアントサイドのJavaScriptバリデーションを出力します。
  • validate メソッドでサーバサイドのバリデーションを実行します。

AppModule クラスに contributeFieldValidatorSource メソッドを追加する

public static void contributeFieldValidatorSource(MappedConfiguration<String, Validator> configuration) {
    configuration.add("pattern", new Pattern());
}

これだけ。

バリデーションメッセージをメッセージカタログに追加する

前回と同じように ValidationMessages.properties, ValidationMessages_ja.properties に追加します。

pattern=Malformed %s format.
pattern=無効な書式の%sです。

これで準備ができました。

patternバリデータを使う

入力値のsetterメソッドのアノテーションを次のように書き換えます。なお、ここで指定した正規表現は@の位置とひとつだけ入ってるかチェックしてるだけなので、これだけでは実際のメールアドレスのバリデーションにはあまり役にたちませんが。

@Validate("required,pattern=^[^@]+@[^@]+$")
public void setEmailAddress(String emailAddress) {
    _emailAddress = emailAddress;
}

実行して、メールアドレスとして不適当な文字列を適当に入力してサブミットすると「無効な書式のEメールです。」と表示されます。Eメールの本文が無効、と指摘されてるようなメッセージになってるので、Start_ja.properties でメッセージ文を変更した方が良さそうです。これも前回書いた通り。

emailaddress-pattern=メールアドレスの書式が不適切です。



(違w


涼宮ハルヒの分裂 (角川スニーカー文庫)

涼宮ハルヒの分裂 (角川スニーカー文庫)