aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md17
-rw-r--r--src/main/java/eu/mulk/aendggner/aenderung/Aenderungsbefehl.java15
-rw-r--r--src/main/java/eu/mulk/aendggner/aenderung/parse/BefehlErkenner.java17
-rw-r--r--src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java18
-rw-r--r--src/test/java/eu/mulk/aendggner/EndToEndTest.java24
-rw-r--r--src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java30
6 files changed, 109 insertions, 12 deletions
diff --git a/README.md b/README.md
index 538f10a..c894884 100644
--- a/README.md
+++ b/README.md
@@ -339,7 +339,15 @@ Streichen und Umnummerierung.
15. Verb-Rahmen, deren Unterpunkte allein die Fundstelle tragen („Es werden
ersetzt: … in § 35 Absatz 3 die Angabe „X“ jeweils durch die Angabe „Y“,“),
sowie
-16. die Neufassung der Gesetzesüberschrift.
+16. die Neufassung der Gesetzesüberschrift sowie
+17. die Verweisung auf einen anderen Punkt desselben Artikels („Die
+ Inhaltsübersicht wird entsprechend der vorstehenden Nummer 8 Buchst. a
+ geändert“). Sie wird gelesen, aber nicht ausgeführt: Die sinngemäße
+ Übertragung setzte einen Rückgriff auf die Befehlsliste und eine Umdeutung
+ des Ziels voraus, die das Erzeugnis nicht leistet. Gelesen zu werden ist
+ gleichwohl mehr als gar nichts — die Rüge sagt alsdann, dass hier das
+ Erzeugnis die Grenze zieht, und nicht, dass die Vorlage unverständlich sei
+ (§ 1 Absatz 5).
(3) Landesrechtliche Befehlsformen bestimmt ergänzend § 13.
@@ -613,9 +621,10 @@ gleichwohl vier allgemeine Funde gebracht: die Nebenform „die Worte“ für â€
Wörter“, den Seitenfuß des dortigen Gesetzblattes, der im Inhaltsstrom das
Zitat einer Neufassung zerschneidet, den Strichpunkt samt Halbsatz-Anfügung
(§ 7 Absatz 2 Nummer 13) und den bezugspunktlosen Chapeau-Lokator (§ 7 Absatz 2
-Nummer 14). Offen bleibt allein die Verweisung auf einen anderen Punkt desselben
-Artikels („Die Inhaltsübersicht wird entsprechend der vorstehenden Nummer 8
-Buchst. a geändert“).
+Nummer 14). Auch die Verweisung auf einen anderen
+Punkt desselben Artikels (§ 7 Absatz 2 Nummer 17) stammt von dort; sie wird
+gelesen und ausdrücklich als Grenze gerügt. Sämtliche 23 Befehle des Heftes sind
+damit erschlossen.
(5) Welche Konvention welches Land beisteuert, welche Stammfassungen woher
stammen und was noch offen ist, verzeichnet
diff --git a/src/main/java/eu/mulk/aendggner/aenderung/Aenderungsbefehl.java b/src/main/java/eu/mulk/aendggner/aenderung/Aenderungsbefehl.java
index 47bca25..3138eeb 100644
--- a/src/main/java/eu/mulk/aendggner/aenderung/Aenderungsbefehl.java
+++ b/src/main/java/eu/mulk/aendggner/aenderung/Aenderungsbefehl.java
@@ -239,4 +239,19 @@ public sealed interface Aenderungsbefehl {
/** Fallback für alles, was der Parser nicht versteht — muss manuell geprüft werden. */
record UnbekannterBefehl(Stelle stelle, String originalText, Provenienz provenienz)
implements Aenderungsbefehl {}
+
+ /**
+ * „Die Inhaltsübersicht wird entsprechend der vorstehenden Nummer 8 Buchst. a geändert.“
+ *
+ * <p>Ein Befehl, der seinen Inhalt nicht selbst nennt, sondern auf einen anderen Punkt desselben
+ * Artikels verweist. Er wird erkannt, aber nicht angewandt: Die sinngemäße Übertragung setzte
+ * voraus, dass der Anwender die Befehlsliste zurückliest und das Ziel umdeutet („Überschrift des
+ * § 13“ → Titelspalte der Übersichtszeile). Erkannt zu werden ist gleichwohl mehr als gar nichts
+ * — die Rüge sagt dann, dass das Erzeugnis die Grenze zieht, und nicht, dass die Vorlage
+ * unverständlich sei.
+ *
+ * @param verweis der Wortlaut der Verweisung („Nummer 8 Buchst. a“).
+ */
+ record VerweisenderBefehl(Stelle stelle, String verweis, Provenienz provenienz)
+ implements Aenderungsbefehl {}
}
diff --git a/src/main/java/eu/mulk/aendggner/aenderung/parse/BefehlErkenner.java b/src/main/java/eu/mulk/aendggner/aenderung/parse/BefehlErkenner.java
index ef49b7b..f1cece5 100644
--- a/src/main/java/eu/mulk/aendggner/aenderung/parse/BefehlErkenner.java
+++ b/src/main/java/eu/mulk/aendggner/aenderung/parse/BefehlErkenner.java
@@ -17,6 +17,7 @@ import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Streichung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturEinfuegung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturErsetzung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Umnummerierung;
+import eu.mulk.aendggner.aenderung.Aenderungsbefehl.VerweisenderBefehl;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WoerterEinfuegung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortAnker;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortlautVoranstellung;
@@ -520,6 +521,15 @@ final class BefehlErkenner {
private static final Pattern HALBSATZ = Pattern.compile("Halbsatz(?: \\d+[a-z]?)?");
+ // „Die Inhaltsübersicht wird entsprechend der vorstehenden Nummer 8 Buchst. a geändert.“ — ein
+ // Befehl, der seinen Inhalt nicht nennt, sondern auf einen anderen Punkt verweist. Verankert auf
+ // den ganzen Satz, damit ein bloß adverbiales „entsprechend“ nicht mitgerissen wird; ohne
+ // verschachtelte Quantoren und daher für die Mustersuche kostenneutral.
+ private static final Pattern VERWEISENDE_AENDERUNG =
+ Pattern.compile(
+ "^Die Inhaltsübersicht wird entsprechend (?:der|dem) "
+ + "(?:vorstehenden |vorgenannten |nachstehenden )?(.+?) geändert\\.$");
+
private static final Pattern EBENE_BEZEICHNUNG =
Pattern.compile(
"^(?:(?:§|Art\\.) (\\d+[a-z]?)|(?:Absatz|Abs\\.) (\\d+[a-z]?)|Satz(?: (\\d+[a-z]?))?|Sätze"
@@ -880,6 +890,13 @@ final class BefehlErkenner {
Matcher m;
+ // Die Verweisung auf einen anderen Punkt desselben Artikels. Sie steht ganz vorn, weil sie
+ // den vollen Satz beansprucht und sonst von der Neufassung an sich gezogen würde.
+ if ((m = VERWEISENDE_AENDERUNG.matcher(text)).matches()) {
+ return Optional.of(
+ new VerweisenderBefehl(mitInhaltsuebersicht(kontext), m.group(1).strip(), provenienz));
+ }
+
// Inhaltsübersichts-Angaben zuerst prüfen, bevor NEUFASSUNG/STRUKTUR_ERSETZUNG die Phrase
// strukturell (aber mit unparsbarer Stelle) an sich ziehen.
if ((m = INHALTSUEBERSICHT_ANGABE.matcher(text)).matches()) {
diff --git a/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java b/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java
index 64c6564..8d9b7e7 100644
--- a/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java
+++ b/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java
@@ -18,6 +18,7 @@ import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturEinfuegung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturErsetzung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Umnummerierung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.UnbekannterBefehl;
+import eu.mulk.aendggner.aenderung.Aenderungsbefehl.VerweisenderBefehl;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WoerterEinfuegung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortAnker;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortlautVoranstellung;
@@ -667,6 +668,20 @@ public final class BefehlAnwender {
if (befehl instanceof UnbekannterBefehl) {
return manuell(befehl, Grund.NICHT_ERKANNT, "Befehl nicht erkannt.");
}
+ // Gelesen, aber bewusst nicht ausgeführt. Die Weiche steht vor der Inhaltsübersichts-Weiche,
+ // damit die Rüge den Verweis nennt und nicht bloß die allgemeine Grenze jener Norm: Die
+ // sinngemäße Übertragung eines anderen Punktes setzte einen Rückgriff auf die Befehlsliste und
+ // eine Umdeutung des Ziels voraus („Überschrift des § 13“ → Titelspalte der Übersichtszeile),
+ // die dieser Anwender nicht leistet. Sie zu erraten wäre schlimmer, als sie zu benennen.
+ if (befehl instanceof VerweisenderBefehl v) {
+ return manuell(
+ befehl,
+ Grund.NICHT_UNTERSTUETZT,
+ "Der Befehl verweist auf „"
+ + v.verweis()
+ + "“ desselben Artikels; die sinngemäße Übertragung auf die Inhaltsübersicht ist"
+ + " nicht umgesetzt.");
+ }
// Sammelbefehle vor den Spezialweichen dispatchen (jeder Teil wird einzeln geroutet).
if (befehl instanceof Sammelbefehl s) {
return wendeSammelAn(normen, gliederungen, s);
@@ -724,6 +739,9 @@ public final class BefehlAnwender {
wendeGliederungsUeberschriftenAn(normen, gliederungen, g);
case Sammelbefehl s -> wendeSammelAn(normen, gliederungen, s);
case UnbekannterBefehl u -> manuell(befehl, Grund.NICHT_ERKANNT, "Befehl nicht erkannt.");
+ // Oben abgefangen; die Weiche muss ihn gleichwohl kennen.
+ case VerweisenderBefehl v ->
+ manuell(befehl, Grund.NICHT_UNTERSTUETZT, "Verweisender Befehl.");
};
} catch (RuntimeException e) {
return manuell(befehl, Grund.FEHLGESCHLAGEN, "Anwendung fehlgeschlagen: " + e);
diff --git a/src/test/java/eu/mulk/aendggner/EndToEndTest.java b/src/test/java/eu/mulk/aendggner/EndToEndTest.java
index d0273ad..8cd867e 100644
--- a/src/test/java/eu/mulk/aendggner/EndToEndTest.java
+++ b/src/test/java/eu/mulk/aendggner/EndToEndTest.java
@@ -10,6 +10,7 @@ import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Ersetzung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Sammelbefehl;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturEinfuegung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.UnbekannterBefehl;
+import eu.mulk.aendggner.aenderung.Aenderungsbefehl.VerweisenderBefehl;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortAnker;
import eu.mulk.aendggner.aenderung.parse.AenderungsantragParser;
import eu.mulk.aendggner.aenderung.parse.AenderungsgesetzParser;
@@ -19,6 +20,7 @@ import eu.mulk.aendggner.aenderung.parse.SuperskriptModus;
import eu.mulk.aendggner.aenderung.parse.TextBereiniger;
import eu.mulk.aendggner.aenderung.parse.ZitatExtraktor;
import eu.mulk.aendggner.anwendung.BefehlAnwender;
+import eu.mulk.aendggner.anwendung.Grund;
import eu.mulk.aendggner.anwendung.Nachfassungsabgleich;
import eu.mulk.aendggner.gesetz.Absatz;
import eu.mulk.aendggner.gesetz.Gesetz;
@@ -1889,14 +1891,20 @@ class EndToEndTest {
assertThat(befehlAn(parseErgebnis, "5. a) aa)")).isInstanceOf(Sammelbefehl.class);
assertThat(befehlAn(parseErgebnis, "7. a) aa)")).isInstanceOf(Ersetzung.class);
- // Eine benannte Grenze bleibt: die Verweisung auf einen anderen Punkt desselben Artikels
- // („Die Inhaltsübersicht wird entsprechend der vorstehenden Nummer 8 Buchst. a geändert“).
- var unerkannt =
- parseErgebnis.befehle().stream()
- .filter(b -> b instanceof UnbekannterBefehl)
- .map(b -> b.provenienz().gliederungsPfad())
- .toList();
- assertThat(unerkannt).containsExactly("12.");
+ // Kein Befehl des Heftes bleibt mehr ungelesen.
+ assertThat(parseErgebnis.befehle()).noneMatch(b -> b instanceof UnbekannterBefehl);
+
+ // Die Verweisung auf einen anderen Punkt desselben Artikels wird gelesen, aber bewusst nicht
+ // ausgeführt. Der Unterschied ist kein kosmetischer: Die Synopse sagt fortan, dass das
+ // Erzeugnis hier die Grenze zieht, und nicht, dass die Vorlage unverständlich sei.
+ var verweisung = befehlAn(parseErgebnis, "12.");
+ assertThat(verweisung).isInstanceOf(VerweisenderBefehl.class);
+ assertThat(((VerweisenderBefehl) verweisung).verweis()).isEqualTo("Nummer 8 Buchst. a");
+
+ var anwendung = BefehlAnwender.anwenden(gesetz, List.of(verweisung));
+ assertThat(anwendung.protokoll().get(0).grund()).isEqualTo(Grund.NICHT_UNTERSTUETZT);
+ assertThat(anwendung.protokoll().get(0).begruendung())
+ .contains("verweist auf „Nummer 8 Buchst. a“");
}
private static Aenderungsbefehl befehlAn(
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 80234b8..327c8db 100644
--- a/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java
+++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java
@@ -15,6 +15,7 @@ import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Streichung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturEinfuegung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.StrukturErsetzung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Umnummerierung;
+import eu.mulk.aendggner.aenderung.Aenderungsbefehl.VerweisenderBefehl;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WoerterEinfuegung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortAnker;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.WortlautZuAbsatz;
@@ -1514,4 +1515,33 @@ class BefehlErkennerTest {
assertThat(ersetzung.alt()).isEqualTo(";");
assertThat(ersetzung.neu()).isEqualTo(",");
}
+
+ /**
+ * Die Verweisung auf einen anderen Punkt desselben Artikels wird gelesen, aber nicht ausgeführt.
+ * Erkannt zu werden ist gleichwohl mehr als gar nichts: Die Rüge sagt dann, dass das Erzeugnis
+ * die Grenze zieht, und nicht, dass die Vorlage unverständlich sei.
+ */
+ @Test
+ void erkenntDieVerweisungAufEinenAnderenPunkt() {
+ var befehl =
+ erkenne(
+ "Die Inhaltsübersicht wird entsprechend der vorstehenden Nummer 8 Buchst. a geändert.",
+ Stelle.LEER);
+
+ assertThat(befehl).containsInstanceOf(VerweisenderBefehl.class);
+ var verweisung = (VerweisenderBefehl) befehl.orElseThrow();
+ assertThat(verweisung.verweis()).isEqualTo("Nummer 8 Buchst. a");
+ assertThat(verweisung.stelle().betrifftInhaltsuebersicht()).isTrue();
+ }
+
+ /** Ein bloß adverbiales „entsprechend“ wird davon nicht mitgerissen. */
+ @Test
+ void adverbialesEntsprechendIstKeineVerweisung() {
+ var befehl =
+ erkenne(
+ "In § 5 werden die Wörter „entsprechend der Anlage“ durch die Wörter „nach der"
+ + " Anlage“ ersetzt.",
+ Stelle.LEER);
+ assertThat(befehl).containsInstanceOf(Ersetzung.class);
+ }
}