feat(api): add toBuilder() to DocumentRequest sealed base - #654
Conversation
Lombok's @SuperBuilder(toBuilder = true) only emits toBuilder() on the concrete request subtypes, so it was unreachable through the abstract DocumentRequest (and intermediate ChunkDocumentRequest) supertype. This forced callers to inject a source/target inside a concrete-type dispatch switch. Declare an abstract toBuilder() on DocumentRequest returning the generic DocumentRequest.Builder<?, ?>, which the Lombok-generated concrete toBuilder() methods satisfy as covariant overrides. ChunkDocumentRequest adds a narrowing override returning its own builder. This lets callers clone-and-modify polymorphically: DocumentRequest withSource = request.toBuilder().source(source).build(); Assisted-By: Claude Code <noreply@anthropic.com> Signed-off-by: Eric Deandrea <eric.deandrea@ibm.com>
There was a problem hiding this comment.
Pull request overview
This PR extends the docling-serve-api request model hierarchy by making toBuilder() reachable from the sealed base types (DocumentRequest, plus the intermediate ChunkDocumentRequest). This enables clone-and-modify workflows (e.g., injecting a source/target) without switching on the concrete request subtype, improving ergonomics for polymorphic dispatch code.
Changes:
- Added an abstract
toBuilder()contract toDocumentRequestreturningDocumentRequest.Builder<?, ?>, relying on Lombok’s generated concretetoBuilder()methods to satisfy it via covariant overrides. - Added a narrowing abstract override on
ChunkDocumentRequestreturningChunkDocumentRequest.Builder<?, ?>. - Added tests validating base-type
toBuilder()reachability and that round-tripping preserves concrete runtime types; updated “What’s New” docs.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| docs/src/doc/docs/whats-new.md | Documents the new ability to call toBuilder() via the DocumentRequest base type. |
| docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/request/DocumentRequest.java | Declares base-type toBuilder() and documents polymorphic clone-and-modify usage. |
| docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/ChunkDocumentRequest.java | Adds a narrowing toBuilder() override for chunk request subtypes. |
| docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/request/DocumentRequestTests.java | Adds coverage for base-type toBuilder() usage and concrete-type preservation across all request subtypes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
:java_duke: JaCoCo coverage report
|
|
||||||||||||||
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
|
🎉 This issue has been resolved in |
What
Adds
toBuilder()to theDocumentRequestsealed base (and the intermediateChunkDocumentRequest) so a request can be cloned-and-modified through the base type.Why
Lombok's
@SuperBuilder(toBuilder = true)only emits a publictoBuilder()on the concrete request subtypes (ConvertDocumentRequest,BatchConvertDocumentRequest,HierarchicalChunkDocumentRequest,HybridChunkDocumentRequest) — never on the abstractDocumentRequestorChunkDocumentRequest.As a result, given a
DocumentRequest-typed reference, there was no way to inject asource/targetwithout first pattern-matching on the concrete type inside a dispatch switch, e.g.:How
DocumentRequestdeclarespublic abstract DocumentRequest.Builder<?, ?> toBuilder();. The Lombok-generated concretetoBuilder()methods (returningConvertDocumentRequest.Builder<?, ?>etc.) satisfy it as covariant overrides — no field moves or builder rewrites needed, sincesources/targetalready live on the base.ChunkDocumentRequestadds a narrowing@OverridereturningChunkDocumentRequest.Builder<?, ?>.Callers can now inject a source once, polymorphically, before dispatching:
Notes
$fillValuesFromInstanceIntoBuilderfield-copy helper; the existingtoBuilderPreservesSourcesAndTargettest still passes.docs/src/doc/docs/whats-new.mdupdated.Tests
Added to
DocumentRequestTests:toBuilderReachableThroughBaseType— injects a source through aDocumentRequestreference and verifies sources/target.toBuilderThroughBaseTypePreservesConcreteType— round-trips all four concrete subtypes through the base-typetoBuilder()and asserts the concrete runtime type is preserved.