diff --git a/backend/src/main/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListener.java b/backend/src/main/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListener.java index a9749fcd..a3c03206 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListener.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListener.java @@ -45,19 +45,12 @@ public class PersonMentionPropagationListener { String oldNeedle = "@" + event.oldDisplayName(); String newNeedle = "@" + event.newDisplayName(); - // Match @OldName only at a token boundary: not followed by a letter/digit/hyphen - // (catches @Hans-Peter when renaming Hans) AND not followed by " " - // (catches @Hans Müller when renaming the single-name @Hans). False negatives — - // e.g. "@Hans Bekam" where Bekam is sentence-initial — are accepted as the - // conservative trade-off; the alternative (corruption) is irrecoverable. Pattern boundary = Pattern.compile( Pattern.quote(oldNeedle) + "(?![\\p{L}0-9\\-]| (?=\\p{Lu}))"); String replacement = Matcher.quoteReplacement(newNeedle); for (TranscriptionBlock block : blocks) { - if (block.getText() != null) { - block.setText(boundary.matcher(block.getText()).replaceAll(replacement)); - } + rewriteBlockText(block, boundary, replacement); for (PersonMention mention : block.getMentionedPersons()) { if (mention.getPersonId().equals(event.personId())) { mention.setDisplayName(event.newDisplayName()); @@ -70,4 +63,15 @@ public class PersonMentionPropagationListener { log.info("Propagated rename {} → {} across {} block(s) for person {}", event.oldDisplayName(), event.newDisplayName(), blocks.size(), event.personId()); } + + // Match @OldName only at a token boundary: not followed by a letter/digit/hyphen + // (catches @Hans-Peter when renaming Hans) AND not followed by " " + // (catches @Hans Müller when renaming the single-name @Hans). False negatives — + // e.g. "@Hans Bekam" where Bekam is sentence-initial — are accepted as the + // conservative trade-off; the alternative (corruption) is irrecoverable. + private void rewriteBlockText(TranscriptionBlock block, Pattern boundary, String replacement) { + if (block.getText() != null) { + block.setText(boundary.matcher(block.getText()).replaceAll(replacement)); + } + } }