feat(massimport): support // as multi-person separator in PersonNameParser #182
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The mass import spreadsheet uses
//to separate independent full names in a single cell, butPersonNameParser.parseReceivers()only splits onund/u. This causes both names to be imported as a single garbage person record.Examples currently broken:
Charl.Blomquist//Tante Lolly→ one person instead of twoWalter de Gruyter//Eugenie de Gruyter→ one person instead of twoSolution
Pre-split the raw input on
//before any existing logic. Each//-segment is then piped through the current pipeline independently, and results are flattened.Unlike
und/u,//always separates fully independent, complete names — no shared last-name distribution is needed. The recursive approach handles mixed cases likeHerbert und Clara Cram//Eugenie de Gruyternaturally.Changes
PersonNameParser.javaAdd a
SLASH_SEPARATORpattern and a pre-split step at the top ofparseReceivers():PersonNameParserTest.java4 new tests (TDD — red first):
slashSeparator_twoIndependentFullNamesslashSeparator_abbreviatedFirstNameslashSeparator_withSpacesAroundSlashesslashSeparator_segmentContainsUndFiles
backend/src/main/java/.../service/PersonNameParser.javabackend/src/test/java/.../service/PersonNameParserTest.javaNo schema, API, or i18n changes needed.
Verification
👨💻 Felix Brandt — Senior Fullstack Developer
Questions & Observations
flatMap(segment -> parseReceivers(segment).stream())) is elegant and handles theHerbert und Clara Cram//Eugenie de Gruytermixed case naturally. Good design — the recursion lets each segment reuse all existing logic without duplication.[feature]_[scenario]naming convention. Each covers a distinct dimension of the feature.//? E.g.,//Herbert CramorHerbert Cram//. The.filter(s -> !s.isBlank())handles this, but an explicit test confirming the behavior would make the contract clear.//with no names around it (i.e.,//)? Again, the blank filter should handle it, but a test documents intent.Suggestions
slashSeparator_trailingOrLeadingSlash_ignored— to document that//Herbert Cramproduces one person, not two. This makes the guard clause's behavior explicit and regression-proof.SLASH_SEPARATORconstant name is good — it reveals intent. SincePattern.compileis used, confirm it'sstatic finalso the regex is compiled once (as shown in the issue — just calling it out for the implementer).//splitting happens on raw input, not on input that's already been partially normalized.🏗️ Markus Keller — Application Architect
Questions & Observations
//-segment re-entersparseReceivers(), so all existing logic (und/u splitting, last-name distribution) is reused without duplication. No new code paths to maintain.PersonNameParseris a pure utility within the service layer, no repository or controller changes needed.Suggestions
/as a separator (as opposed to//)? If so, the//pattern won't match, and those cases will silently pass through as single names. Worth checking the actual import data to be sure//is the only slash-based separator in use.Pattern.compile("//")is straightforward, but since//has no special regex meaning,String.split("//")would also work and avoids the compiled pattern overhead. That said, for a utility called at import time (not hot path), the difference is negligible — either approach is fine. The compiled pattern is arguably more readable since it sits as a named constant.🧪 Sara Holt — QA Engineer
Questions & Observations
//+und. Good coverage of the feature's interaction with existing logic.Herbert Cram//or//Herbert Cram— does the blank filter correctly discard the empty segment?Herbert Cram////Eugenie de Gruyter— does this produce empty segments that get filtered, or does it break?//still pass through unchanged.Suggestions
slashSeparator_segmentContainsUndis the most valuable of the four — it tests the interaction between the new//split and the existingundsplit. I'd make this the first test written (red phase) since it exercises the full recursive pipeline.parseReceiverstests after the change to confirm no behavior change for inputs without//. This is probably already covered by running the full test class, but worth explicitly noting in the PR../mvnw test -Dtest=PersonNameParserTestis correct. I'd also recommend running the fullMassImportServicetest suite (if it exists) to catch any integration-level regressions.🔒 Nora "NullX" Steiner — Security Engineer
Questions & Observations
parseReceivers(segment)is bounded by the number of//-segments in a single spreadsheet cell, which is naturally small. No risk of stack overflow from malicious input at realistic cell sizes.Suggestions
🎨 Leonie Voss — UI/UX Design Lead
Questions & Observations
//separator is a convention within the import spreadsheet, not something end users interact with through the web UI.Suggestions
PersonNameParser.javaand its test file. No UI, accessibility, or design implications.🛠️ Tobias Wendt — DevOps Engineer
Questions & Observations
./mvnw test -Dtest=PersonNameParserTest) is a fast unit test — no Testcontainers or external services required. CI time impact is negligible.Suggestions