- PR -

Annotationの不正な値に対するベストプラクティスは?

1
投稿者投稿内容
ヤング
会議室デビュー日: 2002/12/17
投稿数: 4
投稿日時: 2005-03-22 13:42
J2SE5.0(Tiger)でAnnotationを学習している最中なのですが、
「Annotationの値を検証した際に、不正な値であった場合に、どうすべきか?」
ということで悩んでいます。

こんなコードがあったとします。

(1)MyBirthDay.java
コード:
@BirthDay(year="1999", month="9", day="19")
public class MyBirthDay {
}



(2)BirthDay.java
コード:
public @interface BirthDay {
  String year();
  String month();
  String day();
}



(1)のように、誕生日が1999年9月19日ならいいのですが、
たとえばこんなこと↓したらどうしましょう?

(1')YourBirthDay.java
コード:
@BirthDay(year="9999", month="99", day="X")
public class YourBirthDay {
}



西暦9999年に人類がJavaを使っているか分かりませんし(というかそれ以前に滅亡してなきゃいいけど…)、
「99月」とか、「X日」という値は不正ですよね。

私が思うに、こういう場合はまず

  1. 警告を発しない。
  2. コンパイル時(javacコマンドなど)に警告を発する。
  3. 実行時(javaコマンドなど)に警告を発する。

のうち、まあ少なくとも、「警告を発しない。」はないかな、とも思いますが、
では、コンパイル時または実行時に警告を発するとしても、

  1. コンソール上で警告を発する。
  2. ログファイルに警告を出力する。
  3. com.sun.mirror.apt.AnnotationProcessor実装クラスにて、java.lang.annotation.AnnotationFormatError(を継承したクラス)を投げる。

のどれかではないか、と。
特に、「AnnotationFormatErrorを投げる説」は、processメソッドが何もthrowsしないところをみても、対応できるんではないかな、と思うんですが。

以下に、上記コードのためのAnnotationProcessorおよびAnnotationProcessorFactory実装クラスのサンプルも挙げておきます。

(3)BirthDayProcessor.java
コード:
import java.io.*;
import java.util.*;
import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*;
import com.sun.mirror.type.*;
import com.sun.mirror.util.*;

public class BirthDayProcessor implements AnnotationProcessor {

  AnnotationProcessorEnvironment env;
  Set<AnnotationTypeDeclaration> atds;

  List<String> lines = new ArrayList<String>();

  BirthDayProcessor( Set<AnnotationTypeDeclaration> atds,
            AnnotationProcessorEnvironment env ) {
    this.atds = atds;
    this.env = env;
  }

  public void process() {

    Collection<TypeDeclaration> tds
         =  env.getSpecifiedTypeDeclarations();
    TypeDeclaration td = tds.iterator().next();
    Collection<AnnotationMirror> ams
         = td.getAnnotationMirrors();
    AnnotationMirror am = ams.iterator().next();

    Map<AnnotationTypeElementDeclaration, AnnotationValue> map
       = am.getElementValues();
    Set<AnnotationTypeElementDeclaration> keys
       = map.keySet();

    for( AnnotationTypeElementDeclaration key : keys ) {

      if( key.getSimpleName().equals( "year" ) ) {
        // ここで「year」の値をチェックする。
      }
      else if( key.getSimpleName().equals( "month" ) ) {
        // ここで「month」の値をチェックする。
      }
      else if( key.getSimpleName().equals( "day" ) ) {
        // ここで「day」の値をチェックする。
      }
    }
  }

}



(4)BirthDayProcessorFactory.java
コード:
import java.util.*;

import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*;

public class BirthDayProcessorFactory
       implements AnnotationProcessorFactory {

  private static final Collection<String> types
    = Collections.unmodifiableCollection(Arrays.asList( "BirthDay") );

  private static final Collection<String> options
    = Collections.emptySet();

  public Collection<String> supportedAnnotationTypes() {

    return types;
  }

  public Collection<String> supportedOptions() {

    return options;
  }

  public AnnotationProcessor getProcessorFor(
      Set<AnnotationTypeDeclaration> atds,
      AnnotationProcessorEnvironment env ) {

    return new BirthDayProcessor( atds, env );
  }
}



http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/annotation/AnnotationFormatError.html
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/apt/mirror/com/sun/mirror/apt/AnnotationProcessor.html
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/apt/mirror/com/sun/mirror/apt/AnnotationProcessorFactory.html

1

スキルアップ/キャリアアップ(JOB@IT)