aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/eu
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/eu')
-rw-r--r--src/main/java/eu/mulk/aendggner/aenderung/parse/TextBereiniger.java9
-rw-r--r--src/main/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParser.java20
2 files changed, 28 insertions, 1 deletions
diff --git a/src/main/java/eu/mulk/aendggner/aenderung/parse/TextBereiniger.java b/src/main/java/eu/mulk/aendggner/aenderung/parse/TextBereiniger.java
index 4016256..d79df60 100644
--- a/src/main/java/eu/mulk/aendggner/aenderung/parse/TextBereiniger.java
+++ b/src/main/java/eu/mulk/aendggner/aenderung/parse/TextBereiniger.java
@@ -117,6 +117,12 @@ public final class TextBereiniger {
"^\\s*\\d+\\. Wahlperiode\\s+(?:\\d{2}\\.\\d{2}\\.\\d{4}\\s+)?Drucksache \\d+/\\d+\\s*$");
private static final Pattern LANDTAG_MARKE = Pattern.compile("^\\s*Bayerischer Landtag\\s*$");
+ // Fußzeile der revosax-Volltextausgabe (Sachsen), z.B. „https://www.revosax.sachsen.de
+ // Fassung vom 13.04.2026 Seite 1 von 1“ — Herausgeber-URL, Fassungsdatum und Seitenangabe.
+ private static final Pattern REVOSAX_FUSS =
+ Pattern.compile(
+ "^\\s*https?://\\S+\\s+Fassung vom \\d{1,2}\\.\\d{1,2}\\.\\d{4}\\s+Seite \\d+ von \\d+\\s*$");
+
/** Konjunktionen, die typischerweise auf einen Suspensivstrich folgen („Wirk- und …“). */
private static final Pattern KONJUNKTION =
Pattern.compile("^(und|oder|sowie|bzw\\.|beziehungsweise)\\b.*");
@@ -285,7 +291,8 @@ public final class TextBereiniger {
|| GVBL_KOPF.matcher(zeile).matches()
|| LANDTAG_SEITENKOPF.matcher(zeile).matches()
|| LANDTAG_TITELKOPF.matcher(zeile).matches()
- || LANDTAG_MARKE.matcher(zeile).matches();
+ || LANDTAG_MARKE.matcher(zeile).matches()
+ || REVOSAX_FUSS.matcher(zeile).matches();
}
/**
diff --git a/src/main/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParser.java b/src/main/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParser.java
index b1da42d..23260de 100644
--- a/src/main/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParser.java
+++ b/src/main/java/eu/mulk/aendggner/gesetz/land/LandesRechtTextParser.java
@@ -49,6 +49,13 @@ final class LandesRechtTextParser {
private static final Pattern GLIEDERUNG =
Pattern.compile("^([IVXLCDM]+)\\.\\s+(Abschnitt|Teil|Kapitel)\\b\\s*(.*)$");
+ // Gliederungs-Überschrift in keyword-erster, arabischer Form („Abschnitt 1“, „Unterabschnitt 2“,
+ // „Teil 3“). Die meisten Länder (z.B. Sachsen) gliedern so; Bayern dagegen römisch mit
+ // nachgestelltem Schlüsselwort („I. Abschnitt“, Muster GLIEDERUNG). Der Titel steht — nach der
+ // kanonischen Aufbereitung — mit doppeltem Leerzeichen auf derselben Zeile.
+ private static final Pattern GLIEDERUNG_ARABISCH =
+ Pattern.compile("^(Buch|Teil|Kapitel|Abschnitt|Unterabschnitt|Titel) (\\d+[a-z]?)\\s+(\\S.*)$");
+
private static final Pattern UNTER_GLIEDERUNG = Pattern.compile("^(\\d+[a-z]?)\\.\\s+(\\S.*)$");
// Normkopf: „§ N“ bzw. „Art. N“ plus Titel auf derselben Zeile. Das Sigel steht in Gruppe 1, die
@@ -95,6 +102,7 @@ final class LandesRechtTextParser {
// Rest des Titelblocks (Datum, Fundstellen, Vollzitat) bis zur ersten Struktur überspringen.
while (i < zeilen.size()
&& !GLIEDERUNG.matcher(zeilen.get(i).strip()).matches()
+ && !GLIEDERUNG_ARABISCH.matcher(zeilen.get(i).strip()).matches()
&& !NORM_KOPF.matcher(zeilen.get(i).strip()).matches()) {
i++;
}
@@ -115,11 +123,13 @@ final class LandesRechtTextParser {
var zeile = i < zeilen.size() ? zeilen.get(i).strip() : null;
var gliederung = zeile != null ? GLIEDERUNG.matcher(zeile) : null;
+ var arabisch = zeile != null ? GLIEDERUNG_ARABISCH.matcher(zeile) : null;
var unterGliederung = zeile != null ? UNTER_GLIEDERUNG.matcher(zeile) : null;
var normKopf = zeile != null ? NORM_KOPF.matcher(zeile) : null;
if (zeile == null
|| gliederung.matches()
+ || arabisch.matches()
|| (normKopf.matches() && istNeuerNormKopf(normKopf.group(2), letzteNormNummer))
|| (unterGliederung.matches() && istUnterGliederung(unterGliederung, zeilen, i))) {
// Laufende Norm abschließen.
@@ -142,6 +152,16 @@ final class LandesRechtTextParser {
gliederung.group(1) + ". " + gliederung.group(2),
titel.isEmpty() ? null : titel);
gliederungen.add(aktuelleGliederung);
+ } else if (arabisch.matches()) {
+ gliederungsZaehler++;
+ elternKennzahl = String.format("%03d", gliederungsZaehler);
+ var titel = arabisch.group(3).strip();
+ aktuelleGliederung =
+ new Gliederung(
+ elternKennzahl,
+ arabisch.group(1) + " " + arabisch.group(2),
+ titel.isEmpty() ? null : titel);
+ gliederungen.add(aktuelleGliederung);
} else if (normKopf.matches() && istNeuerNormKopf(normKopf.group(2), letzteNormNummer)) {
normSigel = normKopf.group(1);
normNummer = normKopf.group(2);