blob: 606383f244106060ce541e1c32d37c686d3d1616 [file] [log] [blame]
Matthias Andreas Benkardd1e2fac2026-07-13 07:09:04 +02001package eu.mulk.aendggner.aenderung;
2
3import org.jspecify.annotations.Nullable;
4
5/**
6 * Ein einzelner Änderungsbefehl eines Änderungsgesetzes, wie er im Handbuch der Rechtsförmlichkeit
7 * vorgesehen ist. Nicht erkannte Befehle landen als {@link UnbekannterBefehl} im Ergebnis — sie
8 * werden nie stillschweigend verworfen.
9 */
10public sealed interface Aenderungsbefehl {
11
12 /** Die betroffene Stelle im Stammgesetz. */
13 Stelle stelle();
14
15 /** Herkunft des Befehls im Änderungsgesetz. */
16 Provenienz provenienz();
17
18 /** Strukturelle Ebene eines eingefügten oder angefügten Elements. */
19 enum Ebene {
20 PARAGRAPH,
21 ABSATZ,
22 SATZ,
23 NUMMER,
24 BUCHSTABE
25 }
26
27 /** Anker für Wörter-Einfügungen innerhalb eines Textbereichs. */
28 sealed interface WortAnker {
29 record NachWoertern(String woerter) implements WortAnker {}
30
31 record VorWoertern(String woerter) implements WortAnker {}
32
33 record AmEnde() implements WortAnker {}
34
35 record VorKommaAmEnde() implements WortAnker {}
36 }
37
38 /** „… werden die Wörter „A“ durch die Wörter „B“ ersetzt.“ */
39 record Ersetzung(
40 Stelle stelle, String alt, String neu, boolean jeweils, boolean amEnde, Provenienz provenienz)
41 implements Aenderungsbefehl {}
42
43 /** „§ X wird wie folgt gefasst: „…““ */
44 record Neufassung(Stelle stelle, String neuerText, Provenienz provenienz)
45 implements Aenderungsbefehl {}
46
Matthias Andreas Benkard8ae49722026-07-13 21:32:53 +020047 /**
48 * „§ 2 Absatz 2 wird durch die folgenden Absätze 2 und 3 ersetzt: „…““ — ein Ziel wird durch
49 * einen Block ersetzt, der auch mehrere neue Einheiten enthalten darf.
Matthias Andreas Benkardebd5a7b2026-07-15 20:54:27 +020050 *
51 * @param stelle das (erste) zu ersetzende Ziel.
52 * @param bisStelle bei einem zusammenhängenden Bereich („Die Absätze 8 und 9 …“, „Die Sätze 4 bis
53 * 5 …“) das letzte Ziel; {@code null} bei einem Einzelziel.
Matthias Andreas Benkard8ae49722026-07-13 21:32:53 +020054 */
Matthias Andreas Benkardebd5a7b2026-07-15 20:54:27 +020055 record StrukturErsetzung(
56 Stelle stelle, @Nullable Stelle bisStelle, Ebene ebene, String text, Provenienz provenienz)
57 implements Aenderungsbefehl {
58
59 /** Einzelziel-Konstruktor (kein Bereich). */
60 public StrukturErsetzung(Stelle stelle, Ebene ebene, String text, Provenienz provenienz) {
61 this(stelle, null, ebene, text, provenienz);
62 }
63 }
Matthias Andreas Benkard8ae49722026-07-13 21:32:53 +020064
Matthias Andreas Benkardd1e2fac2026-07-13 07:09:04 +020065 /** „… werden nach dem Wort „A“ die Wörter „B“ eingefügt.“ */
66 record WoerterEinfuegung(Stelle stelle, WortAnker anker, String woerter, Provenienz provenienz)
67 implements Aenderungsbefehl {}
68
69 /**
70 * „Nach § 28 wird folgender § 28a eingefügt: „…““
71 *
72 * @param stelle die Ankerstelle, relativ zu der eingefügt wird.
73 * @param vorher {@code true} bei „Vor …“, {@code false} bei „Nach …“.
74 * @param bezeichnung die Bezeichnung des neuen Elements (z.B. „28a“, „5a“); {@code null}, wenn
75 * der Befehl keine nennt (z.B. „folgender Satz“).
Matthias Andreas Benkard5f30f562026-07-28 06:00:16 +020076 * @param anker bei „Vor den Wörtern „Aus dem Bereich Verkehr:“ wird folgender Absatz 5
77 * eingefügt“ der Wortanker, der die Position innerhalb von {@code stelle} bestimmt;
78 * {@code null}, wenn die Position wie üblich aus der Struktur folgt.
Matthias Andreas Benkardd1e2fac2026-07-13 07:09:04 +020079 */
80 record StrukturEinfuegung(
81 Stelle stelle,
82 boolean vorher,
83 Ebene ebene,
84 @Nullable String bezeichnung,
85 String text,
Matthias Andreas Benkard5f30f562026-07-28 06:00:16 +020086 @Nullable WortAnker anker,
Matthias Andreas Benkardd1e2fac2026-07-13 07:09:04 +020087 Provenienz provenienz)
Matthias Andreas Benkard5f30f562026-07-28 06:00:16 +020088 implements Aenderungsbefehl {
89
90 /** Konstruktor für die strukturbestimmte Position (kein Wortanker). */
91 public StrukturEinfuegung(
92 Stelle stelle,
93 boolean vorher,
94 Ebene ebene,
95 @Nullable String bezeichnung,
96 String text,
97 Provenienz provenienz) {
98 this(stelle, vorher, ebene, bezeichnung, text, null, provenienz);
99 }
100 }
Matthias Andreas Benkardd1e2fac2026-07-13 07:09:04 +0200101
102 /** „Folgender Absatz 9 wird angefügt: „…““ / „Dem Absatz 3 wird folgender Satz angefügt: …“ */
103 record Anfuegung(
104 Stelle stelle, Ebene ebene, @Nullable String bezeichnung, String text, Provenienz provenienz)
105 implements Aenderungsbefehl {}
106
107 /** „§ X / Absatz Y wird aufgehoben.“ */
108 record Aufhebung(Stelle stelle, Provenienz provenienz) implements Aenderungsbefehl {}
109
110 /** „… werden die Wörter „A“ gestrichen.“ */
111 record Streichung(Stelle stelle, String woerter, Provenienz provenienz)
112 implements Aenderungsbefehl {}
113
114 /** „Der bisherige Absatz 2 wird Absatz 3.“ */
115 record Umnummerierung(Stelle stelle, Stelle neu, Provenienz provenienz)
116 implements Aenderungsbefehl {}
117
Matthias Andreas Benkardb05e44a2026-07-13 21:33:20 +0200118 /**
Matthias Andreas Benkard9a29b382026-07-13 21:33:43 +0200119 * „Der Wortlaut wird Absatz 1.“ — der bisher unnummerierte Normtext erhält die Absatznummer, wird
120 * also zum ersten Absatz (Vorbereitung für das Anfügen weiterer Absätze).
121 */
122 record WortlautZuAbsatz(Stelle stelle, String nummer, Provenienz provenienz)
123 implements Aenderungsbefehl {}
124
125 /**
Matthias Andreas Benkard65eff082026-07-18 12:24:32 +0200126 * „Der Wortlaut wird Satz 1.“ (bayerisches Landesrecht) — der bisher unnummerierte Text erhält
127 * die amtliche Satznummer als Superskript (Vorbereitung für das Anfügen weiterer Sätze).
128 */
129 record WortlautZuSatz(Stelle stelle, String nummer, Provenienz provenienz)
130 implements Aenderungsbefehl {}
131
132 /**
133 * „Dem Wortlaut werden die folgenden Abs. 1 bis 4 vorangestellt: „…““ (bayerisches Landesrecht) —
134 * neue Absätze treten vor den bisherigen Normtext.
135 */
136 record WortlautVoranstellung(Stelle stelle, String text, Provenienz provenienz)
137 implements Aenderungsbefehl {}
138
139 /**
140 * „Fußnote 1 wird aufgehoben.“ / „Die Fußnoten 9 und 10 werden aufgehoben.“ (bayerisches
141 * Landesrecht) — entfernt die Fußnotenzeile(n) „ⁿ) [Amtl. Anm.:] …“ samt der Inline-Marker „ⁿ)“
142 * aus der Kontextnorm.
143 */
144 record FussnotenAufhebung(Stelle stelle, java.util.List<String> nummern, Provenienz provenienz)
145 implements Aenderungsbefehl {
146
147 public FussnotenAufhebung {
148 nummern = java.util.List.copyOf(nummern);
149 }
150 }
151
152 /**
153 * „In Satz 1 wird die Satznummerierung „1“ gestrichen.“ (bayerisches Landesrecht) — entfernt die
154 * amtliche Superskript-Satznummer am Anfang des bezeichneten Bereichs (etwa nachdem der zweite
155 * und letzte Satz eines Absatzes aufgehoben wurde).
156 */
157 record SatznummerierungStreichung(Stelle stelle, String nummer, Provenienz provenienz)
158 implements Aenderungsbefehl {}
159
160 /**
Matthias Andreas Benkardb7e9f0f2026-07-16 21:12:08 +0200161 * „Nach § 33 werden die folgenden Überschriften zu Teil 3 und zu Teil 3 Abschnitt 1 eingefügt:
162 * „…““ bzw. „Die bisherigen Überschriften zu Teil 4 und Teil 4 Abschnitt 1 werden durch die
163 * folgende Überschrift zu Abschnitt 2 ersetzt: „…““ — neue Gliederungs-Überschriften im
164 * Gliederungsbaum.
165 *
166 * @param stelle der Anker-§ („Nach § 33“); leer bei der Ersetzungsform.
167 * @param neue die neuen Einheiten in Zitatreihenfolge (Titel stehen im Zitat).
168 * @param ersetzte die zu ersetzenden bisherigen Einheiten (leer bei der Einfügeform); jede als
169 * Pfad („Teil 4 Abschnitt 1“ → [Teil 4, Abschnitt 1]).
170 * @param text das Zitat mit den Überschriften.
171 */
172 record GliederungsUeberschriften(
173 Stelle stelle,
174 java.util.List<Stelle.Gliederungseinheit> neue,
175 java.util.List<java.util.List<Stelle.Gliederungseinheit>> ersetzte,
176 String text,
177 Provenienz provenienz)
178 implements Aenderungsbefehl {
179
180 public GliederungsUeberschriften {
181 neue = java.util.List.copyOf(neue);
182 ersetzte = java.util.List.copyOf(ersetzte);
183 }
184 }
185
186 /**
Matthias Andreas Benkardb05e44a2026-07-13 21:33:20 +0200187 * „In A und B wird jeweils …“ — ein Befehl, der dieselbe Operation auf mehrere, per „und“
188 * koordinierte Stellen anwendet. Die Teilbefehle teilen sich Provenienz und Befehlszeile; der
189 * Applier fasst sie zu einem Protokolleintrag zusammen.
190 */
191 record Sammelbefehl(java.util.List<Aenderungsbefehl> teilbefehle) implements Aenderungsbefehl {
192
193 public Sammelbefehl {
194 teilbefehle = java.util.List.copyOf(teilbefehle);
195 }
196
197 @Override
198 public Stelle stelle() {
199 return teilbefehle.get(0).stelle();
200 }
201
202 @Override
203 public Provenienz provenienz() {
204 return teilbefehle.get(0).provenienz();
205 }
206 }
207
Matthias Andreas Benkardd1e2fac2026-07-13 07:09:04 +0200208 /** Fallback für alles, was der Parser nicht versteht — muss manuell geprüft werden. */
209 record UnbekannterBefehl(Stelle stelle, String originalText, Provenienz provenienz)
210 implements Aenderungsbefehl {}
211}