2010年1月4日月曜日

OValで独自アノテーションを作成

スズキです。

今回は、こちらで作成したメソッドでのバリデーション処理を、
http://blog.suz-lab.com/2010/01/oval.html
下記のような独自アノテーションで実現してみようと思います。

--------【IndexForm.java】--------
...
@NotExistsOnDatastore(kind="feed", property="url", type=Link.class)
public String url;
...
--------
http://code.google.com/p/suz-lab-gae/source/browse/trunk/suz-lab-feed/src/suz/lab/feed/page/other/mypage/IndexJson.java?r=102

ちなみに、上記のバリデーションはDatastore中に
すでに同じデータが無いかどうかチェックするもので、

kind: EntityのKind
property: Entityのprotertyのキー
type: Entityのprotertyの型

としています。そして、アノテーションのコードは下記となります。

--------【NotExistsOnDatastore.java】--------
...
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Constraint(checkWith=NotExistsOnDatastoreCheck.class)
public @interface NotExistsOnDatastore {
  String kind();
  String property();
  Class<?> type();
}
--------
http://code.google.com/p/suz-lab-gae/source/browse/trunk/suz-lab-gae/src/suz/lab/gae/check/NotExistsOnDatastore.java?r=102

ポイントは、
@Constraint(checkWith=NotExistsOnDatastoreCheck.class)
でしょうか?
そして、ここで指定されているNotExistsOnDatastoreCheckが以下になります。

--------【NotExistsOnDatastoreCheck.java】--------
...
public class NotExistsOnDatastoreCheck
  extends AbstractAnnotationCheck<NotExistsOnDatastore> {

  private String kind;
  private String property;
  private Class<?> type;

  @Override
  public void configure(NotExistsOnDatastore constraintAnnotation) {
    this.kind = constraintAnnotation.kind();
    this.property = constraintAnnotation.property();
    this.type = constraintAnnotation.type();
  }

  @Override
  public boolean isSatisfied(
    Object form, Object value,
    OValContext context,
    Validator validator
  ) throws OValException {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Query query = new Query(this.kind);
    if(type.equals(Link.class)) {
      query.setKeysOnly().addFilter(
        this.property,
        FilterOperator.EQUAL,
        new Link((String)value)
      );
    } else {
      return false;
    }
    if(datastore.prepare(query).countEntities() == 0) {
      return true;
    } else {
      return false;
    }
  }

}
--------
http://code.google.com/p/suz-lab-gae/source/browse/trunk/suz-lab-gae/src/suz/lab/gae/check/NotExistsOnDatastoreCheck.java?r=102

型引数として上記で作成したNotExistsOnDatastoreを指定した
AbstractAnnotationCheckクラスを継承し、
configureメソッドとisSatisfiedメソッドをオーバーライドしています。
(メソッドの役割は、まあ、名前の通りです)

と、偉そうに、いろいろ書いてきたのでうが…
実は、propertyの型がLinkのときしか対応していません…

2010年営業開始前の予習は、次の"jQuery Validation"のremote連携までかな?

--------
http://www.suz-lab.com

0 コメント: