Skip to content

input field top/bottom comments#410

Merged
rkrenn merged 8 commits intomasterfrom
top_comment
Mar 17, 2026
Merged

input field top/bottom comments#410
rkrenn merged 8 commits intomasterfrom
top_comment

Conversation

@rkrenn
Copy link
Copy Markdown
Collaborator

@rkrenn rkrenn commented Mar 17, 2026

image image image

Summary by CodeRabbit

  • New Features

    • Input fields now support separate top and bottom comments, shown above or below inputs across forms, PDFs, inquiries, and proband lists.
  • Chores

    • Database schema, localization keys, UI labels, PDF rendering, import/export, and internal mappings updated to persist and display the dual-comment model consistently.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 17, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 015ff6e3-196c-4da7-98a3-6153205b8ca6

📥 Commits

Reviewing files that changed from the base of the PR and between 274c581 and 1e01ee1.

📒 Files selected for processing (1)
  • core/src/main/java/org/phoenixctms/ctsms/domain/InputFieldDaoImpl.java

📝 Walkthrough

Walkthrough

This pull request refactors input field comments by splitting a single COMMENT_L10N_KEY column into two separate columns: TOP_COMMENT_L10N_KEY and BOTTOM_COMMENT_L10N_KEY. The change cascades across the database schema, domain models, service layer, PDF rendering components, test utilities, Excel processing, web UI configuration, and resource bundles.

Changes

Cohort / File(s) Summary
Database Schema
core/db/schema-create.sql, core/db/schema-set-version.sql, core/db/schema-up-master.sql
Removed COMMENT_L10N_KEY from INPUT_FIELD and added TOP_COMMENT_L10N_KEY + BOTTOM_COMMENT_L10N_KEY. Bumped DB version 010901001010901002 and added migration logic to add/rename columns.
Domain & DAO
core/src/main/java/.../InputField.java, core/src/main/java/.../InputFieldDaoImpl.java
Entity/DAO mapping updated to read/write separate top/bottom comment L10n keys instead of one comment key; new setters/getters added.
Service & Utility Layer
core/src/main/java/.../service/shared/InputFieldServiceImpl.java, core/src/main/java/.../util/ServiceUtil.java, core/src/main/java/.../vocycle/InputFieldGraph.java
Cloning, preset initialization and VO conversions updated to copy/populate top and bottom comment fields in place of the single comment.
PDF Rendering & Labels
core/src/main/java/.../pdf/*.java, core/src/main/resources/ctsms-*-pdf-labels*.properties
Replaced single comment label API with TOP/BOTTOM variants (constants and methods). Updated PDF rendering to render top comment above and bottom comment below fields; updated PDF resource keys.
Excel Reader/Writer
core/src/exec/java/.../xls/InputFieldRowProcessor.java, InputFieldRowWriter.java
Replaced single comment column index with TOP_COMMENT_COLUMN_INDEX and BOTTOM_COMMENT_COLUMN_INDEX; shifted downstream indices and included both comments in hash/IO.
Test / Demo Providers
core/src/exec/java/.../DemoDataProvider.java, core/src/test/java/.../TestDataProvider.java
Renamed comment parameter to bottomComment in many createXField helpers and updated setters to setBottomComment(...).
Web UI Models & Beans
web/src/main/java/.../inputfield/InputFieldBean.java, InputFieldConfig.java, InputFieldInVOConfig.java, InputFieldOutVOConfigBase.java, InputModel.java
Replaced single field-comment accessor with getTopComment()/getBottomComment() and added corresponding setters and emptiness checks.
Web Message Codes & Resources
web/src/main/java/.../web/util/MessageCodes.java, web/src/main/resources/org/phoenixctms/ctsms/web/*.properties
Replaced INPUT_FIELD_COMMENT_PRESET and related keys with INPUT_FIELD_TOP_COMMENT_PRESET and INPUT_FIELD_BOTTOM_COMMENT_PRESET. Added top/bottom comment labels/tooltips and removed legacy single-comment keys.
Web Templates
web/src/main/webapp/META-INF/includes/*inputField*.xhtml, inputFieldRow.xhtml
Added top-comment textarea and bindings (inputFieldBean.in.topComment); updated bottom-comment bindings to inputFieldBean.in.bottomComment; adjusted conditional rendering and row classes.
UML / MDA Profiles
mda/src/main/uml/...profile.uml
Bulk internal XMI ID and metadata updates across UML profiles (identifier renames and minor ordering changes); no semantic API changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • fladi
  • 01hasenberger

Poem

🐰 Hop, hop, a comment split in two,
Top above and bottom below, anew,
Fields now wear a twin-lined tune,
Database, PDF, and UI in tune,
I nibble bugs and dance — hooray for you!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: splitting a single input field comment into top and bottom variants across the entire codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch top_comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can validate your CodeRabbit configuration file in your editor.

If your editor has YAML language server, you can enable auto-completion and validation by adding # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json at the top of your CodeRabbit configuration file.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
core/src/test/java/org/phoenixctms/ctsms/TestDataProvider.java (1)

280-287: Consider exposing topComment in test helper APIs.

At Line 280-Line 287 (and similarly in the other create*Field helpers), fixtures can now set only bottomComment. Adding optional topComment parameters/overloads would let tests cover both new comment positions.

Suggested pattern
-public InputFieldOutVO createIntegerField(String name, String category, String title, String bottomComment, Long longPreset, Long lowerLimit,
+public InputFieldOutVO createIntegerField(String name, String category, String title, String topComment, String bottomComment, Long longPreset, Long lowerLimit,
         Long upperLimit, String validationErrorMessage) throws Exception {
    InputFieldInVO newInputField = new InputFieldInVO();
    ...
+   newInputField.setTopComment(topComment);
    newInputField.setBottomComment(bottomComment);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/src/test/java/org/phoenixctms/ctsms/TestDataProvider.java` around lines
280 - 287, The test helper createIntegerField currently accepts only
bottomComment; add an optional topComment parameter (or an overloaded variant)
to createIntegerField and mirror the change across other create*Field helpers
(e.g., createStringField/createDateField) so fixtures can set both comment
positions; update the InputFieldInVO population to call
setTopComment(topComment) when provided and preserve existing behavior when
null/absent.
core/src/main/java/org/phoenixctms/ctsms/pdf/InputFieldPDFBlock.java (1)

112-140: Consider extracting duplicated comment-resolution logic.

Top/bottom methods are structurally identical apart from key/label access. A small shared helper would reduce future drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/src/main/java/org/phoenixctms/ctsms/pdf/InputFieldPDFBlock.java` around
lines 112 - 140, Extract the duplicated logic from getInputFieldTopComment and
getInputFieldBottomComment into a single private helper (e.g.,
resolveInputFieldComment) that takes the L10n key and a reference to the
label-wrapping method; inside the helper, use inputField.getLocalized() and
L10nUtil.getInputFieldComment(getLabelLocale(), key) or the raw key, fall back
to "" when null, and then call the provided label formatter; update
getInputFieldTopComment to call
resolveInputFieldComment(inputField.getTopCommentL10nKey(),
this::getInputFieldTopCommentLabel) and getInputFieldBottomComment to call
resolveInputFieldComment(inputField.getBottomCommentL10nKey(),
this::getInputFieldBottomCommentLabel) so getInputFieldTopCommentLabel and
getInputFieldBottomCommentLabel remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java`:
- Around line 31-46: The code currently uses fixed static indices (e.g.,
TOP_COMMENT_COLUMN_INDEX, BOTTOM_COMMENT_COLUMN_INDEX, PRESET_COLUMN_INDEX)
which will corrupt legacy one-comment XLS templates when processed by
InputFieldRowProcessor.processRow(); update the importer so templates are
validated or remapped before row processing: override processHeaderRow() in
InputFieldRowProcessor (or modify init()) to inspect header column names/count
(using getColumnValue()) and either (a) validate the template version/expected
column count and throw a clear exception from XlsImporterBase.readRows() before
processRow() runs, or (b) detect the legacy layout (missing
TOP_COMMENT/BOTTOM_COMMENT headers or fewer columns) and populate a dynamic
column-mapping table used by processRow() instead of the static
TOP_COMMENT_COLUMN_INDEX/PRESET_COLUMN_INDEX constants; also ensure
out-of-bounds getColumnValue() results are treated as a validation error rather
than silently null so mismatches are not masked.

In `@core/src/main/java/org/phoenixctms/ctsms/domain/InputFieldDaoImpl.java`:
- Around line 425-426: The code in InputFieldDaoImpl mistakenly assigns bottom
comment twice (target.setBottomComment(source.getBottomCommentL10nKey()))
leaving topComment unset; replace the second call with
target.setTopComment(source.getTopCommentL10nKey()) so the top comment is
hydrated from source and not lost on edits.

In `@core/src/main/java/org/phoenixctms/ctsms/pdf/InputFieldPDFBlock.java`:
- Around line 112-123: The top/bottom comment getters are passing null/empty
strings into label formatter methods causing static template text to render;
update getInputFieldTopComment (and the corresponding bottom comment method) to
trim and check for blank (e.g., comment == null || comment.trim().isEmpty())
after localization and return an empty string (or skip calling
getInputFieldTopCommentLabel/getInputFieldBottomCommentLabel) when blank,
otherwise call the formatter with the non-empty comment.

---

Nitpick comments:
In `@core/src/main/java/org/phoenixctms/ctsms/pdf/InputFieldPDFBlock.java`:
- Around line 112-140: Extract the duplicated logic from getInputFieldTopComment
and getInputFieldBottomComment into a single private helper (e.g.,
resolveInputFieldComment) that takes the L10n key and a reference to the
label-wrapping method; inside the helper, use inputField.getLocalized() and
L10nUtil.getInputFieldComment(getLabelLocale(), key) or the raw key, fall back
to "" when null, and then call the provided label formatter; update
getInputFieldTopComment to call
resolveInputFieldComment(inputField.getTopCommentL10nKey(),
this::getInputFieldTopCommentLabel) and getInputFieldBottomComment to call
resolveInputFieldComment(inputField.getBottomCommentL10nKey(),
this::getInputFieldBottomCommentLabel) so getInputFieldTopCommentLabel and
getInputFieldBottomCommentLabel remain unchanged.

In `@core/src/test/java/org/phoenixctms/ctsms/TestDataProvider.java`:
- Around line 280-287: The test helper createIntegerField currently accepts only
bottomComment; add an optional topComment parameter (or an overloaded variant)
to createIntegerField and mirror the change across other create*Field helpers
(e.g., createStringField/createDateField) so fixtures can set both comment
positions; update the InputFieldInVO population to call
setTopComment(topComment) when provided and preserve existing behavior when
null/absent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6edc0a2b-44d0-47f4-9a50-e4edb464efd6

📥 Commits

Reviewing files that changed from the base of the PR and between 90c0f84 and 274c581.

⛔ Files ignored due to path filters (2)
  • core/src/test/resources/ecrfs.xls is excluded by !**/*.xls
  • core/src/test/resources/input_fields.xls is excluded by !**/*.xls
📒 Files selected for processing (51)
  • core/db/schema-create.sql
  • core/db/schema-set-version.sql
  • core/db/schema-up-master.sql
  • core/src/exec/java/org/phoenixctms/ctsms/executable/DemoDataProvider.java
  • core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java
  • core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowWriter.java
  • core/src/main/java/org/phoenixctms/ctsms/domain/InputFieldDaoImpl.java
  • core/src/main/java/org/phoenixctms/ctsms/pdf/EcrfPDFBlock.java
  • core/src/main/java/org/phoenixctms/ctsms/pdf/EcrfPDFLabelCodes.java
  • core/src/main/java/org/phoenixctms/ctsms/pdf/InputFieldPDFBlock.java
  • core/src/main/java/org/phoenixctms/ctsms/pdf/InquiriesPDFBlock.java
  • core/src/main/java/org/phoenixctms/ctsms/pdf/InquiriesPDFLabelCodes.java
  • core/src/main/java/org/phoenixctms/ctsms/pdf/ProbandListEntryTagsPDFBlock.java
  • core/src/main/java/org/phoenixctms/ctsms/pdf/ProbandListEntryTagsPDFLabelCodes.java
  • core/src/main/java/org/phoenixctms/ctsms/service/shared/InputFieldServiceImpl.java
  • core/src/main/java/org/phoenixctms/ctsms/util/ServiceUtil.java
  • core/src/main/java/org/phoenixctms/ctsms/vocycle/InputFieldGraph.java
  • core/src/main/resources/ctsms-ecrf-pdf-labels.properties
  • core/src/main/resources/ctsms-ecrf-pdf-labels_de.properties
  • core/src/main/resources/ctsms-inquiries-pdf-labels.properties
  • core/src/main/resources/ctsms-inquiries-pdf-labels_de.properties
  • core/src/main/resources/ctsms-probandlistentrytags-pdf-labels.properties
  • core/src/main/resources/ctsms-probandlistentrytags-pdf-labels_de.properties
  • core/src/test/java/org/phoenixctms/ctsms/TestDataProvider.java
  • mda/src/main/uml/UML_Standard_Profile.MagicDraw_Profile.DSL_Customization.profile.uml
  • mda/src/main/uml/UML_Standard_Profile.MagicDraw_Profile.Traceability_customization.profile.uml
  • mda/src/main/uml/UML_Standard_Profile.MagicDraw_Profile.profile.uml
  • mda/src/main/uml/UML_Standard_Profile.StandardProfileL2.profile.uml
  • mda/src/main/uml/UML_Standard_Profile.StandardProfileL3.profile.uml
  • mda/src/main/uml/UML_Standard_Profile.Validation_Profile.profile.uml
  • mda/src/main/uml/andromda-common.andromda-persistence.profile.uml
  • mda/src/main/uml/andromda-common.andromda-service.profile.uml
  • mda/src/main/uml/andromda-common.profile.uml
  • mda/src/main/uml/andromda-presentation.profile.uml
  • mda/src/main/uml/andromda-process.profile.uml
  • mda/src/main/uml/andromda-webservice.profile.uml
  • mda/src/main/uml/andromda-xml.profile.uml
  • mda/src/main/uml/ctsms.uml
  • mda/src/main/uml/ctsms.xml
  • web/src/main/java/org/phoenixctms/ctsms/web/model/inputfield/InputFieldBean.java
  • web/src/main/java/org/phoenixctms/ctsms/web/model/shared/inputfield/InputFieldConfig.java
  • web/src/main/java/org/phoenixctms/ctsms/web/model/shared/inputfield/InputFieldInVOConfig.java
  • web/src/main/java/org/phoenixctms/ctsms/web/model/shared/inputfield/InputFieldOutVOConfigBase.java
  • web/src/main/java/org/phoenixctms/ctsms/web/model/shared/inputfield/InputModel.java
  • web/src/main/java/org/phoenixctms/ctsms/web/util/MessageCodes.java
  • web/src/main/resources/org/phoenixctms/ctsms/web/inputfield/labels.properties
  • web/src/main/resources/org/phoenixctms/ctsms/web/inputfield/labels_de.properties
  • web/src/main/resources/org/phoenixctms/ctsms/web/messages.properties
  • web/src/main/resources/org/phoenixctms/ctsms/web/messages_de.properties
  • web/src/main/webapp/META-INF/includes/inputfield/inputFieldMain.xhtml
  • web/src/main/webapp/META-INF/includes/shared/inputFieldRow.xhtml

Comment on lines +31 to +46
private final static int TOP_COMMENT_COLUMN_INDEX = 6;
private final static int BOTTOM_COMMENT_COLUMN_INDEX = 7;
private final static int PRESET_COLUMN_INDEX = 8;
private final static int TEXT_PRESET_COLUMN_INDEX = PRESET_COLUMN_INDEX;
private final static int BOOLEAN_PRESET_COLUMN_INDEX = PRESET_COLUMN_INDEX;
private final static int LONG_PRESET_COLUMN_INDEX = PRESET_COLUMN_INDEX;
private final static int FLOAT_PRESET_COLUMN_INDEX = PRESET_COLUMN_INDEX;
private final static int DATE_PRESET_COLUMN_INDEX = PRESET_COLUMN_INDEX;
private final static int TIME_PRESET_COLUMN_INDEX = PRESET_COLUMN_INDEX;
private final static int TIMESTAMP_PRESET_COLUMN_INDEX = PRESET_COLUMN_INDEX;
private final static int VALIDATION_ERROR_MSG_COLUMN_INDEX = 8;
private final static int PARAM_1_COLUMN_INDEX = 9;
private final static int PARAM_2_COLUMN_INDEX = 10;
private final static int PARAM_3_COLUMN_INDEX = 11;
private final static int PARAM_4_COLUMN_INDEX = 12;
private final static int PARAM_5_COLUMN_INDEX = 13;
private final static int VALIDATION_ERROR_MSG_COLUMN_INDEX = 9;
private final static int PARAM_1_COLUMN_INDEX = 10;
private final static int PARAM_2_COLUMN_INDEX = 11;
private final static int PARAM_3_COLUMN_INDEX = 12;
private final static int PARAM_4_COLUMN_INDEX = 13;
private final static int PARAM_5_COLUMN_INDEX = 14;
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILES="$(fd 'InputFieldRowProcessor.java|InputFieldRowWriter.java|XlsImporter.java|RowProcessor.java')"

echo "Relevant XLS import/export files:"
printf '%s\n' "$FILES"

echo
echo "Current fixed column layout in InputFieldRowProcessor:"
sed -n '24,70p' core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java

echo
echo "Search for header/template validation or legacy remapping:"
rg -n -C3 'template.?version|sheet.?version|header|column.?name|legacy|getColumnValue\(|TOP_COMMENT_COLUMN_INDEX|BOTTOM_COMMENT_COLUMN_INDEX' $FILES

Repository: phoenixctms/ctsms

Length of output: 50373


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking XlsImporter for version/template validation ==="
rg -n -A10 "processRow|init|version|template|header" core/src/exec/java/org/phoenixctms/ctsms/executable/xls/XlsImporter.java | head -100

echo ""
echo "=== Checking RowProcessor base class for init logic ==="
rg -n -A15 "void init|columnIndex.*=" common/src/main/java/org/phoenixctms/ctsms/fileprocessors/xls/RowProcessor.java | head -80

echo ""
echo "=== Looking for any legacy/version handling in InputFieldRowProcessor init ==="
rg -n -B3 -A20 "void init\|initHeaderCellIndex" core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java | head -120

echo ""
echo "=== Checking if column count is validated before row processing ==="
rg -n "values\.length|columnIndex|throw.*Exception" core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java | grep -E "(length|throw|Exception|MIN|MAX)" | head -20

Repository: phoenixctms/ctsms

Length of output: 121


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== XlsImporter.java size and processRow logic ==="
wc -l core/src/exec/java/org/phoenixctms/ctsms/executable/xls/XlsImporter.java
echo ""
# Look for how row processors are invoked
rg -n "new InputFieldRowProcessor|processRow|init(" core/src/exec/java/org/phoenixctms/ctsms/executable/xls/XlsImporter.java | head -30

echo ""
echo "=== RowProcessor base class ==="
wc -l common/src/main/java/org/phoenixctms/ctsms/fileprocessors/xls/RowProcessor.java
echo ""
# Read the init method area
sed -n '1,120p' common/src/main/java/org/phoenixctms/ctsms/fileprocessors/xls/RowProcessor.java

echo ""
echo "=== InputFieldRowProcessor.init() method ==="
sed -n '263,330p' core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java

Repository: phoenixctms/ctsms

Length of output: 343


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full XlsImporter.java ==="
cat core/src/exec/java/org/phoenixctms/ctsms/executable/xls/XlsImporter.java

echo ""
echo "=== RowProcessor.java (first 150 lines for init pattern) ==="
head -150 common/src/main/java/org/phoenixctms/ctsms/fileprocessors/xls/RowProcessor.java

echo ""
echo "=== InputFieldRowProcessor.init() and surrounding context ==="
sed -n '263,340p' core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java

Repository: phoenixctms/ctsms

Length of output: 15163


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if InputFieldRowProcessor overrides processHeaderRow ==="
grep -n "processHeaderRow" core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java

echo ""
echo "=== Check for any version/metadata handling in InputFieldRowProcessor ==="
grep -n "version\|metadata\|header\|template" core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java

echo ""
echo "=== Check XlsImporterBase for any pre-import validation ==="
wc -l core/src/exec/java/org/phoenixctms/ctsms/executable/xls/XlsImporterBase.java 2>/dev/null || echo "File may be in common module"
grep -n "version\|header\|template\|validate" core/src/exec/java/org/phoenixctms/ctsms/executable/xls/XlsImporterBase.java 2>/dev/null | head -20 || \
  grep -rn "version\|header.*template" common/src/main/java/org/phoenixctms/ctsms/fileprocessors/xls/XlsImporterBase.java 2>/dev/null | head -20

echo ""
echo "=== Check if there's a common XlsImporterBase with validation ==="
fd "XlsImporterBase.java" --exec cat {} \;

Repository: phoenixctms/ctsms

Length of output: 127


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Locate XlsImporterBase ==="
fd "XlsImporterBase.java"

echo ""
echo "=== Read XlsImporterBase ==="
fd "XlsImporterBase.java" -x cat {}

Repository: phoenixctms/ctsms

Length of output: 3164


Legacy one-comment XLS templates will be silently corrupted during import.

Two new fixed columns (TOP_COMMENT at index 6, BOTTOM_COMMENT at index 7) shift every subsequent column. If an older template without these columns reaches InputFieldRowProcessor.processRow(), the old preset value (index 6) becomes topComment, the old validation message (index 7) becomes bottomComment, and all validation parameters shift right.

The init() method uses only static column indices with no dynamic mapping. processHeaderRow() is not overridden, and XlsImporterBase.readRows() performs no version or column-count validation before row processing. getColumnValue() silently returns null for out-of-bounds indices, masking the mismatch.

Verify that either:

  1. The XLS import template version is validated before processRow() executes, or
  2. Legacy column layouts are explicitly detected and remapped
    Otherwise older templates will import with corrupted field metadata.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/src/exec/java/org/phoenixctms/ctsms/executable/xls/InputFieldRowProcessor.java`
around lines 31 - 46, The code currently uses fixed static indices (e.g.,
TOP_COMMENT_COLUMN_INDEX, BOTTOM_COMMENT_COLUMN_INDEX, PRESET_COLUMN_INDEX)
which will corrupt legacy one-comment XLS templates when processed by
InputFieldRowProcessor.processRow(); update the importer so templates are
validated or remapped before row processing: override processHeaderRow() in
InputFieldRowProcessor (or modify init()) to inspect header column names/count
(using getColumnValue()) and either (a) validate the template version/expected
column count and throw a clear exception from XlsImporterBase.readRows() before
processRow() runs, or (b) detect the legacy layout (missing
TOP_COMMENT/BOTTOM_COMMENT headers or fewer columns) and populate a dynamic
column-mapping table used by processRow() instead of the static
TOP_COMMENT_COLUMN_INDEX/PRESET_COLUMN_INDEX constants; also ensure
out-of-bounds getColumnValue() results are treated as a validation error rather
than silently null so mismatches are not masked.

Comment on lines +112 to 123
private String getInputFieldTopComment() {
String comment;
if (inputField.getLocalized()) {
comment = L10nUtil.getInputFieldComment(getLabelLocale(), inputField.getCommentL10nKey());
comment = L10nUtil.getInputFieldComment(getLabelLocale(), inputField.getTopCommentL10nKey());
} else {
comment = inputField.getCommentL10nKey();
comment = inputField.getTopCommentL10nKey();
}
if (comment == null) {
comment = "";
}
return getInputFieldCommentLabel(comment);
return getInputFieldTopCommentLabel(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.

⚠️ Potential issue | 🟡 Minor

Avoid formatting empty comments into visible label text.

At Line 122 and Line 137, empty/null comments are still passed into label formatters. If those templates contain static text, top/bottom comment rows render even when no comment exists.

Suggested fix
 private String getInputFieldTopComment() {
 	String comment;
 	if (inputField.getLocalized()) {
 		comment = L10nUtil.getInputFieldComment(getLabelLocale(), inputField.getTopCommentL10nKey());
 	} else {
 		comment = inputField.getTopCommentL10nKey();
 	}
-	if (comment == null) {
-		comment = "";
-	}
+	if (CommonUtil.isEmptyString(comment)) {
+		return "";
+	}
 	return getInputFieldTopCommentLabel(comment);
 }
 ...
 private String getInputFieldBottomComment() {
 	String comment;
 	if (inputField.getLocalized()) {
 		comment = L10nUtil.getInputFieldComment(getLabelLocale(), inputField.getBottomCommentL10nKey());
 	} else {
 		comment = inputField.getBottomCommentL10nKey();
 	}
-	if (comment == null) {
-		comment = "";
-	}
+	if (CommonUtil.isEmptyString(comment)) {
+		return "";
+	}
 	return getInputFieldBottomCommentLabel(comment);
 }

Also applies to: 127-138

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/src/main/java/org/phoenixctms/ctsms/pdf/InputFieldPDFBlock.java` around
lines 112 - 123, The top/bottom comment getters are passing null/empty strings
into label formatter methods causing static template text to render; update
getInputFieldTopComment (and the corresponding bottom comment method) to trim
and check for blank (e.g., comment == null || comment.trim().isEmpty()) after
localization and return an empty string (or skip calling
getInputFieldTopCommentLabel/getInputFieldBottomCommentLabel) when blank,
otherwise call the formatter with the non-empty comment.

@rkrenn rkrenn merged commit 257ce5d into master Mar 17, 2026
1 of 2 checks passed
@sonarqubecloud
Copy link
Copy Markdown

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.

1 participant