Skip to content

[9.x.x] Convert RuleGenerator, ReportGenerator and FunctionGenerator to Java and migrate them to the fluent API - #1375

Merged
davidalk merged 9 commits into
finos:9.x.xfrom
REGnosys:xtend-to-java/rule-generator-9xx
Aug 27, 2026
Merged

[9.x.x] Convert RuleGenerator, ReportGenerator and FunctionGenerator to Java and migrate them to the fluent API#1375
davidalk merged 9 commits into
finos:9.x.xfrom
REGnosys:xtend-to-java/rule-generator-9xx

Conversation

@davidalk

@davidalk davidalk commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

9.x.x backport of #1293.

FunctionGenerator's operation-to-meta logic is backported without the choice-type implied-key handling from #1252: that logic needs RosettaDeepFeatureCall.feature widened from Attribute to RosettaFeature, an EMF model/API change that hasn't been backported to 9.x.x (it would change the generated getFeature() return type for anything compiled against 9.x.x's EMF classes). FunctionOperationGeneratorTest.java, which only exercises that logic, is dropped for the same reason — it isn't present on 9.x.x today either.

Everything else — the Xtend→Java conversion and the fluent CodeRenderer API migration for RuleGenerator, ReportGenerator, FunctionGenerator, and the DeepPathUtilGenerator alignment — carries over as-is.

The last commit updates CalculationFunctionGeneratorTest (9.x.x's still-Xtend equivalent of main's FunctionOperationGeneratorTest, never migrated here, so I missed it while scoping the initial coverage check): FunctionGenerator's new output has different whitespace conventions than the old Xtend-template generator, so this hardcoded-expected-string test needed its expectations regenerated. No generator behaviour changed — full mvn clean install now passes with 0 failures across all modules.

Test coverage per production file changed

  • reports/RuleGenerator.java (+ deleted .xtend) — RosettaRuleGeneratorTest (24/24 pass)
  • reports/ReportGenerator.java (+ deleted .xtend) — ReportGeneratorTest (5/5 pass)
  • function/FunctionGenerator.java (+ deleted .xtend) — FunctionGeneratorTest (148/148), FunctionGeneratorMetaTest (47/47), CalculationFunctionGeneratorTest (9/9), ListOperationTest (71/71), RosettaBinaryOperationTest (11/11)
  • expression/DeepPathUtilGenerator.javaDeepPathRegressionTest (88/88); also exercised transitively by FunctionGeneratorMetaTest
  • FluentJavaClassGenerator.java, statement/builder/JavaExpression.java, types/RGeneratedJavaClass.java, util/CodeWriterTargetStringConcatenation.java, util/TargetStringConcatenationCodeWriter.java — shared base class / rendering plumbing used by all of the above generators; exercised transitively by every test listed
  • util/FluentImportManager.java (new) — exercised via FunctionGeneratorHelper (test helper used by FunctionGeneratorTest, FunctionGeneratorMetaTest, ListOperationTest, RosettaBinaryOperationTest)

Also ran JavaNameEscapingTest (115/115) since the name-escaping regression fixtures under functions/ shifted.

Test plan

  • mvn clean install -o — full multi-module build, all tests, 0 failures

SimonCockx and others added 9 commits August 27, 2026 11:16
Move RuleGenerator from the deprecated XtendJavaClassGenerator base class to
FluentRObjectJavaClassGenerator, so generateClass returns a CodeRenderer.

The class body is still produced as an Xtend template by the (not-yet-migrated)
FunctionGenerator, so add a reusable compatibility bridge, LegacyTemplateRenderer,
that adapts a legacy StringConcatenationClient class body into a CodeRenderer.
Layout is produced by Xtend's StringConcatenation (as the legacy
ImportManagerExtension#buildClass does), while embedded JavaClasses and Methods
are resolved against the RecordingCodeWriter so the fluent file builder collects
their imports and resolves their identifiers. Output is byte-identical, letting
generators move onto the fluent API one at a time, before their templates have
been rewritten with the fluent CodeWriter API.
Like RuleGenerator, move ReportGenerator from the deprecated
RObjectJavaClassGenerator base class to FluentRObjectJavaClassGenerator, with
generateClass returning a CodeRenderer. The class body is still produced as an
Xtend template by FunctionGenerator, so wrap it with LegacyTemplateRenderer.

The @RosettaReport and @RuneLabelProvider annotation bodies, previously Xtend
'''...''' templates, are built as StringConcatenationClient instances (the same
idiom already used in AliasUtil); the label-provider class is embedded as an
object so its import is registered.
Ported from finos#1293, with the choice-type implied-key
handling (finos#1252) omitted: that logic depends on
RosettaDeepFeatureCall.feature being widened from Attribute to
RosettaFeature, an EMF API change that hasn't been backported to
9.x.x. FunctionOperationGeneratorTest.java, which only tests that
logic, is dropped for the same reason.
Make classBody return a CodeRenderer (like dispatchClassBody and the original
StringConcatenationClient-returning classBody) instead of being a void method
taking a CodeWriter, so rBuildClass returns it directly.

Render the default class declaration inline (class XDefault extends ...) instead
of via RGeneratedJavaClass#asClassDeclaration, which lets defaultClass be typed
as JavaClass<?> and removes one legacy-template-fragment bridge usage.
Change RGeneratedJavaClass#asClassDeclaration to return a dual TargetLanguage
representation that renders via the fluent CodeWriter API and, through a reverse
bridge, still appends to the legacy Xtend template machinery. FunctionGenerator
now renders the default class via asClassDeclaration() again (so defaultClass is
an RGeneratedJavaClass<?>), and the not-yet-migrated generators that embed it in
Xtend templates keep working unchanged.

Extract the reverse bridge TargetStringConcatenationCodeWriter from JavaExpression
into a reusable public class (the counterpart of CodeWriterTargetStringConcatenation).

For consistency with FunctionGenerator#classBody, DeepPathUtilGenerator#renderClass
now returns a CodeRenderer instead of being a void method taking a CodeWriter.
…sion

FluentJavaClassGenerator#buildClass had been made public so
FunctionGeneratorHelper could call it directly to assemble a single
function's class file from its CodeRenderer. That widened an internal
detail of the generator base class purely to serve one external caller,
instead of exposing an independently-usable service the way
ImportManagerExtension always was for the legacy Xtend path.

Extract buildClass into FluentImportManager, injected the same way
XtendJavaClassGenerator injects ImportManagerExtension, and have
FunctionGeneratorHelper depend on it directly instead of reaching
through the generator instance. buildClass reverts to protected.
…tionGenerator output format

FunctionGenerator's fluent-API migration (previous commit) changed the
generator's whitespace conventions (4-space indent, no blank line after
an opening brace, condensed Javadoc). This still-Xtend test file
(never migrated on 9.x.x, unlike its main-branch counterpart
FunctionOperationGeneratorTest) asserts against hardcoded expected
Java source, so it needed its expectations regenerated to match.

No generator or production logic changed; only the literal expected
strings were regenerated from a passing test run's actual output.
@davidalk
davidalk merged commit 8cc9a8f into finos:9.x.x Aug 27, 2026
4 checks passed
@davidalk
davidalk deleted the xtend-to-java/rule-generator-9xx branch August 27, 2026 13:49
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.

3 participants