HLTech / pact-gen

MIT License
14 stars 4 forks source link

Write a compiler annotation processor that will generate pact files #29

Open cardil opened 5 years ago

cardil commented 5 years ago

In projects, it's usually useful to generate sources as a build step. For that a Maven or/and Gradle plugin for that was a industry standard.

But, I propose to write a a annotation processor instead. In that way the code will be generated at compile time at any tool: Maven, Gradle, SBT or even IDE like Intellij and Eclipse.

It might look like that (annotation):

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface GeneratePact {
  /**
   * A consumer name that must be given.
   *
   * @return a consumer name
   */
  String value();

  /**
   * A consumer name that must be given. This is an alias for {@link #value()}
   *
   * @return a consumer name
   */
  String consumerName() default EMPTY_VALUE;

  /**
   * A package that should be taken as a root for generated code.
   * <p>
   * If not given {@link #packageClass()} will be used instead.
   * @return a package of generated code
   */
  String packageRoot() default EMPTY_VALUE;

  /**
   * If not given annotated class will be taken as a base for
   * getting a package
   *
   * @return a class whose package will be taken as generated code root
   */
  Class<?> packageClass() default GeneratePact.class;

  /**
   * A supplier for a PactGenerator. Given supplier must be instantiable
   * at compile time.
   * <p>
   * Will be instantiated by {@link #beanFactory()}
   *
   * @return a supplier for Pact Generator
   */
  Class<? extends Supplier<PactGenerator>> pactGenerator()
    default DefaultPactGeneratorSupplier.class;

  /**
   * A supplier for Jackson's ObjectMapper. Given supplier must be instantiable
   * at compile time.
   * <p>
   * Will be instantiated by {@link #beanFactory()}
   * @return a supplier for ObjectMapper
   */
  Class<? extends Supplier<ObjectMapper>> objectMapper()
    default DefaultObjectMapper.class;

  /**
   * A bean factory that will create beans like PactGenerator and others.
   * Bean factory must be instantiable at compile time.
   *
   * @return a supplier for bean factory
   */
  Class<? extends Supplier<BeanFactory>> beanFactory()
    default ReflectionBeanFactory.class;
}

And usage:

// generates resources to package of CompileTimeGeneratorTest
@PactGenerate("consumer-name")
public class CompileTimeGeneratorTest {
  @Test
  public void generatePactFilesAtCompile() {
    URL file = getClass().getResource("example.pact");
    assertThat(Paths.get(url.toURI())).exists();
  }
}
cardil commented 5 years ago

A compiler plugin could be useful: http://www.baeldung.com/java-build-compiler-plugin