Class FieldGeneratorAnnotationProcessor

java.lang.Object
javax.annotation.processing.AbstractProcessor
tech.ydb.yoj.generator.FieldGeneratorAnnotationProcessor
All Implemented Interfaces:
Processor

@SupportedAnnotationTypes("tech.ydb.yoj.databind.schema.Table") @SupportedSourceVersion(RELEASE_17) public class FieldGeneratorAnnotationProcessor extends AbstractProcessor
Generates a "-Fields" classes for all entities in a module.

This is useful for building queries like 'where(AuditEvent.Id.TRAIL_ID).eq(trailId)'

Assume that we have an entity:


     @Table(...)
     class MyTable {
         String strField;
         Object anyTypeField;
         Id idField;
         OtherClass fieldOfOtherClass;

         static class Id {
             String value;
             OneMoreLevel deepField1;
             OneMoreLevel deepField2;

             static class OneMoreLevel {
                 Integer field;
             }
         }
     }
 
 A generated class will be
  

      class MyTableFields { //  Annotation processors must create a new class, so the name is different
          // fields considered as 'simple' if there is no nested class of the field's type
          public static final String STR_FIELD = "strField";
          public static final String ANY_TYPE_FIELD = "anyTypeField";
          // `fieldOfOtherClass` is a simple field because `OtherClass` is not inside the given class
          public static final String FIELD_OF_OTHER_CLASS = "fieldOfOtherClass";

          // idField is not simple because it has a type Id and there is a nested class Id
          // Pay attention that the generated nested class uses the field's name! It's necessary because we might
          // have several fields of the same type
          public static class IdField {
              public static final String VALUE = "idField.value"; // Mind that the value has "idField." prefix

              // The Annotation Processor works recursively
              // Also it's the example of several fields with the same type
              static class DeepField1 {
                  public static final String FIELD = "idField.deepField1.field";
              }
              static class DeepField2 {
                  // Pay attention that ".deepField2." is used here
                  public static final String FIELD = "idField.deepField2.field";
              }
          }
      }
  
  
    Additional info:
  • Support Records
  • Support Kotlin data classes
    Known issues (should be fixed in future):
  • if entity doesn't have @Table it won't be processed even if it's implements Entity interface
  • We assume that annotation @Table is used on top-level class
  • The AP will break in case of two nested classes which refer each other (i.e. circular dependency)
  • Will generate nested classes even disregarding @Column's flatten option
  • No logs are written
  • if a field has type of a class which is not nested inside the annotated class, the field will be ignored
  • There is a rare situation when generated code won't compile. The following source class
    
              class Name{
                  Class1 nameClash;
                  public static class Class1 {
                      Class2 nameClash;
                      class Class2{
                          String nameClash;
                      }
                  }
              }
         
         will produce
         
    
             public class NameFields {
                 public class NameClash {
                     public class NameClash {
                         public static final String NAME_CLASH = "nameClash.nameClash.nameClash";
                     }
                 }
             }
         
         which won't compile due to 2 NameClash classes.
         
Author:
pavel-lazarev