diff options
| author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-07-13 21:33:43 +0200 |
|---|---|---|
| committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-07-13 21:33:43 +0200 |
| commit | 9a29b384b84fac20f3c417ff9dcf3d461627e185 (patch) | |
| tree | f872126e803a9b6452a18050cc4b701fd9b12da2 /src/test/java | |
| parent | 51712fc87ec0487bd471f24b2986a367847d24e9 (diff) | |
Support range, renumbering, and punctuation commands
Extend the parser and applier for several command families that were
falling back to UnbekannterBefehl:
- Range/coordinated Aufhebung ("Die Nummern 1 bis 3 werden aufgehoben.",
"Die Absätze 4 und 5 werden aufgehoben.") via bis-range expansion in
StellenParser.parseMehrfach and ausStellen.
- Range renumbering without "zu den" and for Nummern/Buchstaben ("Die
bisherigen Nummern 4 bis 6 werden die Nummern 8 bis 10."); single
renumbering now also covers Nummer/Buchstabe and "Die bisherige".
- §-range Neufassung ("Die §§ 52 bis 56 werden wie folgt gefasst: …"),
splitting the quoted block at "§ N" boundaries.
- "Der Wortlaut wird Absatz N." — a new WortlautZuAbsatz command that
numbers the previously unnumbered body.
- Word-to-punctuation replacement ("… das Wort „oder" am Ende durch ein
Komma ersetzt") and comma+words insert/replace variants.
StellenParser gains plural component words (Absätze/Sätze/Nummern/
Buchstaben) and bis-range expansion. Cuts UnbekannterBefehl further:
GEG 36->21, IfSG 7->3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Change-Id: I4972d4eb1d6062521a55710c1f23822e8e22b0c4
Diffstat (limited to 'src/test/java')
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java | 68 | ||||
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java | 38 |
2 files changed, 106 insertions, 0 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 ba0dd05..2d0db8a 100644 --- a/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java +++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java @@ -14,6 +14,7 @@ import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturEinfuegung; import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Umnummerierung; import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WoerterEinfuegung; import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortAnker; +import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortlautZuAbsatz; import eu.mulk.aendggner.aenderung.Provenienz; import eu.mulk.aendggner.aenderung.Stelle; import java.util.List; @@ -451,6 +452,73 @@ class BefehlErkennerTest { } @Test + void bereichsAufhebungWirdSammelbefehl() { + var teile = + ((Sammelbefehl) erkenne("Die Nummern 1 bis 3 werden aufgehoben.", Stelle.LEER).orElseThrow()) + .teilbefehle(); + assertThat(teile).hasSize(3).allMatch(t -> t instanceof Aufhebung); + assertThat(teile).extracting(t -> t.stelle().anzeigeText()) + .containsExactly("Nummer 1", "Nummer 2", "Nummer 3"); + } + + @Test + void koordinierteAufhebungWirdSammelbefehl() { + var teile = + ((Sammelbefehl) erkenne("Die Absätze 4 und 5 werden aufgehoben.", Stelle.LEER).orElseThrow()) + .teilbefehle(); + assertThat(teile).extracting(t -> t.stelle().anzeigeText()) + .containsExactly("Absatz 4", "Absatz 5"); + } + + @Test + void bereichsUmnummerierungNummernOhneZuDen() { + var teile = + ((Sammelbefehl) + erkenne("Die bisherigen Nummern 4 bis 6 werden die Nummern 8 bis 10.", Stelle.LEER) + .orElseThrow()) + .teilbefehle(); + assertThat(teile).hasSize(3).allMatch(t -> t instanceof Umnummerierung); + // Absteigend: 6→10, 5→9, 4→8. + assertThat(teile).extracting(t -> t.stelle().anzeigeText()) + .containsExactly("Nummer 6", "Nummer 5", "Nummer 4"); + assertThat(teile).extracting(t -> ((Umnummerierung) t).neu().anzeigeText()) + .containsExactly("Nummer 10", "Nummer 9", "Nummer 8"); + } + + @Test + void paragraphBereichNeufassungWirdSammelbefehl() { + var teile = + ((Sammelbefehl) + erkenne( + "Die §§ 52 bis 56 werden wie folgt gefasst: „§ 52 (weggefallen) § 53" + + " (weggefallen) § 54 (weggefallen)“.", + Stelle.LEER) + .orElseThrow()) + .teilbefehle(); + assertThat(teile).hasSize(3).allMatch(t -> t instanceof Neufassung); + assertThat(teile).extracting(t -> t.stelle().anzeigeText()) + .containsExactly("§ 52", "§ 53", "§ 54"); + } + + @Test + void wortlautWirdAbsatz() { + var befehl = + erkenne("Der Wortlaut wird Absatz 1.", new Stelle(List.of(new Stelle.Paragraph("5")))); + assertThat(befehl).get().isInstanceOf(WortlautZuAbsatz.class); + assertThat(((WortlautZuAbsatz) befehl.orElseThrow()).nummer()).isEqualTo("1"); + } + + @Test + void wortDurchSatzzeichen() { + var befehl = + erkenne("In Nummer 7 wird das Wort „oder“ am Ende durch ein Komma ersetzt.", Stelle.LEER); + var e = (Ersetzung) befehl.orElseThrow(); + assertThat(e.alt()).isEqualTo("oder"); + assertThat(e.neu()).isEqualTo(","); + assertThat(e.amEnde()).isTrue(); + } + + @Test void mehrfachErsetzungWirdSammelbefehl() { // Mehrere Ersetzungspaare unter einem gemeinsamen „ersetzt“. var befehl = diff --git a/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java b/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java index a854632..8a1b1e0 100644 --- a/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java +++ b/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java @@ -459,6 +459,44 @@ class BefehlAnwenderTest { false))); } + @Test + void wendetWortlautZuAbsatzAn() { + // § 2 hat einen unnummerierten Wortlaut, der zu Absatz 1 wird. + var befehl = + new eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortlautZuAbsatz( + stelle(new Stelle.Paragraph("2")), "1", PROV); + + var ergebnis = BefehlAnwender.anwenden(gesetz(), List.of(befehl)); + + assertThat(ergebnis.protokoll().get(0).status()).isEqualTo(Status.ANGEWANDT); + var norm = ergebnis.neu().norm("§ 2").orElseThrow(); + assertThat(norm.absaetze()).hasSize(1); + assertThat(norm.absaetze().get(0).nummer()).isEqualTo("1"); + assertThat(norm.absaetze().get(0).anzeigeText()).startsWith("(1) Erprobung ist"); + } + + @Test + void wendetBereichsAufhebungAn() { + // „Die Nummern 1 bis 3 werden aufgehoben.“ innerhalb von § 1 Absatz 2. + var teile = + List.<eu.mulk.aendggner.aenderung.Aenderungsbefehl>of( + new Aufhebung( + stelle(new Stelle.Paragraph("1"), new Stelle.AbsatzNr("2"), new Stelle.NummerNr("1")), + PROV), + new Aufhebung( + stelle(new Stelle.Paragraph("1"), new Stelle.AbsatzNr("2"), new Stelle.NummerNr("2")), + PROV), + new Aufhebung( + stelle(new Stelle.Paragraph("1"), new Stelle.AbsatzNr("2"), new Stelle.NummerNr("3")), + PROV)); + + var ergebnis = BefehlAnwender.anwenden(gesetz(), List.of(new Sammelbefehl(teile))); + + assertThat(ergebnis.protokoll().get(0).status()).isEqualTo(Status.ANGEWANDT); + var text = absatzText(ergebnis.neu(), "§ 1", 1); + assertThat(text).contains("1. (weggefallen)").contains("2. (weggefallen)").contains("3. (weggefallen)"); + } + private static String absatzText(Gesetz gesetz, String enbez, int index) { return gesetz.norm(enbez).orElseThrow().absaetze().get(index).text(); } |
