# Kogito Codegen

This repository contains the shared (Maven Plug-In, Quarkus Extension, ...)
code generation logic for Kogito: processes, rules, decisions, etc.

The structure of the module is:
- `kogito-codegen-api`: shared API necessary to implement a generator
- `kogito-codegen-core`: common core classes used to wire the generation process together
- `kogito-codegen-*`: module specific generator for processes, rules, etc
- `kogito-codegen-sample`: reference module with a sample implementation of a generator (with a simple -runtime too)
- `kogito-codegen-integration-tests`: integration test modules where it is possible not only to assert on generated source code but also compile it and execute

| NOTE: the `kogito-codegen-integration-tests` module should be only used to test generate engine classes and it is not intended to be used for full end to end test (use `integration-tests` module instead) |
| ---- |

## Generator API
- Each component (process, rules, etc.) implements the `Generator`
  interface 
- `Generator`s are plugged into the `ApplicationGenerator` instance (in the `core` module)
- Upon construction, a `Generator` is given the path(s) of the directory/files
  that it must process. Scanning of the directory take place contextually
- Each `Generator` may come with its own specific configuration
- Each `Generator` can delegate to a subcomponent, to process a single
  component. E.g., the `ProcessCodegen` can
  delegate to a `ProcessGenerator` to work on a single process; `RuleCodegen`
  can delegate to a `RuleUnitGenerator`, etc.

  note: naming convention may vary in the future

- Generators **do not** write files to disk, rather return a `GeneratedFile`
  instance, with the relative file path (derived from the original path
  and further analysis on the contents of the file) and the byte array
  of the contents of the file to be dumped to disk.
  
- `KogitoBuildContext` contains all shared information about the build: it is 
  platform specific (Quarkus/Spring/Java) and it is shared by all the Generators

- `GeneratorFactory` is an interface a generator can implement and together with SPI 
  is used to automatically wire the generator (see `META-INF/services/org.kie.kogito.codegen.api.GeneratorFactory`)

## Core module
- `ApplicationGenerator` is the main entry point. The fluent API allows to
  configure its global behavior.

    ```java
    ApplicationGenerator appGen =
            new ApplicationGenerator(context);
    ```
- The `ApplicationGenerator#generate()` method starts the code generation
  procedure, delegating to each `Generator` where appropriate.

### Generator wiring
The wiring of the generators can be done manually invoking the `setupGenerator` of 
`ApplicationGenerator` class
    
```java
    appGen.setupGenerator(RuleCodegen.ofPath(context, ruleSourceDirectory));
    
    appGen.setupGenerator(ProcessCodegen.ofPath(context, processSourceDirectory));
```
Or it can be done via SPI using `ApplicationGeneratorDiscovery` utility class that
automatically loads the main `ApplicationGenerator` and the generators for the available components.

| NOTE: both Spring and Quarkus integration use SPI and `ApplicationGeneratorDiscovery` for automatic wiring |
| ---- |

## Sample generator
This generator is intended to be a prototype/reference implementation of a simple generator that
consumes `.txt` files and exposes the content as REST endpoint.

The example is formed by a `-runtime` module that contains the "engine" implementation (e.g. DMN runtime) and a 
`-generator` module with the generation/wiring logic

## Testing a generator

A generator is a component that produces source code or resources. The only real and final test of a generator
is an integration test where it is possible to mimic the whole flow from file to endpoint.

At the same time if there is an error in the generated code this could be quite hard to debug: it could fail during the compilation
or follow an unexpected codepath.

For this reason it is strongly suggested to also implement unit tests for each of the generator classes.

You can check sample generator for a full example but in general the rules are:
- Avoid/minimize assertions on number of files because hard to debug. If you need a similar assertion try to filter generated 
  resources by resource type before
- Test the generation with all the build context (Spring/Quarkus/Java): you can use `@ParameterizedTest` to help with this:
  add following dependencies
  ```xml
  <dependency>
    <groupId>org.kie.kogito</groupId>
    <artifactId>kogito-codegen-api</artifactId>
    <type>test-jar</type>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <scope>test</scope>
  </dependency>
  ```
  and use `KogitoContextTestUtils` utility
  ```java
  @ParameterizedTest
  @MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
  void test(KogitoBuildContext.Builder contextBuilder) {
    KogitoBuildContext context = contextBuilder.build();
    ...
  }
  ```
- If your generator use `context.hasClassAvailable` method to introspect the classloader you can use 
  `org.kie.kogito.codegen.KogitoBuildContextTestUtils.mockClassAvailabilityResolver` method to inject 
  (in `KogitoBuildContext.Builder`) your expectation
  ```java
  contextBuilder.withClassAvailabilityResolver(
    mockClassAvailabilityResolver(
        includedClasses, excludedClasses));
  ```
- Avoid (when possible) assertion on full generated statements and prefer more general assertions like:
  the block should contain `this` element, or the method should have an annotation with `this` value
- You should have functional test for each engine in a different specific module outside generators, 
  so you should not need to _execute_ generated code in this module (just write a proper integration test for that).
  If you really want/need to do that it is possible (only for `Application` related classes) to use 
  `kogito-codegen-integration-tests` module and extend `org.kie.kogito.codegen.AbstractCodegenIT`


# Generated Application file

The result of the processing is the main entry point `org.kie.kogito.app.Application`.

- Components are organized into "sections". The idea, is that for a component C,
  it is possible to invoke some method such that an instance of C is returned.
  e.g.:
  
   * for process P, one may write `new Application().get(Processes.class).create("P")`
   * for rule unit R, one may write `new Application().get(RuleUnits.class).create("R")`
  
  note: specific APIs may vary.

```java
package org.kie.kogito.app;

public class Application extends org.kie.kogito.StaticApplication {

  public Application() {
    super(new ApplicationConfig());
    loadEngines(new Processes(), new RuleUnits());
  }
}
```

This Application API is intended to be accessed directly from end users and in both Spring/Quarkus scenarios it is possible
and preferable to directly inject each engine like  
```java
package org.my.package;

@ApplicationScoped
public class MyCustomBean {
  
  @Inject
  private Processes processes;

  @Inject
  private DecisionModels decisionModels;
  
  ...
}
```

# Additionally-generated files

Implementations may (and usually *do*) generate additional source code. 
In particular:
 
- Rules generate source code for the RuleUnit implementation **and** the 
  executable model description
- Processes generate source code for their Process implementation using
  their specific executable model description
- Most Generators also generate `Resources`, i.e. REST API endpoints.  

