diff options
| author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-07-19 10:15:00 +0200 |
|---|---|---|
| committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-07-19 10:15:00 +0200 |
| commit | c2b57decf3d57d4808dd37723c562b8e001cc342 (patch) | |
| tree | 0473edd67bcf8924d9d8fd3baa13dbd0e5086a00 /src/test/java | |
| parent | ab7ac577eedaffabf087a84786bebe9a8904c365 (diff) | |
Generalize Bavarian loader to a shared Landesrecht loader
Prepare wave six (Landesrecht of the remaining Länder) by lifting the
Bavaria-specific stem-law loader to a shared one. Unlike Bavaria (Art./§
inversion), the other Länder structure their stem laws in §, so the loader must
handle both sigils.
- Move gesetz/bayern/{BayRechtLoader,BayRechtTextParser} to
gesetz/land/{LandesRechtLoader,LandesRechtTextParser}; the norm head now
matches "§ N" as well as "Art. N" and derives the sigil per norm from the
match. Cross-reference keywords in the norm head are excluded only as whole
words (so a title "Satzungen" no longer trips on "Satz"), and the juris
abbreviation may be multi-token ("(GO NRW)").
- Derive the superscript mode data-drivenly from the loaded stem law
(Superskript.traegtSatznummern) instead of from "is it gii-XML": Bavaria and
Lower Saxony keep their amtliche Satznummern, the Bund and Länder without
official sentence numbering drop them.
- Recognize the neufassung idiom "erhält/erhalten folgende Fassung" (Schleswig-
Holstein, Niedersachsen) via a NEUFASSUNG_VERB building block, additive to
"wird/werden wie folgt gefasst".
Federal and Bavarian behaviour is unchanged (219 tests green, pinned acceptance
numbers UWG 19/0, GEG 66/53, GEG-GModG 90/9, IfSG 42/24, BayJG 149/154 hold).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Change-Id: I55a70a7932bf657a2346ca70f3fa05e173bf80ad
Diffstat (limited to 'src/test/java')
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/EndToEndTest.java | 4 | ||||
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java | 15 | ||||
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParserTest.java (renamed from src/test/java/eu/mulk/aendggner/gesetz/bayern/BayRechtTextParserTest.java) | 64 |
3 files changed, 71 insertions, 12 deletions
diff --git a/src/test/java/eu/mulk/aendggner/EndToEndTest.java b/src/test/java/eu/mulk/aendggner/EndToEndTest.java index 2e19090..0e90584 100644 --- a/src/test/java/eu/mulk/aendggner/EndToEndTest.java +++ b/src/test/java/eu/mulk/aendggner/EndToEndTest.java @@ -230,7 +230,7 @@ class EndToEndTest { assumeTrue(Files.exists(alt) && Files.exists(pdf), "BayJG-Beispieldaten fehlen"); // 1. Stammgesetz laden (Art.-gegliedert, amtliche Satznummern als Superskripte). - var gesetz = new eu.mulk.aendggner.gesetz.bayern.BayRechtLoader().load(alt); + var gesetz = new eu.mulk.aendggner.gesetz.land.LandesRechtLoader().load(alt); assertThat(gesetz.jurabk()).isEqualTo("BayJG"); assertThat(gesetz.langue()).isEqualTo("Bayerisches Jagdgesetz"); assertThat(gesetz.norm("Art. 1").orElseThrow().absaetze().get(0).text()) @@ -295,7 +295,7 @@ class EndToEndTest { var pdf = SAMPLEDATA.resolve("BayJG/Ltg-Drs-19-9707_Gesetzentwurf.pdf"); assumeTrue(Files.exists(alt) && Files.exists(pdf), "BayJG-Beispieldaten fehlen"); - var gesetz = new eu.mulk.aendggner.gesetz.bayern.BayRechtLoader().load(alt); + var gesetz = new eu.mulk.aendggner.gesetz.land.LandesRechtLoader().load(alt); var text = TextBereiniger.bereinige( new PatchTextExtraktor(eu.mulk.aendggner.aenderung.parse.SuperskriptModus.BEHALTEN) 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 8cf9eea..d89c898 100644 --- a/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java +++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java @@ -91,6 +91,21 @@ class BefehlErkennerTest { } @Test + void erkenntNeufassungMitErhaeltFolgendeFassung() { + // „… erhält folgende Fassung:“ ist die Neufassungsform in Schleswig-Holstein und Niedersachsen. + var befehl = + erkenne( + "§ 34a Absatz 1 erhält folgende Fassung: „(1) Durch Hauptsatzung kann bestimmt" + + " werden, dass Gemeindevertreterinnen und Gemeindevertreter teilnehmen.“", + Stelle.LEER); + + assertThat(befehl).containsInstanceOf(Neufassung.class); + var neufassung = (Neufassung) befehl.orElseThrow(); + assertThat(neufassung.stelle().anzeigeText()).isEqualTo("§ 34a Absatz 1"); + assertThat(neufassung.neuerText()).startsWith("(1) Durch Hauptsatzung"); + } + + @Test void erkenntParagraphEinfuegung() { // Echter Befehl aus Art. 1 Nr. 17 des Dritten Bevölkerungsschutzgesetzes. var befehl = diff --git a/src/test/java/eu/mulk/aendggner/gesetz/bayern/BayRechtTextParserTest.java b/src/test/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParserTest.java index a5fc67a..3354255 100644 --- a/src/test/java/eu/mulk/aendggner/gesetz/bayern/BayRechtTextParserTest.java +++ b/src/test/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParserTest.java @@ -1,13 +1,14 @@ -package eu.mulk.aendggner.gesetz.bayern; +package eu.mulk.aendggner.gesetz.land; import static org.assertj.core.api.Assertions.assertThat; import eu.mulk.aendggner.gesetz.Gliederung; import org.junit.jupiter.api.Test; -class BayRechtTextParserTest { +class LandesRechtTextParserTest { - private static final String BEISPIEL = + // Bayern: Gliederung in „Art.“, amtliche Satznummern als Superskript. + private static final String BAYERN = """ BayJG: Bayerisches Jagdgesetz (BayJG) Vom 13. Oktober 1978 (BayRS V S. 595) BayRS 792-1-W (Art. 1–64) @@ -51,17 +52,38 @@ class BayRechtTextParserTest { (1) Dieses Gesetz tritt am 1. Januar 1979 in Kraft. """; + // Übriges Landesrecht: Gliederung in „§“ (wie der Bund), hier mit amtlichen Satznummern. + private static final String PARAGRAPHEN = + """ + Gemeindeordnung für das Land Nordrhein-Westfalen + (GO NRW) + Vom 14. Juli 1994 + I. Teil Grundlagen der Gemeindeverfassung + § 1 Wesen der Gemeinde + + (1) ¹Die Gemeinden sind die Grundlage des demokratischen Staatsaufbaus. ²Sie fördern das Wohl der Einwohner. + (2) Die Gemeinden verwalten ihre Angelegenheiten selbst. + § 2 Aufgaben + + Die Gemeinden erfüllen die Aufgaben der örtlichen Gemeinschaft. + § 3 (weggefallen) + + § 4 Satzungen + + (1) Die Gemeinden können ihre Angelegenheiten durch Satzung regeln. + """; + @Test - void parstTitelblock() { - var gesetz = BayRechtTextParser.parse(BEISPIEL); + void parstBayerischenTitelblock() { + var gesetz = LandesRechtTextParser.parse(BAYERN); assertThat(gesetz.jurabk()).isEqualTo("BayJG"); assertThat(gesetz.langue()).isEqualTo("Bayerisches Jagdgesetz"); assertThat(gesetz.kurzue()).isNull(); } @Test - void parstNormenMitTitelnUndAbsaetzen() { - var gesetz = BayRechtTextParser.parse(BEISPIEL); + void parstBayerischeNormenMitTitelnUndAbsaetzen() { + var gesetz = LandesRechtTextParser.parse(BAYERN); assertThat(gesetz.normen()) .extracting(n -> n.enbez()) .containsExactly("Art. 1", "Art. 3", "Art. 8", "Art. 59", "Art. 60", "Art. 63", "Art. 64"); @@ -82,7 +104,7 @@ class BayRechtTextParserTest { @Test void querverweiseAmZeilenanfangEroeffnenKeineNorm() { // „Art. 11 Abs. 6 …“ am Zeilenanfang in Art. 8 ist ein Querverweis, kein Normkopf. - var gesetz = BayRechtTextParser.parse(BEISPIEL); + var gesetz = LandesRechtTextParser.parse(BAYERN); var art8 = gesetz.norm("Art. 8").orElseThrow(); assertThat(art8.absaetze().get(0).text()).contains("Art. 11 Abs. 6 sind entsprechend"); assertThat(gesetz.norm("Art. 11")).isEmpty(); @@ -90,7 +112,7 @@ class BayRechtTextParserTest { @Test void parstGliederungenMitUnterUeberschriften() { - var gesetz = BayRechtTextParser.parse(BEISPIEL); + var gesetz = LandesRechtTextParser.parse(BAYERN); assertThat(gesetz.gliederungen()) .extracting(Gliederung::anzeigeText) .containsExactly( @@ -107,7 +129,7 @@ class BayRechtTextParserTest { @Test void erkenntWeggefalleneNormenUndFussnoten() { - var gesetz = BayRechtTextParser.parse(BEISPIEL); + var gesetz = LandesRechtTextParser.parse(BAYERN); assertThat(gesetz.norm("Art. 60").orElseThrow().weggefallen()).isTrue(); assertThat(gesetz.norm("Art. 63").orElseThrow().weggefallen()).isFalse(); @@ -117,4 +139,26 @@ class BayRechtTextParserTest { .contains("Enteignung⁶)") .contains("⁶) [Amtl. Anm.:] BayRS 2141-1-I"); } + + @Test + void parstParagraphengegliedertesLandesrecht() { + // Die übrigen Länder zitieren in „§“; das Sigel folgt aus dem Normkopf, ein Land-Merkmal ist + // nicht nötig. Amtliche Satznummern werden ebenso wie bei Bayern erhalten. + var gesetz = LandesRechtTextParser.parse(PARAGRAPHEN); + assertThat(gesetz.jurabk()).isEqualTo("GO NRW"); + assertThat(gesetz.langue()).isEqualTo("Gemeindeordnung für das Land Nordrhein-Westfalen"); + assertThat(gesetz.normen()) + .extracting(n -> n.enbez()) + .containsExactly("§ 1", "§ 2", "§ 3", "§ 4"); + + var p1 = gesetz.norm("§ 1").orElseThrow(); + assertThat(p1.titel()).isEqualTo("Wesen der Gemeinde"); + assertThat(p1.absaetze()).hasSize(2); + assertThat(p1.absaetze().get(0).text()).startsWith("¹Die Gemeinden sind die Grundlage"); + + // Unnummerierter Einzelabsatz und weggefallene Norm wie im bayerischen Fall. + assertThat(gesetz.norm("§ 2").orElseThrow().absaetze().get(0).nummer()).isNull(); + assertThat(gesetz.norm("§ 3").orElseThrow().weggefallen()).isTrue(); + assertThat(gesetz.gliederungen()).extracting(Gliederung::anzeigeText).containsExactly("I. Teil — Grundlagen der Gemeindeverfassung"); + } } |
