-
Notifications
You must be signed in to change notification settings - Fork 5.9k
[V2] feat(delete-form,modify-form,fill-form,extract-forms): add delete, modify, fill, and extract form functionality #4830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: V2
Are you sure you want to change the base?
Conversation
- Relocated `FormUtils` from `common` to `proprietary` module - Renamed class to `FormCopyUtils` - Updated class annotations and import paths in line with its new scope Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
…yUtils - Removed reflection-based invocation of `refreshAppearances` - Replaced it with direct method call for better clarity and maintainability - Adjusted exception handling to catch `NoSuchMethodError` instead of `NoSuchMethodException` Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
- Updated method names from `supportsDefinitionCreation` to `doesNotsupportsDefinitionCreation` to better reflect functionality - Simplified multi-case switch statements in `FormUtils` for readability - Removed unused `flattenFormOnly` method to reduce code clutter - Adjusted `requirePdf` method signature by removing redundant parameter - Modified `ensureCheckBoxAppearance` to be static for consistent behavior across instances Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR performs a major refactoring of form-related utilities, moving FormUtils from the common module to the proprietary module and significantly expanding its functionality. The changes introduce comprehensive PDF form field manipulation capabilities including extraction, modification, deletion, and filling operations.
Key Changes
- Moved and expanded FormUtils: Relocated from
app/commontoapp/proprietarywith 1,762 lines of new functionality for form field operations - New API controllers: Added
FormFillControllerandFormPayloadParserproviding REST endpoints for form operations - New type system: Introduced
FormFieldTypeSupportenum for type-safe field handling across different PDF form field types - Removed form copying from MultiPageLayoutController: Form field transformation functionality removed from the core module (proprietary-only feature)
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
FormUtils.java (proprietary) |
Complete rewrite with extensive form field extraction, modification, deletion, and filling capabilities |
FormFieldTypeSupport.java |
New enum-based type handler for different PDF form field types (text, checkbox, radio, combobox, listbox, signature, button) |
FormCopyUtils.java |
New utility for copying and transforming form fields across multi-page layouts |
FormFillController.java |
New REST controller exposing form operations via /api/v1/form/* endpoints |
FormPayloadParser.java |
New parser handling flexible JSON payload formats for form operations |
FormUtilsTest.java |
New test file (disabled, deferred to integration tests) |
MultiPageLayoutController.java |
Removed form field copying logic (moved to proprietary module) |
FormUtils.java (common) |
Deleted - functionality moved to proprietary module |
RegexPatternUtils.java |
Added patterns for form field name parsing and validation |
EndpointConfiguration.java |
Registered new form endpoints in "Other" group |
UserAuthenticationFilter.java |
Minor comment formatting fix |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
app/proprietary/src/main/java/stirling/software/proprietary/util/FormUtils.java
Outdated
Show resolved
Hide resolved
app/proprietary/src/main/java/stirling/software/proprietary/util/FormUtils.java
Outdated
Show resolved
Hide resolved
app/proprietary/src/main/java/stirling/software/proprietary/util/FormUtils.java
Show resolved
Hide resolved
app/proprietary/src/main/java/stirling/software/proprietary/util/FormUtils.java
Show resolved
Hide resolved
app/proprietary/src/main/java/stirling/software/proprietary/util/FormUtils.java
Outdated
Show resolved
Hide resolved
app/proprietary/src/main/java/stirling/software/proprietary/util/FormUtils.java
Outdated
Show resolved
Hide resolved
app/proprietary/src/main/java/stirling/software/proprietary/util/FormCopyUtils.java
Show resolved
Hide resolved
app/proprietary/src/main/java/stirling/software/proprietary/util/FormCopyUtils.java
Show resolved
Hide resolved
- Added null checks for `alternate`, `tooltipLabel`, and options in `FormUtils` - Improved boundary checks in `FormCopyUtils` to prevent out-of-bounds errors - Simplified widget mapping process in `FormCopyUtils` with early exits Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
Description of Changes
TLDR
/api/v1/form/fields,/fill,/modify-fields, and/delete-fieldsendpoints for end-to-end AcroForm workflows.FormUtilswith strict type handling.FormPayloadParserfor resilient JSON parsing across legacy flat payloads and new structured payloads.FormCopyUtilsplusFormFieldTypeSupportto create, clone, and normalize widget properties when transforming forms.Implementation Details
FormFillControllerupdates the new multipart APIs, and streams updated documents or metadata responses.FormUtilsnow owns extraction, template building, value application (including flattening strategies), and field CRUD helpers used by the controller endpoints.FormPayloadParsernormalizes request bodies: accepts flat key/value maps, combinedfieldsarrays, or nested templates, returning deterministic LinkedHashMap ordering for repeatable fills.FormFieldTypeSupportencapsulates per-type creation, value copying, default appearance, and option handling; utilized by both modification flows andFormCopyUtilstransformations.FormCopyUtilsexposes shared routines for making widgets across documentsAPI Surface (Multipart Form Data)
POST /api/v1/form/fields-> returnsFormUtils.FormFieldExtractionwith orderedFormFieldInforecords plus a fill template.POST /api/v1/form/fill-> applies parsed values viaFormUtils.applyFieldValues; optionalflattenrenders appearances while respecting strict validation.POST /api/v1/form/modify-fields-> updates existing fields in-place usingFormUtils.modifyFormFieldswith definitions parsed fromupdatespayloads.POST /api/v1/form/delete-fields-> removes named fields afterFormPayloadParser.parseNameListdeduplication and validation.Individual endpoints:
Data Validation & Type Safety
detectFieldType) and choice option resolution ensure only supported values are written; checkbox mapping uses export states and boolean heuristics.filterChoiceSelections/filterSingleChoiceSelectionto reject invalid entries and provide actionable logs.setTextValueto merge inline formatting resources and regenerate appearances when necessary.applyFieldValuessupports strict mode (default) to raise when unknown fields are supplied, preventing silent data loss.Automation Workflow Support
The
/filland/fieldsendpoints are designed to work together for automated form processing. The workflow is straightforward: extract the form structure, modify the values, and submit for filling.How It Works:
/fieldsendpoint extracts all form field metadata from your PDF/fillendpoint accepts this same JSON structure to populate the formExample Workflow:
How to Fill the
templateJSONThe
template(your data) is filled by creating key-value pairs that match the "rules" defined in thefieldsarray (the schema).Find the Field
name: Look in thefieldsarray for thenameof the field you want to fill.{"name": "Agent of Dependent", "type": "text", ...}Use
nameas the Key: Thisnamebecomes the key (in quotes) in yourtemplateobject.{"Agent of Dependent": ...}Find the
type: Look at thetypefor that same field. This tells you what kind of value to provide."type": "text"requires a string (e.g.,"John Smith")."type": "checkbox"requires a boolean (e.g.,trueorfalse)."type": "combobox"requires a string that exactly matches one of its"options"(e.g.,"Choice 1").Add the Value: This matching value becomes the value for your key.
Correct Examples
For a Textbox:
{"name": "Agent of Dependent", "type": "text", ...}{"Agent of Dependent": "Mary Jane"}For a Checkbox:
{"name": "Option 2", "type": "checkbox", ...}{"Option 2": true}For a Dropdown (Combobox):
{"name": "Dropdown2", "type": "combobox", "options": ["Choice 1", "Choice 2", ...] ...}{"Dropdown2": "Choice 1"}Incorrect Examples (These Will Error)
{"Option 2": "Checked"}checkboxand expectstrueorfalse, not a string.{"Dropdown2": "Choice 99"}"Choice 99"is not listed in theoptionsfor "Dropdown2".For people manually doing this
For users filling forms manually, there's a simplified format that focuses only on field names and values:
{ "FullName": "", "ID": "", "Gender": "Off", "Married": false, "City": "[]" }This format is easier to work with when you're manually editing the JSON. You can skip the full metadata structure (type, label, required, etc.) and just provide the field names with their values.
Important caveat: Even though the type information isn't visible in this simplified format, type validation is still enforced by PDF viewers. This simplified format just makes manual editing more convenient while maintaining data integrity.
Please note: this suffers from: https://issues.apache.org/jira/browse/PDFBOX-5962
Closes #237
Closes #3569
Checklist
General
Documentation
Translations (if applicable)
scripts/counter_translation.pyUI Changes (if applicable)
Testing (if applicable)