CAMEL-22894: Split SimpleExpressionBuilder into domain-aligned builder classes#23719
CAMEL-22894: Split SimpleExpressionBuilder into domain-aligned builder classes#23719ammachado wants to merge 2 commits into
Conversation
…r classes Replace the monolithic SimpleExpressionBuilder (3,523 lines, 100+ static methods) with seven focused builder classes: - CollectionExpressionBuilder: list, map, filter, sort, set-header, etc. - DateExpressionBuilder: date/time expressions with offset support - FileExpressionBuilder: file name, path, size, extension, etc. - MathExpressionBuilder: abs, floor, ceil, sum, min, max, average - MiscExpressionBuilder: uuid, random, type, hash, convert, etc. - OgnlExpressionBuilder: OGNL body/header/variable/exchange navigation - StringExpressionBuilder: pad, trim, substring, replace, contains, etc. KeyedOgnlExpressionAdapter (inner class) moves to OgnlExpressionBuilder. OFFSET_PATTERN static field moves to DateExpressionBuilder. All 22 function factories and ast/SimpleFunctionExpression updated to import their respective domain builder. AttachmentExpressionBuilder (camel-attachments) updated to use OgnlExpressionBuilder.KeyedOgnlExpressionAdapter. Pure mechanical refactor: no behavioral change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> rh-pre-commit.version: 2.4.0 rh-pre-commit.check-secrets: ENABLED
…r split - shuffleExpression.toString() returned "reverse(...)" due to a copy-paste error; now returns "shuffle(...)" - mapExpression.toString() printed compiled Expression[] object refs instead of the source String[] pairs; now prints the source pairs - collateExpression(String,String) overwrote the 'exp' field inside evaluate(), wrapping an already-grouped iterator on every call and causing a data race under concurrent route execution; fixed by using a local variable for the grouped expression - throwExceptionExpression's catch(Exception) block caught the RuntimeException it had just thrown and double-wrapped it, breaking typed onException handlers; restructured so RuntimeExceptions propagate unwrapped - skipExpression(String,String) unboxed a potentially-null Integer without a null check; now throws IllegalArgumentException with a clear message - padExpression returned NPE when the string or width expression was null; now returns null for a null string and throws IllegalArgumentException for a null width - floor() and ceil() cast Math.floor/ceil to int, silently overflowing for values outside Integer range; now returns long - range(max) in the csimple code path used min=0 while the simple interpreter used min=1; unified to min=1 to match documented behaviour Tests added to document each pre-existing bug and verify the fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> rh-pre-commit.version: 2.4.0 rh-pre-commit.check-secrets: ENABLED
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
|
🧪 CI tested the following changed modules:
Build reactor — dependencies compiled but only changed modules were tested (3 modules)
|
davsclaus
left a comment
There was a problem hiding this comment.
Reviewed the final step of the CAMEL-22894 refactoring series. 34 files changed, splitting the 3523-line SimpleExpressionBuilder monolith into 7 domain-aligned builder classes, plus 8 pre-existing bug fixes.
Structural split verified:
- All 18 function factory files updated to import from the correct new builder class
camel-attachments(only external reference) updatedSimpleFunctionExpressionfile references updated- No remaining references to the deleted
SimpleExpressionBuilder(verified with grep) - Two logical commits properly separated: structural split, then bug fixes
Bug fixes verified against old code:
throwExceptiondouble-wrapping: oldcatch(Exception)caught the just-thrownRuntimeExceptionand re-wrapped it, breaking typedonExceptionhandlerscollatefield overwrite:exp = groupIteratorExpression(exp, ...)mutated state, causing double-wrapping on reuse and a data race under concurrent executionshuffle.toString()copy-paste error: returned"reverse(...)"instead of"shuffle(...)"map.toString(): printed compiledExpression[]object refs instead of source pairsfloor/ceiloverflow:(int) Math.floor(...)silently overflowed for values > Integer.MAX_VALUE — fixed to(long)skip/padnull safety: NPE on null unboxing — now throwsIllegalArgumentExceptionwith clear messagerange(max)csimple/simple inconsistency: csimple used min=0, simple used min=1 — unified to min=1
Each bug fix has a dedicated test documenting the pre-existing bug and verifying the correction.
Non-blocking suggestions:
- Consider an upgrade guide note mentioning the
SimpleExpressionBuilderremoval and new class names — the class is internal (camel-core-languages, notcamel-api) but advanced users building custom Simple functions might reference it directly - The
floor/ceilreturn type change frominttolongandrange(N)starting at 1 instead of 0 in csimple are behavioral changes worth noting in the upgrade guide
This review does not replace specialized AI review tools (CodeRabbit, Sourcery) or static analyzers (SonarCloud).
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Claus Ibsen
Description
SimpleExpressionBuilderhad grown into a ~3500-line monolith housing expression factories for every domain in the simple language. This PR splits it into six focused, domain-aligned builder classes:CollectionExpressionBuilderDateExpressionBuilderFileExpressionBuilderMathExpressionBuilderMiscExpressionBuilderOgnlExpressionBuilderStringExpressionBuilderSimpleExpressionBuilderitself is removed; each function factory (*FunctionFactory) now imports from the appropriate domain class.A subsequent commit fixes several pre-existing bugs that were surfaced and reviewed after the split:
shuffleExpression.toString()returned"reverse(...)"(copy-paste error) — fixed to"shuffle(...)"mapExpression.toString()printed compiledExpression[]object refs instead of source pairs — fixedcollateExpression(String, String)overwrote theexpfield insideevaluate(), double-wrapping the iterator on reuse and creating a data race under concurrent route execution — fixed using a local variablethrowExceptionExpressioncatch block caught theRuntimeExceptionit had just thrown and double-wrapped it, breaking typedonExceptionhandlers — restructured soRuntimeExceptions propagate unwrappedskipExpression(String, String)unboxed a potentially-nullIntegerwithout a null check — now throwsIllegalArgumentExceptionwith a clear messagepadExpressionthrewNullPointerExceptionwhen the string or width expression resolved to null — now returns null for a null string and throwsIllegalArgumentExceptionfor a null widthfloor()andceil()castMath.floor/Math.ceiltoint, silently overflowing for values outsideIntegerrange — fixed to returnlong${range(max)}in the csimple code path usedmin=0while the simple interpreter usedmin=1— unified tomin=1to match documented behaviourTests added to each fix to document the pre-existing bug and verify the correction.
Target
mainbranch)Tracking
JIRA: https://issues.apache.org/jira/browse/CAMEL-22894
Apache Camel coding standards and style
mvn clean install -DskipTestslocally from root folder and I have committed all auto-generated changes.Claude Code on behalf of Adriano Machado