【Jackson】アノテーションをコードから追加する

# TL;DR
- `ClassIntrospector`と`BasicBeanDescription`を独自実装することで、コードからアノテーションを追加できる
  - 例えば、後から`JsonSerialize`アノテーションを追加することが可能
- 見通しが悪くなるため、事情が無ければやらない方がよい
- （これによって`jackson-module-kotlin`の`value class`サポートが1歩進んだ）

# 状況
`Jackson`内で利用したいアノテーションが`Synthetic`なコンストラクタにしか付与されておらず、`Jackson`内で取り扱われるコンストラクタには付与されていないという状況がありました。
そこで、どこかで`Jackson`の処理に介入して`Synthetic`なコンストラクタのアノテーションを`Jackson`内で取り扱われるコンストラクタ側に注入できないか試しました。

## 補足
以下はこの記事の元になった`PR`で修正された`failing test`です。
コンストラクタのパラメータに付与される形になるアノテーションが、変更前は機能しておらず、変更後は機能している様子が分かります。

https://github.com/ProjectMapK/jackson-module-kogera/pull/50/files#diff-d4d396706d19f0636b03e75522a1c2bb717ca2cd9609bb36a22743f61cde22c9L75-L96

# やったこと
## クラスの解析処理へ介入する
`BeanDescription`を独自実装し、同じく独自実装した`ClassIntrospector`から利用することで、`Jackson`のクラス解析処理へ介入することが出来ます。
実装のベースとしては、それぞれ`BasicBeanDescription`と`BasicClassIntrospector`を利用します。

https://fasterxml.github.io/jackson-databind/javadoc/2.14/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.html

https://fasterxml.github.io/jackson-databind/javadoc/2.14/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.html

## 実装したもの
### BeanDescription
```kotlin
import com.fasterxml.jackson.databind.introspect.AnnotatedConstructor
import com.fasterxml.jackson.databind.introspect.BasicBeanDescription
import com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector

// アノテーションの注入処理
private fun AnnotatedConstructor.injectSyntheticAnnotations() {
    val constructor = annotated

    @Suppress("UNCHECKED_CAST")
    val syntheticParams = constructor.parameterTypes.copyOf(constructor.parameterCount + 1)
        .apply { this[constructor.parameterCount] = defaultConstructorMarker } as Array<Class<*>>
    // 対応するSyntheticなコンストラクタの取得を試し、取得できなければ何もしない
    val syntheticConstructor = runCatching { declaringClass.getDeclaredConstructor(*syntheticParams) }
        .getOrNull()
        ?: return

    // 取得できた場合、注入処理を行う
    (0 until constructor.parameterCount).forEach { i ->
        val map = getParameterAnnotations(i)
        syntheticConstructor.parameterAnnotations[i].forEach { map.add(it) }
    }
}

internal class KotlinBeanDescription(coll: POJOPropertiesCollector) : BasicBeanDescription(coll) {
    init {
        // クラス内のコンストラクタ全てについてアノテーションの注入処理を行う
        this.constructors?.forEach { it.injectSyntheticAnnotations() }
    }
}
```

### ClassIntrospector
```kotlin
import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.databind.SerializationConfig
import com.fasterxml.jackson.databind.introspect.BasicBeanDescription
import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector
import com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector

internal object KotlinClassIntrospector : BasicClassIntrospector() {
    override fun forSerialization(
        config: SerializationConfig,
        type: JavaType,
        r: MixInResolver
    ): BasicBeanDescription {
        // この処理はKotlinBeanDescription関係以外全てsuperからコピーしてKotlin化だけしたもの
        return _findStdTypeDesc(config, type)
            ?: _findStdJdkCollectionDesc(config, type)
            ?: run {
                val coll = collectProperties(config, type, r, true)

                if (type.rawClass.annotations.any { it is Metadata }) {
                    KotlinBeanDescription(coll)
                } else {
                    BasicBeanDescription.forDeserialization(coll)
                }
            }
    }
}
```