Как создать enum с пользовательским типом, используя JavaPoet - PullRequest
0 голосов
/ 27 сентября 2019

Можно ли с помощью JavaPoet сгенерировать следующий перечислимый класс?

public enum EnumName {

  import com.sth.sth.SomeClass1;
  import com.sth.sth.SomeClass2;

  ITEM1(new CustomType<SomeClass1>("string1", "string 2", SomeClass1.class)),
  ITEM2(new CustomType<SomeClass2>("string1", "string 2", SomeClass2.class));

  EnumName(CustomType customType) {
    this.customType = customType;
  }

  private final CustomType customType;

  public CustomType getCustomType() {
    return customType;
  }
}

Я могу создать все, но у меня огромная борьба с блоком инициализации в рамках ПУНКТОВ.

Мой текущий код

TypeSpec.Builder typeSpecBuilder = TypeSpec.enumBuilder("EnumName")
                .addModifiers(PUBLIC)
                .addField(TypeVariableName.get("CustomType"), "customType", PRIVATE, FINAL)
                .addMethod(MethodSpec.constructorBuilder()
                                     .addParameter(TypeVariableName.get("CustomType"), "customType")
                                     .addStatement("this.$N = $N", "customType", "customType")
                                     .build())
                .addMethod(MethodSpec.methodBuilder("getCustomType")
                                     .addModifiers(PUBLIC)
                                     .addStatement("return customType")
                                     .returns(TypeVariableName.get("CustomType"))
                                     .build());
for (Model model : models) {
    typeSpecBuilder.addEnumConstant(prepareName(model), HERE I DO NOT KNOW HOW TO BUILD TypeSpec that would create what i need);
}

Я смог создать это

public enum EnumName {

  ITEM1("ITEM1"){
    @Override
    public CustomType getCustomType(){
      return new CustomType<SomeClass1>("string1", "string 2", SomeClass1.class));
    }
  },
  ITEM2("ITEM2"){
    @Override
    public CustomType getCustomType(){
      return new CustomType<SomeClass2>("string1", "string 2", SomeClass2.class));
    }
 };

  EnumName(customTypeName customTypeName) {
    this.customTypeName = customTypeName;
  }

  private final String customTypeName;

  public String getCustomTypeName() {
    return customTypeName;
  }

, настроив цикл следующим образом:

for (Model model : models) {
    typeSpecBuilder.addEnumConstant(prepareName(model), TypeSpec.anonymousClassBuilder("$S", prepareName(model))
    .addMethod(MethodSpec.methodBuilder("getCustomType")
    .addAnnotation(Override.class)
    .addModifiers(PUBLIC)
    .addStatement(getInitStatement(model))
    .returns(TypeVariableName.get("CustomType"))
                            .build())
                    .build());
}

Это частично нормально, но я не знаю какдля генерации импорта для этих классов.

Я предпочитаю первый вариант

ITEM1(new CustomType<SomeClass1>("string1", "string 2", SomeClass1.class))

, но если это невозможно сделать, может кто-нибудь предложить, как создать импорт для второго примера с поправкой на цикл?

Большое спасибо за любые предложения.

1 Ответ

1 голос
/ 30 сентября 2019

Хорошо, найдено решение, если кому-то будет интересно будущее.

String fullyQualifiedClassName = getClassName();
if (fullyQualifiedClassName == null) {
  fullyQualifiedClassName = "Object";  //important if class was not found we need set to object -> otherwise there will not be imports for some reason
}
TypeName typeName = ClassName.bestGuess(fullyQualifiedClassName);
for (Model model : models) {
    typeSpecBuilder.addEnumConstant(prepareName(model), TypeSpec.anonymousClassBuilder("new CustomType<$T>($S, $S, $T.class)", typeName, string1, string2, typeName));
}
...