Skip to content

Refactor the Java code generator to allow “template variants”#3124

Merged
kevinschaper merged 5 commits into
linkml:mainfrom
gouttegd:refactor-java-generator
Feb 10, 2026
Merged

Refactor the Java code generator to allow “template variants”#3124
kevinschaper merged 5 commits into
linkml:mainfrom
gouttegd:refactor-java-generator

Conversation

@gouttegd

@gouttegd gouttegd commented Feb 2, 2026

Copy link
Copy Markdown
Contributor

This PR refactors the Java code generator to make it possible to have an arbitrary number of "template variants", where a variant can be used to represent a particular "style" of Java code. This implements the idea proposed in #3073.

This replaces the previous code that was used to implement the --generate-records option by a more generic mechanism.

There is no longer a default template that is embedded directly into the code of the Java generator module. Instead, all templates, for all variants, are expected to be located in the javagen directory, and named according to the following convention:

NAME[-VARIANT].jinja2

where NAME is the name of the class or enum to be generated (can be class for a generic template to use for all classes, or enum for a generic template to use for all enums) and VARIANT is an optional variant name.

When the generator has to generate the code file for a class named Foo using the variant bar, it will successively search for the following templates, using the first one that is found:

  1. Foo-bar.jinja2 (template specific for the Foo class, bar variant);
  2. class-bar.jinja2 (generic class template, bar variant);
  3. Foo.jinja2 (template specific for the Foo class, default variant);
  4. class.jinja2 (generic class template, default variant).

Steps 1 and 2 are skipped if no explicit variant is requested.

The same logic applies when generating the code for an enum (assuming the recently introduced --true-enums option is used), with the fallback templates in step 2 and 4 being named enum-bar.jinja2 and enum.jinja2 in that case.

On the command line, two new options are added:

  • --template-dir to specify an alternative directory for the templates;
  • --template-variant to specify the variant to use.

The existing option --generate-records is kept for backwards compatibility, and is now equivalent to --template-variant=records.

The --template-file option can still be used to completely bypass the template selection mechanism and use a single template for all the objects to generate.

This PR refactors the Java code generator to make it possible to have an
arbitrary number of "template variants", where a variant can be used to
represent a particular "style" of Java code.

This replaces the previous code that was used to implement the
`--generate-records` option by a more generic mechanism.

There is no longer a default template that is embedded directly into the
code of the Java generator module. Instead, all templates, for all
variants, are expected to be located in the `javagen` directory, and
named according to the following convention:

  NAME[-VARIANT].jinja2

where NAME is the name of the class or enum to be generated (can be
`class` for a generic template to use for all classes, or `enum` for a
generic template to use for all enums) and VARIANT is an optional
variant name.

When the generator has to generate the code file for a class named
`Foo` using the variant `bar`, it will successively search for the
following templates, using the first one that is found:

  1. Foo-bar.jinja2 (template specific for the Foo class, bar variant);
  2. class-bar.jinja2 (generic class template, bar variant);
  3. Foo.jinja2 (template specific for the Foo class, default variant);
  4. class.jinja2 (generic class template, default variant).

Steps 1 and 2 are skipped if no explicit variant is requested.

The same logic applies when generating the code for an enum (assuming
the `--true-enums` option is used), with the fallback templates in step
2 and 4 being named `enum-bar.jinja2` and `enum.jinja2` in that case.

On the command line, two new options are added:

  * `--template-dir` to specify an alternative directory for the
    templates;
  * `--template-variant` to specify the variant to use.

The existing option `--generate-records` is kept for backwards
compatibility, and is now equivalent to `--template-variant=records`.

The `--template-file` option can still be used to completely bypass the
template selection mechanism and use a single template for all the
objects to generate.
Add a test to check that we can still use the `--template-file` option
of the Java code generator and get the expected results, bypassing the
generator's own logic to pick up the template.
@codecov

codecov Bot commented Feb 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.18182% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.62%. Comparing base (b9f7dd0) to head (cecf1fb).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
packages/linkml/src/linkml/generators/javagen.py 78.18% 8 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3124      +/-   ##
==========================================
+ Coverage   79.86%   83.62%   +3.75%     
==========================================
  Files         149      149              
  Lines       16888    16924      +36     
  Branches     3465     3476      +11     
==========================================
+ Hits        13488    14152     +664     
+ Misses       2659     1981     -678     
- Partials      741      791      +50     
Flag Coverage Δ
linkml 79.84% <78.18%> (-0.02%) ⬇️
runtime 79.84% <78.18%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

1. Damn "modern" editors.
2. Why isn't that check part of `uv run tox -e lint`?
@gouttegd gouttegd marked this pull request as ready for review February 2, 2026 18:13
@matentzn matentzn requested a review from kevinschaper February 3, 2026 05:56
@matentzn matentzn linked an issue Feb 3, 2026 that may be closed by this pull request

@kevinschaper kevinschaper left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice! thank you!

@kevinschaper kevinschaper merged commit 0286c1a into linkml:main Feb 10, 2026
19 checks passed
@gouttegd gouttegd deleted the refactor-java-generator branch February 10, 2026 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactoring how the Java code generator uses Jinja templates

2 participants