Используйте класс данных Kotlin в сервис-прокси Vert.x - PullRequest
1 голос
/ 29 марта 2020

Я пытаюсь передать data class прокси-серверу Vert.x следующим образом:

data class Entity(val field: String)

@ProxyGen
@VertxGen
public interface DatabaseService {
  DatabaseService createEntity(Entity entity, Handler<AsyncResult<Void>> resultHandler);
}

Однако прокси-серверу требуется DataObject в качестве типа параметра.

Вот то, что я пробовал до сих пор. Во-первых, я переписываю класс данных как:

@DataObject
data class Entity(val field: String) {
  constructor(json: JsonObject) : this(
    json.getString("field")
  )

  fun toJson(): JsonObject = JsonObject.mapFrom(this)
}

Хотя это работает, код является избыточным, поэтому я попробовал kapt с помощью следующего генератора:

  override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
    roundEnv.getElementsAnnotatedWith(ProxyDataObject::class.java).forEach { el ->
      val className = el.simpleName.toString()
      val pack = processingEnv.elementUtils.getPackageOf(el).toString()
      val filename = "Proxy$className"

      val classBuilder = TypeSpec.classBuilder(filename)
      val primaryConstructorBuilder = FunSpec.constructorBuilder()
      val secondaryConstructorBuilder = FunSpec.constructorBuilder().addParameter("json", JsonObject::class)
      val secondaryConstructorCodeBlocks = mutableListOf<CodeBlock>()
      el.enclosedElements.forEach {
        if (it.kind == ElementKind.FIELD) {
          val name = it.simpleName.toString()
          val kClass = getClass(it)              // get the corresponding Kotlin class
          val jsonTypeName = getJsonTypeName(it) // get the corresponding type name in methods of JsonObject

          classBuilder.addProperty(PropertySpec.builder(name, kClass).initializer(name).build())
          primaryConstructorBuilder.addParameter(name, kClass)
          secondaryConstructorCodeBlocks.add(CodeBlock.of("json.get$jsonTypeName(\"$name\")"))
        }
      }
      secondaryConstructorBuilder.callThisConstructor(secondaryConstructorCodeBlocks)
      classBuilder
        .addAnnotation(DataObject::class)
        .addModifiers(KModifier.DATA)
        .primaryConstructor(primaryConstructorBuilder.build())
        .addFunction(secondaryConstructorBuilder.build())
        .addFunction(
          FunSpec.builder("toJson").returns(JsonObject::class).addStatement("return JsonObject.mapFrom(this)").build()
        )
      val generatedFile = FileSpec.builder(pack, filename).addType(classBuilder.build()).build()
      generatedFile.writeTo(processingEnv.filer)
    }
    return true
  }

Тогда я могу получить правильно сгенерированный файл, просто записав исходный data class, но когда я выполняю здание после очистки, я все равно получаю следующую ошибку:

Could not generate model for DatabaseService#createEntity(ProxyEntity,io.vertx.core.Handler<io.vertx.core.AsyncResult<java.lang.Void>>): type ProxyEntity is not legal for use for a parameter in proxy

Кажется, что сгенерированная аннотация @DataObject не обрабатывается .

Так что мне делать? Есть ли лучшее решение?

...