[jjbug-seam 64] カスタムHibernate Validator

266 views
Skip to first unread message

Toshiya Kobayashi

unread,
Oct 7, 2008, 6:38:04 AM10/7/08
to japan-j...@lists.sourceforge.jp
こんにちは、小林です。

みなさん、カスタムバリデータは作っていますか?

私の場合、実際に欲しいバリデータの大部分は
@Patternの正規表現とメッセージで表現できます。
しかし

@Pattern(regex="^[a-zA-Z]*$", message="国名は半角英字で入力してください")
public String getCountry() {
return this.country;
}

よりは

@Country
public String getCountry() {
return this.country;
}

のように書きたい(正規表現とメッセージの組を個々に定義して再利用)ので、
Hibernate Validatorの仕組み(@ValidatorClass)を使ってカスタムバリデータを作りました。
(参照: http://reyjexter.blogspot.com/2008/02/custom-hibernate-validator-that.html
)
この場合、アノテーション+バリデーション実装クラスが対になり、
実装クラスとしてPatternValidatorを使いまわせない(アノテーションがextendsできないのが痛い)ので、
同じような内容のバリデーション実装クラスをたくさん作るはめになります。

そこで正規表現を使うバリデーション実装クラスを共有するために
リフレクションを使って以下のようなクラスを書いてみましたが、
これがベストプラクティスなのか?というとイマイチ釈然としません。
こんな風にしているよ、などあればご意見お願いします。

# なんか大きな見落としがありそうな気が・・・

public class PatternValidatorSupport implements Validator<Annotation>,
Serializable {

private java.util.regex.Pattern pattern;

public void initialize(Annotation parameters) {
String regex;
int flags;
try {
// この辺もう少し安全にするための処理が必要か
regex =
(String)parameters.getClass().getDeclaredMethod("regex",
null).invoke(parameters, null);
flags =
(Integer)parameters.getClass().getDeclaredMethod("flags",
null).invoke(parameters, null);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}

pattern = java.util.regex.Pattern.compile(
regex,
flags
);
}

public boolean isValid(Object value) {
if ( value == null ) return true;
if ( !( value instanceof String ) ) return false;
String string = (String) value;
Matcher m = pattern.matcher( string );
return m.matches();
}

}

== PatternValidatorSupport を使うアノテーションの例 ==

@Documented
@ValidatorClass(PatternValidatorSupport.class)
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Country{
/** regular expression */
String regex() default "^[a-zA-Z]*$";

/** regular expression processing flags */
int flags() default 0;

String message() default "国名は半角英字で入力してください";
}

_______________________________________________
Japan-jbug-seam mailing list
Japan-j...@lists.sourceforge.jp
http://lists.sourceforge.jp/mailman/listinfo/japan-jbug-seam

Reply all
Reply to author
Forward
0 new messages