0

Is it possible to generate the following enum class using 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;
  }
}

i can create everything but i have huge struggle with initialisation block within the ITEMs.

My current code is

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);
}

i was able to create this

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;
  }

by adjusting for cycle like so:

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());
}

This is partially ok but i do not know how to generate imports for those classes.

I prefer first option

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

but if it cannot be done can someone suggest how to generate imports for the second example with adjusted for cycle?

Thank you very much for any suggestion.

Juraj V.
  • 11
  • 3

1 Answers1

1

Ok found solution if anyone will be interested in future.

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));
}
Juraj V.
  • 11
  • 3