Support the two Lower Saxony insertion forms; NEFG now applies fully
The NEFG acceptance case left two commands as "check manually". Both are
now supported, so Lower Saxony applies 7 of 7 with no remainder.
* Lower Saxony cites inserted paragraphs with a space before the sub
number ("§ 2 a"); the rest of German legal usage writes "§ 2a", which
is what the Stelle and level parsers expect. TextBereiniger now pulls
the form together, leaving enumeration markers of the amendment act
alone ("… nach § 8 c) In Absatz 2 …").
* "In Kapitel 4 wird nach § 12 der folgende neue § 13 angefügt" — the
division only names the section the new paragraph lands in; the
anchor governs the position, as in the plain form. The optional
"neue" is now accepted in both.
Applying that insertion needed one more thing: the paragraph it creates
is only vacated by the *following* command ("Der bisherige § 13 wird
§ 14"), so in document order the two collided and the insertion was
rejected. "Bisherig" denotes the state before the amendment, so the
renumbering logically precedes the reoccupation and is now pulled ahead.
The log still lists commands in the order of the amendment act.
226 tests green; all other pinned figures unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I0e2ea5b0389f8002157eeb8471800da51febe739
diff --git a/FASSUNGEN.txt b/FASSUNGEN.txt
index dd458df..e1528ef 100644
--- a/FASSUNGEN.txt
+++ b/FASSUNGEN.txt
@@ -44,6 +44,10 @@
Kurztitel und Abkürzung im Klammerzusatz und eine Strukturgrenze für unbalancierte
Anführungszeichen nötig.
+Schließlich (Artikel 8 bis 10) werden die beiden niedersächsischen Einfügeformen
+ertüchtigt, die bislang als Grenze dokumentiert waren; das Niedersächsische
+ELER-Fördergesetz wird damit ohne Rest umgesetzt.
+
Artikel 1
Seitenkopf des Gesetz- und Verordnungsblatts für Schleswig-Holstein
@@ -136,6 +140,42 @@
Ausführungsgesetz) werden zutreffend nicht gewählt.
+Artikel 8
+Sachnummern mit Leerzeichen
+
+Niedersachsen zitiert eingeschobene Paragraphen mit einem Leerzeichen vor der
+Sachnummer („§ 2 a“), die übrige Rechtssprache ohne („§ 2a“). Stellen- und
+Ebenenparser erkannten die niedersächsische Form nicht. Der Textbereiniger zieht
+sie nunmehr auf die kanonische Form zusammen (Muster SACHNUMMER_MIT_LEERZEICHEN);
+ein folgender Aufzählungsmarker des Änderungsgesetzes („… nach § 8 c) In Absatz 2
+…“) bleibt ausgenommen.
+
+
+Artikel 9
+Gliederungsbezogene Einfügung eines Paragraphen
+
+Der Befehlserkenner (BefehlErkenner) erkannte die Einfügung eines Paragraphen nur
+in der ankergeführten Form („Nach § 12 wird der folgende § 13 angefügt“). Die
+gliederungsbezogene Form „In Kapitel 4 wird nach § 12 der folgende neue § 13
+angefügt“ tritt hinzu (Muster STRUKTUR_EINFUEGUNG_IN_GLIEDERUNG); die
+Gliederungsangabe nennt nur den Abschnitt, maßgeblich für die Position bleibt der
+Anker. Zugleich wird das Beiwort „neu“ in beiden Formen zugelassen.
+
+
+Artikel 10
+Vorrang der Umnummerierung vor der Neubesetzung
+
+Der Befehlsanwender (BefehlAnwender) wandte die Befehle stets in der Reihenfolge
+des Änderungsgesetzes an. Besetzt eine Einfügung einen Paragraphen neu, dessen
+bisheriger Träger erst durch einen nachfolgenden Befehl umnummeriert wird („In
+Kapitel 4 wird nach § 12 der folgende neue § 13 angefügt“ vor „Der bisherige § 13
+wird § 14“), so führte das auf zwei Paragraphen gleicher Bezeichnung und die
+Einfügung wurde zurückgewiesen. Das Wort „bisherig“ bezeichnet den Stand vor der
+Änderung; die Umnummerierung geht der Neubesetzung sachlich voraus und wird
+deshalb vorgezogen (BefehlAnwender.anwendungsReihenfolge). Protokolliert wird
+weiterhin in der Reihenfolge des Änderungsgesetzes.
+
+
════════════════════════════════════════════════════════════════════════════════
Fassung vom 24. Juli 2026,
zuletzt geändert durch die am 24. Juli 2026 vorgenommenen Änderungen
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 fb578cc..80206f6 100644
--- a/src/main/java/eu/mulk/aendggner/aenderung/parse/BefehlErkenner.java
+++ b/src/main/java/eu/mulk/aendggner/aenderung/parse/BefehlErkenner.java
@@ -200,7 +200,19 @@
private static final Pattern STRUKTUR_EINFUEGUNG =
Pattern.compile(
- "^(Nach|Vor) (.+?) (?:wird|werden) (?:der |die |das )?folgende[nrs]? (.+?) "
+ "^(Nach|Vor) (.+?) (?:wird|werden) (?:der |die |das )?folgende[nrs]? (?:neue[nrs]? )?(.+?) "
+ + "(?:ein|an)gefügt: "
+ + ENUM
+ + Z
+ + "\\.?$");
+
+ // „In Kapitel 4 wird nach § 12 der folgende neue § 13 angefügt: „…““ — gliederungsbezogene
+ // Einfügung. Die Gliederungsangabe nennt nur den Abschnitt, in dem die neue Einheit landet;
+ // maßgeblich für die Position ist der Anker („nach § 12“), der ohnehin eindeutig ist.
+ private static final Pattern STRUKTUR_EINFUEGUNG_IN_GLIEDERUNG =
+ Pattern.compile(
+ "^In (?:Buch|Teil|Kapitel|Abschnitt|Unterabschnitt|Titel) \\S+ (?:wird|werden) "
+ + "(?i:(nach|vor)) (.+?) (?:der |die |das )?folgende[nrs]? (?:neue[nrs]? )?(.+?) "
+ "(?:ein|an)gefügt: "
+ ENUM
+ Z
@@ -897,8 +909,9 @@
provenienz));
}
- if ((m = STRUKTUR_EINFUEGUNG.matcher(text)).matches()) {
- var vorher = m.group(1).equals("Vor");
+ if ((m = STRUKTUR_EINFUEGUNG.matcher(text)).matches()
+ || (m = STRUKTUR_EINFUEGUNG_IN_GLIEDERUNG.matcher(text)).matches()) {
+ var vorher = m.group(1).equalsIgnoreCase("vor");
var stelle = StellenParser.parse(m.group(2));
if (stelle.isEmpty()) {
return Optional.empty();
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 7460b15..f1b75e1 100644
--- a/src/main/java/eu/mulk/aendggner/aenderung/parse/TextBereiniger.java
+++ b/src/main/java/eu/mulk/aendggner/aenderung/parse/TextBereiniger.java
@@ -190,6 +190,13 @@
private static final Pattern INVERTIERTES_LISTEN_ZITAT =
Pattern.compile("(?m)^(\\s*)(\\d+[a-z]?\\.|[a-z]{1,3}\\))[ \\t]+„[ \\t]+");
+ // Sachnummern mit Leerzeichen: Niedersachsen zitiert eingeschobene Paragraphen als „§ 2 a“, der
+ // Rest der Rechtssprache als „§ 2a“. Auf die kanonische Form ziehen, damit Stellen- und
+ // Ebenenparser greifen. Ein folgendes „)“ oder „.“ schließt Aufzählungsmarker des
+ // Änderungsgesetzes aus („… nach § 8 c) In Absatz 2 …“).
+ private static final Pattern SACHNUMMER_MIT_LEERZEICHEN =
+ Pattern.compile("(§|Art\\.) (\\d+) ([a-z])(?![a-zäöüß).])");
+
private TextBereiniger() {}
public static String bereinige(String rohText) {
@@ -206,7 +213,8 @@
var verbunden = verbindeUmbrueche(zeilen);
// Falsch-positive markerlose Zusammenzüge („durch“ + „die“ → „durchdie“) reparieren — die
// Befehlsvokabeln sind nie Kompositum-Bestandteile.
- return loeseArtikelFussnoten(trenneVerklebteZitatgrenzen(reflowUndStrippe(verbunden)));
+ var ergebnis = loeseArtikelFussnoten(trenneVerklebteZitatgrenzen(reflowUndStrippe(verbunden)));
+ return SACHNUMMER_MIT_LEERZEICHEN.matcher(ergebnis).replaceAll("$1 $2$3");
}
/**
diff --git a/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java b/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java
index b6bee1b..b2e855d 100644
--- a/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java
+++ b/src/main/java/eu/mulk/aendggner/anwendung/BefehlAnwender.java
@@ -2,6 +2,7 @@
import eu.mulk.aendggner.aenderung.Aenderungsbefehl;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Anfuegung;
+import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Ebene;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Aufhebung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.Ersetzung;
import eu.mulk.aendggner.aenderung.Aenderungsbefehl.FussnotenAufhebung;
@@ -26,6 +27,7 @@
import eu.mulk.aendggner.gesetz.Norm;
import eu.mulk.aendggner.gesetz.Superskript;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -71,16 +73,20 @@
var protokoll = new ArrayList<AngewandteAenderung>();
String neuerLangtitel = null;
- for (var befehl : befehle) {
+ // Angewandt wird in Sachreihenfolge, protokolliert in der Reihenfolge des Änderungsgesetzes.
+ var ergebnisse = new AngewandteAenderung[befehle.size()];
+ for (int index : anwendungsReihenfolge(befehle)) {
+ var befehl = befehle.get(index);
// „Die Überschrift wird wie folgt gefasst / durch die folgende Überschrift ersetzt“ auf
// oberster Ebene meint die Überschrift des Gesetzes selbst.
if (befehl instanceof Neufassung n && istNurUeberschrift(n.stelle())) {
neuerLangtitel = n.neuerText().replaceAll("\\s+", " ").strip();
- protokoll.add(angewandt(befehl, "(Gesetzesüberschrift)"));
+ ergebnisse[index] = angewandt(befehl, "(Gesetzesüberschrift)");
continue;
}
- protokoll.add(wendeAn(normen, gliederungen, befehl));
+ ergebnisse[index] = wendeAn(normen, gliederungen, befehl);
}
+ protokoll.addAll(Arrays.asList(ergebnisse));
var neu = alt.mitNormen(normen).mitGliederungen(gliederungen);
if (neuerLangtitel != null) {
@@ -89,6 +95,47 @@
return new AnwendungsErgebnis(neu, protokoll);
}
+ /**
+ * Reihenfolge, in der die Befehle anzuwenden sind: grundsätzlich die des Änderungsgesetzes.
+ *
+ * <p>Eine Umnummerierung „Der bisherige § 13 wird § 14“ wird jedoch vor eine vorangehende
+ * Einfügung gezogen, die denselben Paragraphen neu besetzt („In Kapitel 4 wird nach § 12 der
+ * folgende neue § 13 angefügt“). „Bisherig“ bezeichnet den Stand vor der Änderung; die
+ * Umnummerierung geht der Neubesetzung sachlich also voraus. In der Textreihenfolge angewandt
+ * liefen beide Befehle dagegen auf zwei Paragraphen gleicher Bezeichnung hinaus.
+ */
+ private static List<Integer> anwendungsReihenfolge(List<Aenderungsbefehl> befehle) {
+ var reihenfolge = new ArrayList<Integer>(befehle.size());
+ for (int i = 0; i < befehle.size(); i++) {
+ reihenfolge.add(i);
+ }
+ for (int j = 0; j < befehle.size(); j++) {
+ if (!(befehle.get(j) instanceof Umnummerierung u) || !nurParagraph(u.stelle())) {
+ continue;
+ }
+ var quelle = u.stelle().paragraph().get().enbez();
+ for (int i = 0; i < j; i++) {
+ if (quelle.equals(neuerParagraph(befehle.get(i)))) {
+ reihenfolge.remove(Integer.valueOf(j));
+ reihenfolge.add(reihenfolge.indexOf(i), j);
+ break;
+ }
+ }
+ }
+ return reihenfolge;
+ }
+
+ /** Bezeichnung des Paragraphen, den {@code befehl} neu anlegt — sonst {@code null}. */
+ private static @Nullable String neuerParagraph(Aenderungsbefehl befehl) {
+ if (!(befehl instanceof StrukturEinfuegung s)
+ || s.ebene() != Ebene.PARAGRAPH
+ || s.bezeichnung() == null) {
+ return null;
+ }
+ var sigel = s.stelle().paragraph().map(Stelle.Paragraph::sigel).orElse("§");
+ return sigel + " " + s.bezeichnung();
+ }
+
private static boolean istNurUeberschrift(Stelle stelle) {
return stelle.komponenten().size() == 1
&& stelle.komponenten().get(0) instanceof Stelle.Ueberschrift;
diff --git a/src/main/resources/sampledata/Landesrecht-Beispiele.adoc b/src/main/resources/sampledata/Landesrecht-Beispiele.adoc
index 1d831ac..52ab028 100644
--- a/src/main/resources/sampledata/Landesrecht-Beispiele.adoc
+++ b/src/main/resources/sampledata/Landesrecht-Beispiele.adoc
@@ -88,9 +88,9 @@
der archivierten revosax-Volltextfassung abgeleitet) und End-to-End-Akzeptanztest
(`EndToEndTest.saechsBeamtVgAcceptance`; fünf Befehle, kein Rest).
* *Niedersachsen* ist umgesetzt: `Niedersachsen/NEFG-alt.txt` (seit 2022 unveränderter NEFG, aus
- dem zweispaltigen Nds. GVBl 2022 Nr. 33) und `EndToEndTest.nefgAcceptance` (fünf von sieben
- Befehlen angewandt; zwei Einfügeformen — Sachnummer mit Leerzeichen „§ 2 a“, kapitelbezogene
- §-Block-Einfügung — noch nicht unterstützt, als Grenze dokumentiert).
+ dem zweispaltigen Nds. GVBl 2022 Nr. 33) und `EndToEndTest.nefgAcceptance` (alle sieben Befehle
+ angewandt, kein Rest — einschließlich der beiden niedersächsischen Einfügeformen: Sachnummer mit
+ Leerzeichen „§ 2 a“ und gliederungsbezogene Einfügung „In Kapitel 4 wird nach § 12 …“).
* *Schleswig-Holstein* ist bis einschließlich der Befehlserkennung umgesetzt
(`EndToEndTest.kommunalrechtAendGSchleswigHolstein`): Artikel 1 trifft die Gemeindeordnung,
Artikel 2 die Kreisordnung, je ein Neufassungsbefehl, kein unbekannter Befehl. Ein voller
diff --git a/src/test/java/eu/mulk/aendggner/EndToEndTest.java b/src/test/java/eu/mulk/aendggner/EndToEndTest.java
index b89a367..e7f7a00 100644
--- a/src/test/java/eu/mulk/aendggner/EndToEndTest.java
+++ b/src/test/java/eu/mulk/aendggner/EndToEndTest.java
@@ -402,21 +402,18 @@
assertThat(parseErgebnis.artikel()).containsExactly("1");
assertThat(parseErgebnis.befehle()).hasSize(7);
- // Fünf der sieben Befehle werden angewandt. Zwei bleiben als „manuell prüfen“ stehen — zwei
- // Einfügeformen, die ÄndGgner noch nicht beherrscht (bewusst dokumentierte Grenze, nicht
- // stillschweigend verworfen):
- // * Nr. 3 „Nach § 2 wird der folgende § 2 a eingefügt“ — Einfügung eines §-Blocks mit einer
- // durch Leerzeichen getrennten Sachnummer („§ 2 a“).
- // * Nr. 5 „In Kapitel 4 wird nach § 12 der folgende neue § 13 angefügt“ — kapitelbezogene
- // §-Block-Einfügung.
+ // Alle sieben Befehle werden angewandt, darunter die beiden niedersächsischen Einfügeformen:
+ // * Nr. 3 „Nach § 2 wird der folgende § 2 a eingefügt“ — Sachnummer mit Leerzeichen.
+ // * Nr. 5 „In Kapitel 4 wird nach § 12 der folgende neue § 13 angefügt“ — gliederungs-
+ // bezogene Einfügung, deren Zielbezeichnung erst der nachfolgende Befehl Nr. 6 freimacht.
var anwendung = BefehlAnwender.anwenden(gesetz, parseErgebnis.befehle());
- assertThat(anwendung.anzahlAngewandt()).isEqualTo(5);
- var manuellPfade =
- anwendung.protokoll().stream()
- .filter(a -> a.status() == BefehlAnwender.Status.MANUELL_PRUEFEN)
- .map(a -> a.befehl().provenienz().gliederungsPfad())
- .toList();
- assertThat(manuellPfade).containsExactlyInAnyOrder("3.", "5.");
+ assertThat(anwendung.anzahlAngewandt()).isEqualTo(7);
+ assertThat(anwendung.protokoll())
+ .noneMatch(a -> a.status() == BefehlAnwender.Status.MANUELL_PRUEFEN);
+ // Protokolliert wird trotz vorgezogener Umnummerierung in der Reihenfolge des Gesetzes.
+ assertThat(anwendung.protokoll())
+ .extracting(a -> a.befehl().provenienz().gliederungsPfad())
+ .containsExactly("1. a)", "1. b)", "2.", "3.", "4.", "5.", "6.");
// Stichproben: „erhält folgende Fassung“ (§ 1 Abs. 1, § 2), Angaben-Ersetzung (§ 1 Abs. 5),
// Wörter-Einfügung (§ 6 Abs. 1) und §-Umnummerierung (§ 13 → § 14).
@@ -426,7 +423,18 @@
assertThat(neu.norm("§ 1").orElseThrow().absaetze().get(4).text()).contains("§ 14 Abs. 3");
assertThat(neu.norm("§ 2").orElseThrow().titel()).isEqualTo("Registriernummer");
assertThat(neu.norm("§ 6").orElseThrow().gesamtText()).contains("8 bis 10");
- assertThat(neu.norm("§ 14")).isPresent();
+
+ // Die beiden neuen Paragraphen stehen an der richtigen Stelle, der bisherige § 13 ist § 14.
+ assertThat(neu.normen()).hasSize(15);
+ assertThat(neu.normen())
+ .extracting(n -> n.enbez())
+ .containsSubsequence("§ 2", "§ 2a", "§ 3")
+ .containsSubsequence("§ 12", "§ 13", "§ 14");
+ assertThat(neu.norm("§ 2a").orElseThrow().titel())
+ .isEqualTo("Anwendung bundesrechtlicher Vorschriften");
+ assertThat(neu.norm("§ 13").orElseThrow().titel())
+ .isEqualTo("Entbehrlichkeit von Vergabeverfahren im Unterschwellenbereich");
+ assertThat(neu.norm("§ 14").orElseThrow().titel()).isEqualTo("Verordnungsermächtigungen");
var synopse = SynopseBuilder.baue(gesetz, anwendung, parseErgebnis.warnungen(), false);
assertThat(HtmlRenderer.rendere(synopse, "E2E-Test NEFG")).contains("§ 1");
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 d89c898..5213030 100644
--- a/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java
+++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/BefehlErkennerTest.java
@@ -126,6 +126,27 @@
}
@Test
+ void erkenntGliederungsbezogeneParagraphEinfuegung() {
+ // Echter Befehl aus Art. 1 Nr. 5 des Änderungsgesetzes zum NEFG (Nds. GVBl. 2026 Nr. 10). Die
+ // Kapitelangabe nennt nur den Abschnitt, in dem der neue Paragraph landet; maßgeblich für die
+ // Position ist der Anker „nach § 12“.
+ var befehl =
+ erkenne(
+ "In Kapitel 4 wird nach § 12 der folgende neue § 13 angefügt: „§ 13 Entbehrlichkeit"
+ + " von Vergabeverfahren im Unterschwellenbereich Das Gesetz ist nicht"
+ + " anzuwenden.“",
+ Stelle.LEER);
+
+ assertThat(befehl).containsInstanceOf(StrukturEinfuegung.class);
+ var einfuegung = (StrukturEinfuegung) befehl.orElseThrow();
+ assertThat(einfuegung.stelle().anzeigeText()).isEqualTo("§ 12");
+ assertThat(einfuegung.vorher()).isFalse();
+ assertThat(einfuegung.ebene()).isEqualTo(Ebene.PARAGRAPH);
+ assertThat(einfuegung.bezeichnung()).isEqualTo("13");
+ assertThat(einfuegung.text()).startsWith("§ 13 Entbehrlichkeit");
+ }
+
+ @Test
void erkenntSatzEinfuegung() {
var befehl =
erkenne(
diff --git a/src/test/java/eu/mulk/aendggner/aenderung/parse/TextBereinigerTest.java b/src/test/java/eu/mulk/aendggner/aenderung/parse/TextBereinigerTest.java
index f49e41b..4da5c79 100644
--- a/src/test/java/eu/mulk/aendggner/aenderung/parse/TextBereinigerTest.java
+++ b/src/test/java/eu/mulk/aendggner/aenderung/parse/TextBereinigerTest.java
@@ -224,6 +224,18 @@
}
@Test
+ void ziehtSachnummernMitLeerzeichenZusammen() {
+ // Niedersachsen zitiert eingeschobene Paragraphen als „§ 2 a“; kanonisch ist „§ 2a“.
+ assertThat(TextBereiniger.bereinige("Nach § 2 wird der folgende § 2 a eingefügt:"))
+ .isEqualTo("Nach § 2 wird der folgende § 2a eingefügt:");
+ assertThat(TextBereiniger.bereinige("Art. 28 a Abs. 1")).isEqualTo("Art. 28a Abs. 1");
+ // Aufzählungsmarker des Änderungsgesetzes bleiben unberührt, ebenso echte Folgewörter.
+ assertThat(TextBereiniger.bereinige("Nach § 8 c) In Absatz 2"))
+ .isEqualTo("Nach § 8 c) In Absatz 2");
+ assertThat(TextBereiniger.bereinige("§ 5 des Gesetzes")).isEqualTo("§ 5 des Gesetzes");
+ }
+
+ @Test
void entferntSeitenkopfDesGvoblSchleswigHolstein() {
var roh =
"""
diff --git a/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java b/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java
index a23f444..a8f3daa 100644
--- a/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java
+++ b/src/test/java/eu/mulk/aendggner/anwendung/BefehlAnwenderTest.java
@@ -1134,4 +1134,37 @@
assertThat(absatzText(ergebnis.neu(), "Art. 2", 0))
.isEqualTo("Erprobung ist die Prüfung der Tauglichkeit; sie schließt mit einem Bericht.");
}
+
+ @Test
+ void ziehtUmnummerierungVorDieNeubesetzendeEinfuegung() {
+ // „Nach § 2 wird der folgende neue § 3 eingefügt“ + „Der bisherige § 3 wird § 4“: In der
+ // Textreihenfolge angewandt kollidierten beide Befehle auf „§ 3“. Die Umnummerierung
+ // beschreibt den Stand vor der Änderung und geht der Neubesetzung sachlich voraus.
+ var einfuegung =
+ new StrukturEinfuegung(
+ stelle(new Stelle.Paragraph("2")),
+ false,
+ Ebene.PARAGRAPH,
+ "3",
+ "§ 3 Zwischennorm (1) Der neue Text.",
+ PROV);
+ var umnummerierung =
+ new Umnummerierung(
+ stelle(new Stelle.Paragraph("3")),
+ stelle(new Stelle.Paragraph("4")),
+ new Provenienz("1", "2.", "(Test)"));
+
+ var ergebnis = BefehlAnwender.anwenden(gesetz(), List.of(einfuegung, umnummerierung));
+
+ assertThat(ergebnis.anzahlAngewandt()).isEqualTo(2);
+ // Protokolliert wird weiterhin in der Reihenfolge des Änderungsgesetzes.
+ assertThat(ergebnis.protokoll())
+ .extracting(a -> a.befehl().provenienz().gliederungsPfad())
+ .containsExactly("1.", "2.");
+ assertThat(ergebnis.neu().normen())
+ .extracting(n -> n.enbez())
+ .containsExactly("§ 1", "§ 2", "§ 3", "§ 4");
+ assertThat(ergebnis.neu().norm("§ 3").orElseThrow().titel()).isEqualTo("Zwischennorm");
+ assertThat(ergebnis.neu().norm("§ 4").orElseThrow().titel()).isEqualTo("Schlussvorschriften");
+ }
}