blob: 2bc6359b274dcb0b8b6932a37b99c22a04978817 [file] [log] [blame]
// SPDX-FileCopyrightText: 2026 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
// SPDX-License-Identifier: AGPL-3.0-or-later
package eu.mulk.aendggner.synopse;
import eu.mulk.aendggner.aenderung.Inkrafttreten;
import eu.mulk.aendggner.anwendung.BefehlAnwender.AnwendungsErgebnis;
import eu.mulk.aendggner.anwendung.BefehlAnwender.Status;
import eu.mulk.aendggner.gesetz.Gesetz;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
/** Paart die Normen alter und neuer Fassung zu Synopse-Einträgen. */
public final class SynopseBuilder {
private SynopseBuilder() {}
/**
* @param alt das Stammgesetz vor Anwendung der Befehle.
* @param anwendung das Ergebnis des {@link eu.mulk.aendggner.anwendung.BefehlAnwender}.
* @param parseWarnungen Warnungen aus dem Parsen des Änderungsgesetzes.
* @param vollstaendig auch unveränderte Normen aufnehmen.
*/
public static Synopse baue(
Gesetz alt, AnwendungsErgebnis anwendung, List<String> parseWarnungen, boolean vollstaendig) {
return baue(alt, anwendung, parseWarnungen, vollstaendig, null, null);
}
/**
* @param inkrafttreten was der Schlussartikel des Änderungsgesetzes anordnet, sofern gelesen.
* @param stichtag der Tag, dessen Fassung gezeigt wird; {@code null} = ohne Rücksicht darauf.
*/
public static Synopse baue(
Gesetz alt,
AnwendungsErgebnis anwendung,
List<String> parseWarnungen,
boolean vollstaendig,
@Nullable Inkrafttreten inkrafttreten,
@Nullable LocalDate stichtag) {
var neu = anwendung.neu();
var eintraege = new ArrayList<Synopse.Eintrag>();
for (var neuNorm : neu.normen()) {
var altNorm = alt.norm(neuNorm.enbez()).orElse(null);
Synopse.Aenderungsart art;
if (altNorm == null) {
art = Synopse.Aenderungsart.NEU;
} else if (neuNorm.weggefallen() && !altNorm.weggefallen()) {
art = Synopse.Aenderungsart.AUFGEHOBEN;
} else if (!gleicherInhalt(altNorm, neuNorm)) {
art = Synopse.Aenderungsart.GEAENDERT;
} else {
art = Synopse.Aenderungsart.UNVERAENDERT;
}
if (art == Synopse.Aenderungsart.UNVERAENDERT && !vollstaendig) {
continue;
}
var ursachen =
anwendung.protokoll().stream()
.filter(a -> a.betroffeneEnbez().contains(neuNorm.enbez()))
.toList();
eintraege.add(new Synopse.Eintrag(altNorm, neuNorm, art, ursachen));
}
var manuell =
anwendung.protokoll().stream().filter(a -> a.status() == Status.MANUELL_PRUEFEN).toList();
var nichtInKraft =
anwendung.protokoll().stream().filter(a -> a.status() == Status.NICHT_IN_KRAFT).toList();
return new Synopse(
alt,
neu,
eintraege,
gliederungsAenderungen(alt, neu),
manuell,
parseWarnungen,
inkrafttreten,
stichtag,
nichtInKraft,
null);
}
/**
* Paart die Gliederungseinheiten nach Kennzahl und sammelt die mit geänderter Überschrift. Neu
* eingefügte Einheiten (ohne Kennzahl und ohne Alt-Pendant) erscheinen mit {@code alt == null}.
*/
private static List<Synopse.GliederungsAenderung> gliederungsAenderungen(Gesetz alt, Gesetz neu) {
var aenderungen = new ArrayList<Synopse.GliederungsAenderung>();
for (var neuG : neu.gliederungen()) {
if (neuG.kennzahl() == null) {
if (!alt.gliederungen().contains(neuG)) {
aenderungen.add(new Synopse.GliederungsAenderung(null, neuG));
}
continue;
}
alt.gliederungen().stream()
.filter(a -> java.util.Objects.equals(a.kennzahl(), neuG.kennzahl()))
.findFirst()
.filter(a -> !java.util.Objects.equals(a.titel(), neuG.titel()))
.ifPresent(a -> aenderungen.add(new Synopse.GliederungsAenderung(a, neuG)));
}
return aenderungen;
}
private static boolean gleicherInhalt(
eu.mulk.aendggner.gesetz.Norm a, eu.mulk.aendggner.gesetz.Norm b) {
return a.gesamtText().equals(b.gesamtText()) && java.util.Objects.equals(a.titel(), b.titel());
}
}