値検証機能の定義を HTML ドキュメントとして出力する方法
Java の ValidatorExpression のコンストラクタツリーのルート要素を Visitor に作用させて HTML の文字列表現を得る。
final ValidatorExpression validatorExpression = (コンストラクタツリー);

final DomContext context = new DomContext();
TestUtils.getToNode("<HTML><BODY></BODY></HTML>").interpret(context);
final Visitor visitor = new Visitor();
visitor.setMap(DocValidatorConstants.MAP);
visitor.setContext(context.getNode().getFirstChild().getFirstChild());
visitor.visit(validatorExpression);
System.out.println("// ---- validator start ----");
UtilsConstants.TRANSFORMER_FACTORY.newInstance().transform(
    new DOMSource(context.getNode()),
    new StreamResult(new OutputStreamWriter(System.out))
);
System.out.println("// ---- validator end ----");

サンプルプログラムにおける出力例を以下に示す。
変換前のコンストラクタツリー
final NumberFormat numberFormat = new DecimalFormat();
// 値検証の定義。
final ValidatorExpression validatorExpression =
new DumpValidator(new SerialValidator(ValidatorConstants.ANDAND,
    // 受け入れ可能なプロパティ一覧の定義。id の数が多くなるとハッシュ実装のほうが検索効率がよいので HashSet としてプロパティ一覧を扱う。
    new IfNotValidator(
        new ValidNamesValidator(new HashSet<String>(Arrays.asList("userId", "name", "sex", "address", "age", "hobby", "comment"))),
        new MessageValidator("validator.acceptable")
    ),
    // 必須検証以外はアクション id をまたがってプロパティ名で値検証を行う。
    new BranchByNameIfExistsValidator(
        new SwitchBuilder<String,ValidatorExpression>()
        .put("userId", new ValueLoopValidator(
            new IfNotValidator(
                new ParseValidator(new ToIntegerFormat(numberFormat)),
                new MessageValidator("validator.userId.parse"))))
        .put("name", new ValueLoopValidator(
            new IfNotValidator(
                new MaxLengthValidator(40),
                new MessageValidator("validator.name.maxLength"))))
        .put("sex", new ValueLoopValidator(new SerialValidator(
            new IfNotValidator(
                new ValidValuesValidator(Arrays.asList("0", "1")),
                new MessageValidator("validator.sex.acceptable")),
            new IfNotValidator(
                new ParseValidator(new ToIntegerFormat(numberFormat)),
                new MessageValidator("validator.sex.parse")))))
        .put("address", new ValueLoopValidator(
            new IfNotValidator(
                new MaxLengthValidator(80),
                new MessageValidator("validator.address.maxLength"))))
        .put("age", new ValueLoopValidator(new SerialValidator(
            new IfNotValidator(
                new ParseValidator(new ToIntegerFormat(numberFormat)),
                new MessageValidator("validator.age.parse")),
            new IfNotValidator(
                new MinValidator(0),
                new MessageValidator("validator.age.min")),
            new IfNotValidator(
                new MaxValidator(200),
                new MessageValidator("validator.age.max")))))
        .put("hobby", new ValueLoopValidator(
            new IfNotValidator(
                new ValidValuesValidator(Arrays.asList("0", "1", "2", "3")),
                new MessageValidator("validator.hobby.acceptable"))))
        .put("comment", new ValueLoopValidator(
            new IfNotValidator(
                new MaxLengthValidator(200),
                new MessageValidator("validator.comment.maxLength"))))
        .get()),
    new IfValidator(
        new RegExpIdValidator("user_(deleteConfirm|updateInput)"),
        new BranchByNameValidator(
            new SwitchBuilder<String,ValidatorExpression>()
            .put("userId", new ValueLoopValidator(
                new IfNotValidator(
                    ValidatorConstants.REQUIRED,
                    new MessageValidator("validator.userId.required"))))
            .get())),
    new IfValidator(
        // 必須検証はアクション id に依存するのでアクション id でしぼって検証する。
        new RegExpIdValidator("user_(register|update)(Confirm|Result)"),
        new BranchByNameValidator(
            new SwitchBuilder<String,ValidatorExpression>()
            .put("name", new ValueLoopValidator(
                new IfNotValidator(
                    ValidatorConstants.REQUIRED,
                    new MessageValidator("validator.name.required"))))
            .put("sex", new ValueLoopValidator(
                new IfNotValidator(
                    ValidatorConstants.REQUIRED,
                    new MessageValidator("validator.sex.required"))))
            .put("address", new ValueLoopValidator(
                new IfNotValidator(
                    ValidatorConstants.REQUIRED,
                    new MessageValidator("validator.address.required"))))
            .put("age", new ValueLoopValidator(
                new IfNotValidator(
                    ValidatorConstants.REQUIRED,
                    new MessageValidator("validator.age.required"))))
            .get()))
    ));

変換後の HTML 表現
以下の処理を順次実行し、論理積で全体の検証結果を判定する。
  1. 以下にあげる変数名のみ含まれている
    sex, age, userId, address, comment, hobby, name
    そうでない場合メッセージ"validator.acceptable"を出力する。
  2. リクエストされた変数名により以下分岐し、論理積(全部評価する)で全体の検証結果を判定する。
    userId
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    パターン"#,##0.###"の数値フォーマットによる変換結果を Integer に変換するフォーマットによって文字列を変換する。そうでない場合メッセージ"validator.userId.parse"を出力する。
    name
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    文字列の長さが40以下そうでない場合メッセージ"validator.name.maxLength"を出力する。
    sex
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    以下の処理を順次実行し、論理積で全体の検証結果を判定する。
    1. 以下にあげる値のいずれかである
      0, 1
      そうでない場合メッセージ"validator.sex.acceptable"を出力する。
    2. パターン"#,##0.###"の数値フォーマットによる変換結果を Integer に変換するフォーマットによって文字列を変換する。そうでない場合メッセージ"validator.sex.parse"を出力する。
    address
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    文字列の長さが80以下そうでない場合メッセージ"validator.address.maxLength"を出力する。
    age
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    以下の処理を順次実行し、論理積で全体の検証結果を判定する。
    1. パターン"#,##0.###"の数値フォーマットによる変換結果を Integer に変換するフォーマットによって文字列を変換する。そうでない場合メッセージ"validator.age.parse"を出力する。
    2. 数値が0以上そうでない場合メッセージ"validator.age.min"を出力する。
    3. 数値が200以下そうでない場合メッセージ"validator.age.max"を出力する。
    hobby
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    以下にあげる値のいずれかである
    0, 1, 2, 3
    そうでない場合メッセージ"validator.hobby.acceptable"を出力する。
    comment
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    文字列の長さが200以下そうでない場合メッセージ"validator.comment.maxLength"を出力する。
    デフォルト
    なにもしない。
  3. リクエスト ID が正規表現"user_(deleteConfirm|updateInput)"に合致である場合指定された変数名により以下分岐し、論理積(全部評価する)で全体の検証結果を判定する。
    userId
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    値が入力されている状態そうでない場合メッセージ"validator.userId.required"を出力する。
    デフォルト
    なにもしない。
    そうでない場合なにもしない。
  4. リクエスト ID が正規表現"user_(register|update)(Confirm|Result)"に合致である場合指定された変数名により以下分岐し、論理積(全部評価する)で全体の検証結果を判定する。
    name
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    値が入力されている状態そうでない場合メッセージ"validator.name.required"を出力する。
    sex
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    値が入力されている状態そうでない場合メッセージ"validator.sex.required"を出力する。
    address
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    値が入力されている状態そうでない場合メッセージ"validator.address.required"を出力する。
    age
    変数一覧に対し以下の処理を順次実行し、論理積(全部評価する)で全体の検証結果を判定する。
    値が入力されている状態そうでない場合メッセージ"validator.age.required"を出力する。
    デフォルト
    なにもしない。
    そうでない場合なにもしない。
トップに戻る
Copyright (C) 2006 Takahiro Nakamura. All rights reserved.