aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2026-08-24 21:12:44 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2026-08-24 21:12:44 +0200
commite8213085ebb446081cfe6ce45f047d6862e1a755 (patch)
treec311888baa3c23cfc678d763470a8b459aa5def6 /src/main
parenta88d5707a4a58b1d37db97b211770d3509e95ee5 (diff)
Nicht jedes Landesportal versteckt seinen Text
Brandenburg ist das erste Land, dessen Portal keine juris-Einseitenanwendung ist: BRAVORS gibt seine Vorschriften als gewöhnliches HTML aus und führt unter „Änderungshistorie“ jede Fassung einzeln. Vor- und Nachfassung entstammen damit derselben Quelle — kein Wayback, keine Browsersteuerung, nur zwei Adressen. Die Hefte lassen sich am Dokumententitel des PDF einordnen; „FraktG-1AendG“ verrät mehr als jede Volltextsuche. Der Belegfall ist das Erste Gesetz zur Änderung des Fraktionsgesetzes (GVBl. I 2026 Nr. 12): vier Befehle, vier angewandt, alle 24 Normen gleich der amtlichen Nachfassung — auf Anhieb, ohne einen einzigen Eingriff am Parser. Zugleich ist er die Gegenprobe zum Inkrafttreten: Artikel 2 ordnet es schlicht an („am Tag nach der Verkündung“), also darf keine Staffelung gerügt und kein Datum erfunden werden. Drei Eigenheiten fürs Aufbereiten stehen in Brandenburg/SOURCES: Die Abschnittsbezeichnung steht im Kopfelement vor der Überschrift; die Aufzählungen sind echte Listen, deren Marken erst das Stilblatt erzeugt; und an ehemaligen Trennstellen führt das Portal vereinzelt Steuerzeichen mit (U+0002 in „Mitglie<STX>der“), die kein Textbestand sind. Ein allgemeiner Fund kam doch dazu: Die Überschrift des Schlussartikels geriet in den Wortlaut der Inkrafttretens-Anordnung, weil ein Artikel ohne Absatz- bezeichnungen im ganzen ein Absatz ist. Auf das bloße Vorkommen von „tritt“ ist dabei kein Verlass — das Wort „Inkrafttreten“ trägt es selbst. Geprüft: 349 Tests, REUSE 185/185. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Change-Id: I17660864fdf589d280024c9ba310e23902781515
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/eu/mulk/aendggner/aenderung/parse/InkrafttretensLeser.java29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/main/java/eu/mulk/aendggner/aenderung/parse/InkrafttretensLeser.java b/src/main/java/eu/mulk/aendggner/aenderung/parse/InkrafttretensLeser.java
index 2892466..fccad16 100644
--- a/src/main/java/eu/mulk/aendggner/aenderung/parse/InkrafttretensLeser.java
+++ b/src/main/java/eu/mulk/aendggner/aenderung/parse/InkrafttretensLeser.java
@@ -45,6 +45,8 @@ public final class InkrafttretensLeser {
+ "(?:\\s+Buchstabe\\s+(\\p{Ll})\\b)?"
+ "(?:\\s+Doppelbuchstabe\\s+(\\p{Ll}{2})\\b)?");
+ private static final Pattern VERB = Pattern.compile("\\b(?:tritt|treten)\\b");
+
private static final Pattern AENDERUNGSFORMEL = Pattern.compile("wird wie folgt geändert");
private InkrafttretensLeser() {}
@@ -75,7 +77,7 @@ public final class InkrafttretensLeser {
/** Liest die Anordnungen eines einzelnen Blocks; {@code null}, wenn er keine trägt. */
public static @Nullable Inkrafttreten lies(String blockText) {
- var text = blockText.replaceAll("\\s+", " ").strip();
+ var text = ohneUeberschrift(blockText).replaceAll("\\s+", " ").strip();
var regeln = new ArrayList<Regel>();
for (var absatz : teileInAbsaetze(text)) {
var regel = liesAbsatz(absatz);
@@ -87,6 +89,31 @@ public final class InkrafttretensLeser {
}
/**
+ * Streicht die Überschrift des Artikels („Inkrafttreten“), die als eigene Zeile vor der Anordnung
+ * steht. Ohne das begänne der Wortlaut der Regel mit ihr, denn ein Artikel ohne Absatzmarken ist
+ * im ganzen ein Absatz.
+ */
+ private static String ohneUeberschrift(String blockText) {
+ var zeilen = blockText.lines().toList();
+ for (int i = 0; i < zeilen.size(); i++) {
+ var zeile = zeilen.get(i).strip();
+ if (zeile.isEmpty()) {
+ continue;
+ }
+ // Auf das bloße Vorkommen von „tritt“ ist kein Verlass: Die Überschrift „Inkrafttreten“
+ // trägt es selbst. Maßgeblich ist das Wort.
+ if (ABSATZ.matcher(zeile).lookingAt() || VERB.matcher(zeile).find()) {
+ return String.join("\n", zeilen.subList(i, zeilen.size()));
+ }
+ // Eine Überschrift steht für sich und endet nicht wie ein Satz.
+ if (zeile.endsWith(".") || zeile.length() > 60) {
+ return String.join("\n", zeilen.subList(i, zeilen.size()));
+ }
+ }
+ return blockText;
+ }
+
+ /**
* Zerlegt den Schlussartikel an seinen Absatzmarken. Ohne Marken ist der ganze Text ein Absatz
* („Dieses Gesetz tritt am Tage nach seiner Verkündung in Kraft.“).
*/