CLOVER🍀

That was when it all began.

scala.annotation.metaパッケージのアノテーションと、パラメータ付きのアノテーションを一緒に使う

先ほどのBean Validatorでも使いましたが、絶対忘れそうなので独立したエントリとして書いておくことにしました。

このようなクラスを用意してみます。

import javax.validation.constraints.{Min, NotNull, Size}

case class Book(
  @NotNull
  @Size(min = 14, max = 14)
  isbn: String,

  @NotNull
  title: String,

  @Min(1)
  price: Int
)

ただ、この書き方だとコンストラクタ引数に対してアノテーションを付与していることになってしまうので、scala.annotation.metaパッケージのアノテーションを使用します。

  • field
  • getter
  • setter
  • beanGetter
  • beanSetter

…などなど。これらを使用することで、実際にアノテーションが付与される場所をコントロールできます。

で、今回はフィールドに付与することにして、fieldアノテーションを使用してみます。

何も考えずに書こうとすると

import scala.annotation.meta.field

import javax.validation.constraints.{Min, NotNull, Size}

case class Book(
  @(NotNull @field)
  @(Size(min = 14, max = 14) @field)
  isbn: String,

  @(NotNull @field)
  title: String,

  @(Min(1) @field)
  price: Int
)

こんな感じになるかと思うのですが、バシバシとコンパイルエラーになります。

[error] /path/to/Book.scala:9: ')' expected but '(' found.
[error]   @(Size(min = 14, max = 14) @field)
[error]         ^
[error] /path/to/Book.scala:9: identifier expected but ')' found.
[error]   @(Size(min = 14, max = 14) @field)
[error]                                    ^
[error] /path/to/Book.scala:31: ':' expected but eof found.

こういうのはいいのですが

  @(NotNull @field)

パラメータを付ける時が、ダメだということですね。

  @(Size(min = 14, max = 14) @field)

で、どうなるかというと、こうなります。

case class Book(
  @(NotNull @field)
  @(Size @field)(min = 14, max = 14)
  isbn: String,

  @(NotNull @field)
  title: String,

  @(Min @field)(1)
  price: Int
)

後ろに括弧を付けて、指定しろと。

  @(Size @field)(min = 14, max = 14)

パラメータ名がvalueの時は、書かなくていいのは普通に書く時と同じっぽい?

  @(Min @field)(1)

「value = 1」と書いても同じですが。

滅多に使わないので、覚えていられるかなぁ…。