aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2026-07-13 21:33:25 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2026-07-13 21:33:25 +0200
commit51712fc87ec0487bd471f24b2986a367847d24e9 (patch)
tree131061eaf3664bfbb2a49abf9a43628e31a33867 /src/test
parentb05e44a627b3bbdf6f8b2e920b963709fd348f5a (diff)
Recognize compound and multi-pair amendment commands
Split BefehlErkenner into a single-command pass and a fallback that composes Sammelbefehle from commands chained with "und"/", wird": - Multi-pair replacement ("… A durch B und C durch D ersetzt") emits one Ersetzung per pair, crossed with the (possibly coordinated) Stelle. - Verbund splitter probes each "und"/", wird" boundary; when both halves parse — trying the right clause as-is, capitalized, or with the left clause's locative prefix — it folds them into one Sammelbefehl. The single pass no longer short-circuits when a pattern matches but its Stelle is unparseable, so the fallback still gets a chance. Add "ein Komma eingefügt" and anchor-first insertion patterns the splitter needs, and let StellenParser.parseMehrfach inherit the component type for bare-number continuations ("Absatz 1 und 5"). Cuts UnbekannterBefehl counts: GEG 50->36, IfSG 11->7, AGG/UWG 2->1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Change-Id: I8f76edd0c9ed6cf68c10c50f535a8182e13e378e
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java57
-rw-r--r--src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java15
2 files changed, 55 insertions, 17 deletions
diff --git a/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java b/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java
index 05055e0..ba0dd05 100644
--- a/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java
+++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java
@@ -412,32 +412,55 @@ class BefehlErkennerTest {
}
@Test
- void verbundZweierBefehleBleibtUnbekannt() {
+ void verbundZweierBefehleWirdSammelbefehl() {
// „… wird zu Absatz 2 und nach Satz 2 werden … eingefügt“ verbindet zwei verschiedene
- // Befehle per „und“ — bewusst nicht unterstützt.
- assertThat(
- erkenne(
- "Der bisherige Absatz 1 wird zu Absatz 2 und nach Satz 2 werden die folgenden"
- + " Sätze eingefügt: „Ein Satz.“",
- Stelle.LEER))
- .isEmpty();
+ // Befehle per „und“ → Sammelbefehl aus Umnummerierung und Struktureinfügung.
+ var befehl =
+ erkenne(
+ "Der bisherige Absatz 1 wird zu Absatz 2 und nach Satz 2 werden die folgenden"
+ + " Sätze eingefügt: „Ein Satz.“",
+ Stelle.LEER);
+ var teile = ((Sammelbefehl) befehl.orElseThrow()).teilbefehle();
+ assertThat(teile).hasSize(2);
+ assertThat(teile.get(0)).isInstanceOf(Umnummerierung.class);
+ assertThat(teile.get(1)).isInstanceOf(StrukturEinfuegung.class);
}
@Test
- void faelltBeiBereichsbefehlenAufUnbekanntZurueck() {
- // Bereichs- und Mehrfachbefehle sind in v1 bewusst nicht unterstützt.
+ void koordinierteStelleErsetzungWirdSammelbefehl() {
+ // „In Absatz 1 Satz 1 und 2 …“ — koordinierte Stelle (das „2“ erbt „Satz“).
+ var befehl =
+ erkenne(
+ "In Absatz 1 Satz 1 und 2 werden die Wörter „alt“ durch die Wörter „neu“ ersetzt.",
+ Stelle.LEER);
+ var teile = ((Sammelbefehl) befehl.orElseThrow()).teilbefehle();
+ assertThat(teile).hasSize(2).allMatch(t -> t instanceof Ersetzung);
+ assertThat(teile).extracting(t -> t.stelle().anzeigeText())
+ .containsExactly("Absatz 1 Satz 1", "Absatz 1 Satz 2");
+ }
+
+ @Test
+ void faelltBeiBisBereichenAufUnbekanntZurueck() {
+ // „bis“-Bereiche über Struktureinheiten sind hier (Phase 1) noch nicht unterstützt.
assertThat(
erkenne(
"Die Absätze 2 bis 4 werden durch die folgenden Absätze 2 bis 6 ersetzt:"
+ " „(2) Text.“",
Stelle.LEER))
.isEmpty();
- assertThat(erkenne("Die Nummern 1 bis 3 werden aufgehoben.", Stelle.LEER)).isEmpty();
- assertThat(
- erkenne(
- "In Absatz 1 Satz 1 und 2 werden die Wörter „alt“ durch die Wörter „neu“"
- + " ersetzt.",
- Stelle.LEER))
- .isEmpty();
+ }
+
+ @Test
+ void mehrfachErsetzungWirdSammelbefehl() {
+ // Mehrere Ersetzungspaare unter einem gemeinsamen „ersetzt“.
+ var befehl =
+ erkenne(
+ "In Satz 1 werden die Wörter „a“ durch die Wörter „b“ und die Angabe „c“ durch die"
+ + " Wörter „d“ ersetzt.",
+ Stelle.LEER);
+ var teile = ((Sammelbefehl) befehl.orElseThrow()).teilbefehle();
+ assertThat(teile).hasSize(2).allMatch(t -> t instanceof Ersetzung);
+ assertThat(teile).extracting(t -> ((Ersetzung) t).alt()).containsExactly("a", "c");
+ assertThat(teile).extracting(t -> ((Ersetzung) t).neu()).containsExactly("b", "d");
}
}
diff --git a/src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java b/src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java
index 4c2c7ef..c0ea159 100644
--- a/src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java
+++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java
@@ -52,4 +52,19 @@ class StellenParserTest {
void unparsbaresSegmentLiefertLeereListe() {
assertThat(StellenParser.parseMehrfach("§ 5 Absatz 2 und Kauderwelsch")).isEmpty();
}
+
+ @Test
+ void bloßeNummerErbtKomponentenart() {
+ // „Absatz 1 und 5“: das „5“ erbt die Komponentenart „Absatz“ der letzten Komponente.
+ var stellen = StellenParser.parseMehrfach("§ 7 Absatz 1 und 5");
+ assertThat(stellen).extracting(Stelle::anzeigeText)
+ .containsExactly("§ 7 Absatz 1", "§ 7 Absatz 5");
+ }
+
+ @Test
+ void bloßeNummerNachSatz() {
+ var stellen = StellenParser.parseMehrfach("Absatz 1 Satz 1 und 2");
+ assertThat(stellen).extracting(Stelle::anzeigeText)
+ .containsExactly("Absatz 1 Satz 1", "Absatz 1 Satz 2");
+ }
}