# Code Generting Conventions

This document outlines the coding conventions for this project to be used by any AI agent.
Ask the user to add these files to the AI agent before generating anything.

## Initially

At the beginning of each code generation session, determine all files which are not yet added, but might need to be changed and new files which might need to be created.

Consider:
- related Java-classes (*.java), including test classes
- also Java-classes files in the same package as the mainly related class, e.g. patcher
- related liquibase changesets (*.sql)
- related openapi specs (*.yaml)
- related i18n files (*.properties)

Make sure production code and test code stay in sync,
a change in one usually means the other has also to be changed.

## Java Conventions (`*.java` files)

### General Rules for Java Files

These rules apply to all `.java` files in `src/**/*.java` but not those located in `**/generated/**`, `build/**`, or `.gradle/**` directories.

1.  **Imports**: No wildcard imports. Unused imports must be removed.
2.  **Indentation**: Use 4 spaces for indentation. Do not use tabs.
3.  **End of File**: All files must end with a newline character.
4.  **Formatting Control**: Spotless formatting can be temporarily disabled for specific code blocks using comments:
    ```java
    // spotless:off
    // ... code that should not be formatted ...
    // spotless:on
    ```
*   Follow existing code style and patterns within the project.
    - Avoid reassigning variables and use `final var` where possible.
    - Use `final` for method parameters.
*   Use meaningful names for variables, methods, and classes.
*   Write clear and concise comments where necessary to explain complex logic or intent.

### toString via Stringify

For assertions, keep in mind, that the Stringify implementation of the toString method skips null values. Thus, do not add null values in assertions if a Stringify-based toString implementation is tested!


## PostgreSQL Conventions (`*.sql` files)

Do only Liquibase changesets if they got created in the same branch.

If they already exist in the master branch, generate a new Liquibase changeset.

Add new Liquibase changesets to existing files where they belong,
e.g. add a changeset with an ALTER TABLE directly after the related CREATE TABLE changeset. 

If creating a new Liquibase changeset, there is no need to check if the change already exists, Liquibase will check that.

## i18n Conventions (`*.properties` files)

Use the English translation as the key in the `messages_*.properties` file,
'=' and ' ' need to be quoted.

## YAML Conventions (*.yaml files)

Always use exactly 4 spaces for indentation.

## General Conventions

### general strategy

At the beginning of each task, always determine all files which might need to be changed and new files which might need to be created. 

### adding/deleting/amending fields/properties

If a field in a database table is added, deleted or amended, the following steps must be taken:

- The property must be added to the Java class on which the entity/entities are based; it must also be included in the toString method. Also amend the related unit test.

- If the related entity has a patcher class, also add the new property to the patcher (usually ending with EntityPatcher) and its unit test (usually ending with EntityPatcherUnitTest).

- The property must be included in (potentially 3) JSON resources (POST, GET, PATCH) in the OpenAPI specification.

- The property must be added to the SQL table, so either enforce it via Liquibase or create a new Liquibase changeset.

- The property must be included in the restricted view, which must be dropped and recreated due to the structural change; this view is generated by a stored procedure from the RBAC system.

- The property must be added to the RBAC update trigger; for this, the RBAC DSL, the static method rbac() in the entity class(es), must be adjusted. The generator should automatically force Liquibase to reapply the changeset.

- The tests may need to be adjusted; the new field should also be tested in an integration test for POST, GET, and PATCH.

## While Generating CHanges

Check all added files, if they need to be changed for the new feature.
Most likely, all added files need some sort of change.

Make sure production code and test code stay in sync,
a change in one usually means the other has also to be changed.

## Executing Commands

### Generating from OpenAPI

If OpenAPI specs (*.yaml) got changed, `gw openApiGenerate` needs to be executed.

### Generating from RBAC DSL

If any RBAC spec of an entity has changed, the static rbac() method in an entity class, `gw rbacGenerate` has to be executed before any test can run.

### Test Execution

Use the alias `gw-test` to run the tests with a proper environment.
Do not suggest to run `./gradlew test`, it won't work without a correect environment.
