diff options
| author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-08-28 08:36:29 +0200 |
|---|---|---|
| committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-08-28 08:36:29 +0200 |
| commit | d51e3dad33edb14c048372c035b635313d7a1dc9 (patch) | |
| tree | ed8cb2cf39e141f04ba05d99f5b913fa6ac93409 /src/test/java | |
| parent | 0be6e41ca5ae1c16aab308931616f1ec84ea3eba (diff) | |
Die Anlage gliedert sich nach eigener Wahl
Der Korpuslauf sollte klären, woran die Anlagen-Reste liegen, und hat die Frage
anders beantwortet als erwartet: Unter den 116 liegengebliebenen Befehlen des
Korpus ist kein einziger ein Tabellenproblem. Die Annahme, die vier
mecklenburgischen Reste scheiterten an fehlender Tabellenunterstützung, war
unrichtig. Beschafft man das Ursprungsheft (GVOBl. M-V 2016 Nr. 12, über das
Internet-Archiv, weil der Wirt einer Skriptabfrage nicht antwortet), so zeigt
sich: Der Ausbildungsrahmenplan ist keine Tabelle, sondern gegliederter
Fließtext — je Abschnitt eine Kopfzeile, die Ausbildungsstelle, die Dauer und
eine Spiegelstrichliste. Er fehlte in der Stammfassung, das war alles.
Eine Anlage gliedert sich nach eigener Wahl. Neben den Nummern eines
Zuständigkeitskatalogs kennt das Erzeugnis deshalb fortan die benannte Einheit
und führt sie wie jene als eigene Norm, deren Bezeichnung die Anlage voranstellt:
„Anlage 1 Ausbildungsabschnitt 1“. Erkannt wird sie an ihrem Bau und nicht an
einer Wortliste — verlangt sind Buchstaben vor dem Wortstamm —, denn jede Anlage
darf ihre Einheiten nennen, wie sie will, und eine Liste wäre am nächsten Land
wieder unvollständig. Leser und Ausgeber tragen sie (der Rundlauf geht auf), der
Stellenparser nimmt sie als Stellenangabe, der Auflöser setzt sie mit der Anlage
zur Normbezeichnung zusammen, und der Anwender benennt sie um.
Dabei ist ein stiller Fehler zutage getreten: Die Umnummerierung lief für alles,
was weder Paragraph noch Absatz noch Aufzählungsmarke noch Satz war, in den
Auffangzweig „keine Textänderung nötig“ und meldete Erfolg, ohne etwas zu tun.
Erst der Belegfall hat das gezeigt.
Von den vier mecklenburgischen Resten sind zwei erledigt (22 statt 20 von 24
Befehlen). Die beiden übrigen haben benannte Gründe: Der eine fügt einen ganzen
Ausbildungsabschnitt ein — eine neue Norm innerhalb einer Anlage setzt das
Erzeugnis nicht —, der andere verweist auf einen Anhang des ändernden Gesetzes,
der nicht vorliegt. Die Anlage 2 (Vordruck des Befähigungsberichts) bleibt aus
demselben Grund fort; sie ist der einzige echte Tabellensatz des ganzen Korpus.
Die Grundlinie hat sich sogleich bewährt: Die Erweiterung kostete einen Befehl,
der zuvor angewandt wurde — „Die Überschrift zu Unterabschnitt 4 wird
gestrichen“ des GEG-Entwurfs fiel aus dem Gliederungszweig, weil auch
„Unterabschnitt“ auf den Wortstamm endet. Der Korpuslauf rügte das im selben
Durchgang („angewandte Befehle 86 statt 87“), und zwar in einem anderen Land und
einem anderen Dokument, wo keine Einzelprüfung es bemerkt hätte. Die Grenze ist
gezogen und durch zwei Prüffälle gepinnt.
Geprüft: mvnw verify (445 Testfälle) und reuse lint (214/214) gehen durch. Der
Akzeptanzfall pinnt 35 statt 29 Normen und 22 statt 20 angewandte Befehle; die
Grundlinie des Korpuslaufs ist auf 1289 statt 1287 angewandter Befehle
fortgeschrieben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I3e6046c3a91ecc45406058b367ec5a9a19c84967
Diffstat (limited to 'src/test/java')
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/EndToEndTest.java | 34 | ||||
| -rw-r--r-- | src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java | 20 |
2 files changed, 47 insertions, 7 deletions
diff --git a/src/test/java/eu/mulk/aendggner/EndToEndTest.java b/src/test/java/eu/mulk/aendggner/EndToEndTest.java index 34bc8e6..ea014b0 100644 --- a/src/test/java/eu/mulk/aendggner/EndToEndTest.java +++ b/src/test/java/eu/mulk/aendggner/EndToEndTest.java @@ -1931,8 +1931,12 @@ class EndToEndTest { var gesetz = new eu.mulk.aendggner.gesetz.land.LandesRechtLoader().load(alt); assertThat(gesetz.jurabk()).isEqualTo("APOAmtsTA M-V"); - // Die Inhaltsübersicht ist eine Norm gleichen Namens; dazu die 28 Paragraphen. - assertThat(gesetz.normen()).hasSize(29); + // Die Inhaltsübersicht ist eine Norm gleichen Namens; dazu die 28 Paragraphen, die Anlage 1 + // (Ausbildungsrahmenplan) und deren fünf Ausbildungsabschnitte, die das Portal wie die Nummern + // eines Zuständigkeitskatalogs als eigene Einheiten führt. + assertThat(gesetz.normen()).hasSize(35); + assertThat(gesetz.norm("Anlage 1 Ausbildungsabschnitt 1")).isPresent(); + assertThat(gesetz.norm("Anlage 1 Ausbildungsabschnitt 5")).isPresent(); var text = TextBereiniger.bereinige(new PatchTextExtraktor().extrahiere(pdf)); // Kolumnentitel und Seitenfuß stehen im Inhaltsstrom, und zwar mitten im Befehlstext. @@ -1945,7 +1949,7 @@ class EndToEndTest { assertThat(parseErgebnis.befehle()).hasSize(24); var anwendung = BefehlAnwender.anwenden(gesetz, parseErgebnis.befehle()); - assertThat(anwendung.anzahlAngewandt()).isEqualTo(20); + assertThat(anwendung.anzahlAngewandt()).isEqualTo(22); // Die Nummern 2 und 3 entfallen, die Nummern 4 bis 6 rücken auf 2 bis 4 — ohne Platzhalter, // denn sie stehen am Ende ihres Blockes nicht. @@ -1965,15 +1969,31 @@ class EndToEndTest { assertThat(anwendung.neu().norm("Inhaltsübersicht").orElseThrow().absaetze().get(0).text()) .contains("§ 10 | Ausbildungsnachweise"); - // Übrig bleiben allein die vier Befehle, die die Anlagen betreffen: Die Stammfassung führt sie - // nicht mit (Tabellen und Vordrucke), und der elfte Befehl verweist auf einen Anhang des - // Änderungsgesetzes. + // Die benannte Einheit der Anlage trägt die Wortersetzung … + assertThat( + anwendung + .neu() + .norm("Anlage 1 Ausbildungsabschnitt 1") + .orElseThrow() + .absaetze() + .get(0) + .text()) + .startsWith("Das für das Veterinärwesen zuständige Ministerium") + .doesNotContain("Ministerium für Landwirtschaft, Umwelt und Verbraucherschutz"); + // … und die Umnummerierung trifft ihre Bezeichnung, nicht ihren Wortlaut. + assertThat(anwendung.neu().norm("Anlage 1 Ausbildungsabschnitt 6")).isPresent(); + assertThat(anwendung.neu().norm("Anlage 1 Ausbildungsabschnitt 5")).isEmpty(); + + // Übrig bleiben zwei Befehle, beide mit benanntem Grund: Nummer 10 Buchstabe b fügt einen + // ganzen Ausbildungsabschnitt ein — eine neue Norm innerhalb einer Anlage, die das Erzeugnis + // nicht setzt —, und Nummer 11 verweist auf einen Anhang des ändernden Gesetzes, der nicht + // vorliegt. Was nicht vorliegt, lässt sich nicht anwenden. var offen = anwendung.protokoll().stream() .filter(a -> a.status() == BefehlAnwender.Status.MANUELL_PRUEFEN) .map(a -> a.befehl().provenienz().gliederungsPfad()) .toList(); - assertThat(offen).containsExactly("10. a)", "10. b)", "10. c)", "11."); + assertThat(offen).containsExactly("10. b)", "11."); } private static Aenderungsbefehl befehlZu( 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 13e4442..6c34b8c 100644 --- a/src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java +++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/StellenParserTest.java @@ -152,4 +152,24 @@ class StellenParserTest { // Ein Wort, das bloß so anfängt, ist keiner. assertThat(StellenParser.istNurChapeau("In der Einleitungsformel")).isFalse(); } + + @Test + void benannteEinheitEinerAnlage() { + // „Im Ausbildungsabschnitt 1 …“ — der Ausbildungsrahmenplan gliedert sich in benannte + // Einheiten, die das Portal wie eigene Normen führt. + var stelle = StellenParser.parse("Ausbildungsabschnitt 1").orElseThrow(); + assertThat(stelle.anzeigeText()).isEqualTo("Ausbildungsabschnitt 1"); + assertThat(stelle.anlagenEinheit()).isPresent(); + assertThat(stelle.betrifftEchteGliederung()).isFalse(); + } + + @Test + void unterabschnittBleibtGliederungDesGesetzes() { + // Er endet auf denselben Wortstamm, gliedert aber das Gesetz und ist keine Einheit einer + // Anlage. Ohne diese Grenze fiele „Die Überschrift zu Unterabschnitt 4 wird gestrichen“ aus + // dem Gliederungszweig heraus. + var stelle = StellenParser.parse("Unterabschnitt 4").orElseThrow(); + assertThat(stelle.anlagenEinheit()).isEmpty(); + assertThat(stelle.betrifftEchteGliederung()).isTrue(); + } } |
