
package de.ivu.elect.dokumente.stimmeingabe;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nullable;

import de.ivu.document.generator.template.annotations.Document;
import de.ivu.document.generator.template.annotations.DocumentComplexField;
import de.ivu.document.generator.template.annotations.DocumentMethod;
import de.ivu.document.generator.template.annotations.DocumentParam;
import de.ivu.document.generator.template.annotations.DocumentRepeat;
import de.ivu.document.generator.template.annotations.DocumentSimpleField;
import de.ivu.elect.business.dokumente.entity.DokumentVorlageArt;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietPK;
import de.ivu.elect.dokumente.ElectDocument;
import de.ivu.elect.dokumente.ergebnis.ErgebnisDocumentMitWahlverwaltungGebietInformation;
import de.ivu.elect.dokumente.gebiet.BasicGebietDokument;
import de.ivu.elect.dokumente.gebiet.GebietDokument;
import de.ivu.elect.dokumente.wahl.UmgangWaehlerDocument;
import de.ivu.elect.dokumente.wahl.UmgangWahlberechtigteDocument;

/**
 * Grundlage für die Erzeugung der Niederschriften für die Wahlbezirke (d.h. V1/V3), auf denen die Auszählungsergebnisse erfasst werden.
 */
@Document(DokumentVorlageArt.STIMMEINGABE_DOKUMENT_PREFIX)
public class StimmeingabeDocument extends ElectDocument implements ErgebnisDocumentMitWahlverwaltungGebietInformation<GebietDokument> {

  private static final long serialVersionUID = 1L;

  @DocumentSimpleField("Ergebniseingang-Art-Vorlaeufig")
  public boolean ergebniseingangArtVorlaeufig;

  @DocumentSimpleField("Ergebniseingang-Art-Endgueltig")
  public boolean ergebniseingangArtEndgueltig;

  /**
   * @see StimmeingabeDocument#ergebniseingangArtEndgueltig
   * @deprecated
   */
  @Deprecated
  @DocumentSimpleField("Erfassungsart-IstEndgueltig")
  public boolean ergebniseingangsartEndgueltig;

  @DocumentSimpleField("Ergebniseingang-Art-Nur-Trendmeldung")
  public boolean ergebniseingangArtNurTrendmeldung; // ELECT-14019

  @DocumentSimpleField("Ergebniseingang-Erfasser")
  public String ergebniseingangErfasser;

  @DocumentSimpleField("Ergebniseingang-Zeitstempel")
  public String ergebniseingangZeitstempel;

  /**
   * Gebiet, für das das Dokument erstellt wurde, also bspw. das Wahlgebiet ODER das Stimmzettelgebiet ODER ein Erfassungsgebiet...
   */
  @DocumentComplexField("Document-Gebiet")
  public GebietDokument documentGebiet;

  @DocumentSimpleField("Document-Per-Wahlgebiet")
  public boolean documentPerWahlgebiet;

  @DocumentComplexField("Wahlgebiet")
  public GebietDokument wahlgebiet;

  @DocumentSimpleField("Document-Per-Stimmzettelgebiet")
  public boolean documentPerStimmzettelgebiet;

  @DocumentComplexField("Wahlkreis")
  public GebietDokument wahlkreis;

  @DocumentSimpleField("Document-Per-Stimmkreis")
  public boolean documentPerStimmkreis;

  @DocumentComplexField("Stimmkreis")
  public GebietDokument stimmkreis;

  @DocumentSimpleField("Document-Per-Wahlbereich")
  public boolean documentPerWahlbereich;

  @DocumentComplexField("Wahlbereich")
  public GebietDokument wahlbereich;

  @DocumentSimpleField("Document-Per-Stimmbezirk")
  public boolean documentPerWahlbezirk;

  @DocumentComplexField("Stimmbezirk")
  public GebietDokument wahlbezirk;

  @DocumentSimpleField("Stimmbezirk-Art")
  public String wahlbezirkArtKennzeichen;

  @DocumentComplexField("Bundesland")
  public GebietDokument bundesland;

  @DocumentComplexField("Landkreis")
  public GebietDokument landkreis;

  @DocumentComplexField("Gemeindeverwaltung")
  public GebietDokument gemeindeverwaltung;

  @DocumentComplexField("Gemeindeverband")
  public GebietDokument gemeindeverband;

  @DocumentComplexField("Gemeinde")
  public GebietDokument gemeinde;

  @DocumentComplexField("Ortsbezirk")
  public GebietDokument ortsbezirk; // ELECT-13692

  @DocumentComplexField("Stadtbezirk")
  public GebietDokument stadtbezirk;

  @DocumentSimpleField("Eingaben-Anzahlen-Wahlberechtigte-Excluded")
  public final boolean eingabenAnzahlenWahlberechtigteExcluded;

  @DocumentComplexField("Wahlart-Umgang-Wahlberechtigte") // ELECT-13015
  public UmgangWahlberechtigteDocument wahlartUmgangWahlberechtigte;

  @DocumentSimpleField("Anzahl-Wahlberechtigte-Ohne-Wahlschein")
  public Long wahlberechtigteOhneWahlschein;

  @DocumentSimpleField("Anzahl-Wahlberechtigte-Mit-Wahlschein")
  public Long wahlberechtigteMitWahlschein;

  @DocumentSimpleField("Anzahl-Wahlberechtigte-Nicht-Im-Waehlerverzeichnis")
  public Long wahlberechtigteNichtImWaehlerverzeichnis;

  @DocumentSimpleField("Anzahl-Wahlberechtigte-Gesamt-Exklusive-Nicht-Im-Waehlerverzeichnis")
  public Long wahlberechtigteGesamtExklusiveNichtImWaehlerverzeichnis; // ELECT-16945

  @DocumentSimpleField("Anzahl-Wahlberechtigte-Gesamt")
  public Long wahlberechtigteGesamt;

  /**
   * @see StimmeingabeDocument#wahlberechtigteOhneWahlschein
   * @deprecated ELECT-8018
   */
  @Deprecated
  @DocumentSimpleField("A1")
  public Long a1;

  /**
   * @see StimmeingabeDocument#wahlberechtigteMitWahlschein
   * @deprecated ELECT-8018
   */
  @Deprecated
  @DocumentSimpleField("A2")
  public Long a2;

  /**
   * @see StimmeingabeDocument#wahlberechtigteNichtImWaehlerverzeichnis
   * @deprecated ELECT-8018
   */
  @Deprecated
  @DocumentSimpleField("A3")
  public Long a3;

  /**
   * @see StimmeingabeDocument#wahlberechtigteGesamt
   * @deprecated ELECT-8018
   */
  @Deprecated
  @DocumentSimpleField("A")
  public Long a;

  @DocumentSimpleField("Eingaben-Anzahlen-Waehler-Excluded")
  public final boolean eingabenAnzahlenWaehlerExcluded;

  @DocumentComplexField("Wahlart-Umgang-Waehler") // ELECT-13015
  public UmgangWaehlerDocument wahlartUmgangWaehler;

  @DocumentSimpleField("Anzahl-Waehler-Ohne-Wahlschein")
  public Long waehlerOhneWahlschein;

  @DocumentSimpleField("Anzahl-Waehler-Mit-Wahlschein")
  public Long waehlerMitWahlschein;

  @DocumentSimpleField("Anzahl-Waehler-Mit-Wahlschein-Anteil-Aus-Urnenwahl")
  public Long waehlerMitWahlscheinAnteilAusUrnenwahl;

  @DocumentSimpleField("Anzahl-Waehler-Mit-Wahlschein-Anteil-Aus-Briefwahl")
  public Long waehlerMitWahlscheinAnteilAusBriefwahl;

  @DocumentSimpleField("Anzahl-Waehler-Mit-Vollmacht")
  public Long waehlerMitVollmacht;

  @DocumentSimpleField("Anzahl-Waehler-Gesamt")
  public Long waehlerGesamt;

  /**
   * @see StimmeingabeDocument#waehlerMitWahlschein
   * @deprecated ELECT-8018
   */
  @Deprecated
  @DocumentSimpleField("B1")
  public Long b1;

  /**
   * @see StimmeingabeDocument#waehlerOhneWahlschein
   * @deprecated ELECT-8018
   */
  @Deprecated
  @DocumentSimpleField("B2")
  public Long b2;

  /**
   * @see StimmeingabeDocument#waehlerGesamt
   * @deprecated ELECT-8018
   */
  @Deprecated
  @DocumentSimpleField("B")
  public Long b;

  @DocumentSimpleField("Anzahl-Wahlbriefe-Zurueckgewiesen-Gesamt")
  public Long wahlbriefeZurueckgewiesenGesamt; // ELECTKOM-2783

  @DocumentSimpleField("Eingaben-Anzahlen-Stimmen-Excluded")
  public final boolean eingabenAnzahlenStimmenExcluded;

  @DocumentSimpleField("Erststimmen-Gueltig")
  public Long erststimmenGueltig;

  @DocumentSimpleField("Erststimmen-Ungueltig")
  public Long erststimmenUngueltig;

  @DocumentSimpleField("Erststimmen-Gesamt")
  public Long erststimmenGesamt;

  @DocumentSimpleField("Zweitstimmen-Gueltig")
  public Long zweitstimmenGueltig;

  @DocumentSimpleField("Zweitstimmen-Ungueltig")
  public Long zweitstimmenUngueltig;

  @DocumentSimpleField("Zweitstimmen-Gesamt")
  public Long zweitstimmenGesamt;

  @DocumentSimpleField("NurErgebnisAusgeben")
  public boolean nurErgebnisAusgeben; // ELECT-9009

  @DocumentSimpleField("Section-Zaehlliste-Elektronisch-Excluded")
  public final boolean sectionZaehllisteElektronischExcluded; // ELECT-9443

  @DocumentSimpleField("Section-Erfasste-Stimmzettel-Excluded")
  public final boolean sectionErfassteStimmzettelExcluded; // ELECT-9443

  /**
   * @see StimmeingabeDocument#sectionErfassteStimmzettelExcluded
   * @deprecated ELECT-9443
   */
  @Deprecated
  @DocumentSimpleField("StimmzettelMitBeschlussAusgeben")
  public final boolean stimmzettelMitBeschlussAusgeben; // ELECTKOM-744

  @DocumentSimpleField("VersionsnummerStimmzettelerfassung")
  public Long versionsnummerStimmzettelerfassung; // ELECT-9105

  @DocumentRepeat(value = "ErfassteStimmzettel", elementClass = ErfassterStimmzettelDocument.class, itemName = "erfassterStimmzettel")
  public List<ErfassterStimmzettelDocument> erfassteStimmzettel = new ArrayList<>();

  @DocumentSimpleField("Stimmzettel-Gueltig")
  public Long stimmzettelGueltig;

  @DocumentSimpleField("Stimmzettel-Ungueltig")
  public Long stimmzettelUngueltig;

  @DocumentSimpleField("Stimmzettel-Mit-Bedenken")
  public Long stimmzettelUnbestimmt; // ELECT-13792

  /**
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagUnveraendert
   * @see ListeStimmenDocument#stimmzettelWahlvorschlagUnveraendert
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Unveraendert")
  public Long stimmzettelWahlvorschlagUnveraendert; // ELECT-13791

  /**
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagVeraendert
   * @see ListeStimmenDocument#stimmzettelWahlvorschlagVeraendert
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Veraendert")
  public Long stimmzettelWahlvorschlagVeraendert; // ELECT-13791

  /**
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagPanaschiert
   * @see ListeStimmenDocument#stimmzettelWahlvorschlagPanaschiert
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Panaschiert")
  public Long stimmzettelWahlvorschlagPanaschiert; // ELECT-13791

  @DocumentSimpleField("Stimmzettel-Manuell-Erfasst-Ohne-Beschluss")
  public Long stimmzettelManuellErfasstOhneBeschluss;

  @DocumentSimpleField("Stimmzettel-Manuell-Erfasst-Gueltig-Mit-Beschluss")
  public Long stimmzettelManuellErfasstGueltigMitBeschluss;

  @DocumentSimpleField("Stimmzettel-Manuell-Erfasst-Ungueltig-Mit-Beschluss")
  public Long stimmzettelManuellErfasstUngueltigMitBeschluss;

  @DocumentSimpleField("Stimmzettel-Ohne-Erfassung-Offensichtlich-Ungueltig")
  public Long stimmzettelOhneErfassungOffensichtlichUngueltig;

  /**
   * @see GruppeStimmenDocument#stimmzettelWahlvorschlagGesamt
   * @see ListeStimmenDocument#stimmzettelWahlvorschlagGesamt
   */
  @DocumentSimpleField("Stimmzettel-Nur-Einzelner-Wahlvorschlag-Gesamt")
  public Long stimmzettelWahlvorschlagGesamt; // ELECT-13791

  @DocumentSimpleField("Stimmzettel-Kein-Einzelner-Wahlvorschlag-Veraendert")
  public Long stimmzettelKeinWahlvorschlagVeraendert; // ELECT-13792

  @DocumentSimpleField("Stimmzettel-Kein-Einzelner-Wahlvorschlag-Panaschiert")
  public Long stimmzettelKeinWahlvorschlagPanaschiert; // ELECT-13792

  @DocumentSimpleField("Stimmzettel-Kein-Einzelner-Wahlvorschlag-Gesamt")
  public Long stimmzettelKeinWahlvorschlagGesamt; // ELECT-13792

  @DocumentSimpleField("Stimmzettel-Gesamt")
  public Long stimmzettelGesamt;

  @DocumentRepeat(value = "Parteien", elementClass = GruppeStimmenDocument.class, itemName = "politischeGruppe")
  public List<GruppeStimmenDocument> politischeGruppen = new ArrayList<>();

  @DocumentRepeat(value = "Direktkandidaten", elementClass = KandidatStimmenDocument.class, itemName = "kandidat")
  public List<KandidatStimmenDocument> direktkandidaten = new ArrayList<>();

  @DocumentRepeat(value = "Listen", elementClass = ListeStimmenDocument.class, itemName = "liste")
  public List<ListeStimmenDocument> listen = new ArrayList<>();

  @DocumentRepeat(value = "ReferendumVorlagen", elementClass = ReferendumVorlageStimmenDocument.class, itemName = "referendumVorlage")
  public List<ReferendumVorlageStimmenDocument> referendumVorlagen = new ArrayList<>();

  @DocumentRepeat(value = "Wahlhelfereinsaetze", elementClass = WasWahlhelfereinsatzDocument.class, itemName = "wahlhelfereinsatz")
  public List<WasWahlhelfereinsatzDocument> wasWahlhelfereinsaetze = new ArrayList<>();

  @DocumentRepeat(value = "StimmzettelWaehlerBenannteKandidaturen", elementClass = StimmzettelWaehlerBenannteKandidatur.class, itemName = "stimmzettelWaehlerBenannteKandidatur")
  public List<StimmzettelWaehlerBenannteKandidatur> stimmzettelWaehlerBenannteKandidaturen = new ArrayList<>();

  @DocumentSimpleField("Stimmzettel-Anzahl-Stimmen-Listenstimmen")
  public Long anzahlStimmenStimmzettelListenstimmen;

  @DocumentSimpleField("Stimmzettel-Anzahl-Stimmen-Waehlerbenannte-Kandidatur")
  public Long anzahlStimmenStimmzettelWaehlerBenannteKandidatur;

  @DocumentSimpleField("Stimmzettel-Anzahl-Mit-Waehlerbenannte-Kandidatur")
  public Long anzahlStimmzettelMitWaehlerBenannteKandidaturen;

  @Deprecated
  @DocumentSimpleField("stimmzettelPruefungDokument")
  public Object stimmzettelPruefungDokument; // vergleiche de.ivu.elect.dokumente.WesStimmzettelPruefungDokument.stimmzettelPruefungDokument

  private final StimmeingabeDocumentContext context;

  public StimmeingabeDocument(StimmeingabeDocumentContext context) {
    super(context);

    this.context = context;

    this.sectionZaehllisteElektronischExcluded = context.isSectionZaehllisteElektronischExcluded();
    this.sectionErfassteStimmzettelExcluded = context.isSectionErfassteStimmzettelExcluded();
    this.stimmzettelMitBeschlussAusgeben = !this.sectionErfassteStimmzettelExcluded;

    this.eingabenAnzahlenWahlberechtigteExcluded = !context.isEingabenAnzahlenWahlberechtigteIncluded();
    this.eingabenAnzahlenWaehlerExcluded = !context.isEingabenAnzahlenWaehlerIncluded();
    this.eingabenAnzahlenStimmenExcluded = !context.isEingabenAnzahlenStimmenIncluded();
  }

  @DocumentMethod // ELECT-14076
  public boolean isSitzverteilungPerMehrheitswahl() {
    return isSitzverteilungPerMehrheitswahl(documentGebiet);
  }

  @DocumentMethod // ELECT-14076
  public boolean isSitzverteilungPerMehrheitswahl(@DocumentParam("gebiet") Object gebietReference) {
    Long gebietId = null;

    if (gebietReference instanceof Gebiet) {
      gebietId = ((Gebiet) gebietReference).getId();
    } else if (gebietReference instanceof GebietPK) {
      gebietId = ((GebietPK) gebietReference).getId();
    } else if (gebietReference instanceof BasicGebietDokument) {
      gebietId = ((BasicGebietDokument) gebietReference).id;
    }

    return gebietId != null && context.isSitzverteilungPerMehrheitswahl(new GebietPK(gebietId));
  }

  public void addToDocumentKumuliert(StimmeingabeDocumentContext context, CoreStimmeingabeDocumentBuilder stimmeingabeDocumentBuilder, StimmeingabeDocument stimmeingabeDocument) {
    stimmeingabeDocument.ergebniseingangArtVorlaeufig = ergebniseingangArtVorlaeufig;
    stimmeingabeDocument.ergebniseingangArtEndgueltig = ergebniseingangArtEndgueltig;
    stimmeingabeDocument.ergebniseingangsartEndgueltig = ergebniseingangArtEndgueltig;
    stimmeingabeDocument.ergebniseingangArtNurTrendmeldung = ergebniseingangArtNurTrendmeldung;

    stimmeingabeDocument.wahlartUmgangWahlberechtigte = wahlartUmgangWahlberechtigte;

    stimmeingabeDocument.wahlberechtigteOhneWahlschein = aggregate(stimmeingabeDocument.wahlberechtigteOhneWahlschein, wahlberechtigteOhneWahlschein);
    stimmeingabeDocument.wahlberechtigteMitWahlschein = aggregate(stimmeingabeDocument.wahlberechtigteMitWahlschein, wahlberechtigteMitWahlschein);
    stimmeingabeDocument.wahlberechtigteNichtImWaehlerverzeichnis = aggregate(stimmeingabeDocument.wahlberechtigteNichtImWaehlerverzeichnis, wahlberechtigteNichtImWaehlerverzeichnis);
    stimmeingabeDocument.wahlberechtigteGesamtExklusiveNichtImWaehlerverzeichnis = aggregate(stimmeingabeDocument.wahlberechtigteGesamtExklusiveNichtImWaehlerverzeichnis, wahlberechtigteGesamtExklusiveNichtImWaehlerverzeichnis);
    stimmeingabeDocument.wahlberechtigteGesamt = aggregate(stimmeingabeDocument.wahlberechtigteGesamt, wahlberechtigteGesamt);

    // ELECT-8018, LEGACY!!!
    stimmeingabeDocument.a1 = stimmeingabeDocument.wahlberechtigteOhneWahlschein;
    stimmeingabeDocument.a2 = stimmeingabeDocument.wahlberechtigteMitWahlschein;
    stimmeingabeDocument.a3 = stimmeingabeDocument.wahlberechtigteNichtImWaehlerverzeichnis;
    stimmeingabeDocument.a = stimmeingabeDocument.wahlberechtigteGesamt;

    stimmeingabeDocument.wahlartUmgangWaehler = wahlartUmgangWaehler;

    stimmeingabeDocument.waehlerOhneWahlschein = aggregate(stimmeingabeDocument.waehlerOhneWahlschein, waehlerOhneWahlschein);
    stimmeingabeDocument.waehlerMitWahlschein = aggregate(stimmeingabeDocument.waehlerMitWahlschein, waehlerMitWahlschein);
    stimmeingabeDocument.waehlerMitWahlscheinAnteilAusUrnenwahl = aggregate(stimmeingabeDocument.waehlerMitWahlscheinAnteilAusUrnenwahl, waehlerMitWahlscheinAnteilAusUrnenwahl);
    stimmeingabeDocument.waehlerMitWahlscheinAnteilAusBriefwahl = aggregate(stimmeingabeDocument.waehlerMitWahlscheinAnteilAusBriefwahl, waehlerMitWahlscheinAnteilAusBriefwahl);
    stimmeingabeDocument.waehlerMitVollmacht = aggregate(stimmeingabeDocument.waehlerMitVollmacht, waehlerMitVollmacht);
    stimmeingabeDocument.waehlerGesamt = aggregate(stimmeingabeDocument.waehlerGesamt, waehlerGesamt);

    // ELECT-8018, LEGACY!!!
    stimmeingabeDocument.b1 = stimmeingabeDocument.waehlerMitWahlschein;
    stimmeingabeDocument.b2 = stimmeingabeDocument.waehlerOhneWahlschein;
    stimmeingabeDocument.b = stimmeingabeDocument.waehlerGesamt;

    stimmeingabeDocument.wahlbriefeZurueckgewiesenGesamt = aggregate(stimmeingabeDocument.wahlbriefeZurueckgewiesenGesamt, wahlbriefeZurueckgewiesenGesamt);

    stimmeingabeDocument.erststimmenGueltig = aggregate(stimmeingabeDocument.erststimmenGueltig, erststimmenGueltig);
    stimmeingabeDocument.erststimmenUngueltig = aggregate(stimmeingabeDocument.erststimmenUngueltig, erststimmenUngueltig);
    stimmeingabeDocument.erststimmenGesamt = aggregate(stimmeingabeDocument.erststimmenGesamt, erststimmenGesamt);

    stimmeingabeDocument.zweitstimmenGueltig = aggregate(stimmeingabeDocument.zweitstimmenGueltig, zweitstimmenGueltig);
    stimmeingabeDocument.zweitstimmenUngueltig = aggregate(stimmeingabeDocument.zweitstimmenUngueltig, zweitstimmenUngueltig);
    stimmeingabeDocument.zweitstimmenGesamt = aggregate(stimmeingabeDocument.zweitstimmenGesamt, zweitstimmenGesamt);

    stimmeingabeDocument.stimmzettelGueltig = aggregate(stimmeingabeDocument.stimmzettelGueltig, stimmzettelGueltig);
    stimmeingabeDocument.stimmzettelUngueltig = aggregate(stimmeingabeDocument.stimmzettelUngueltig, stimmzettelUngueltig);
    stimmeingabeDocument.stimmzettelUnbestimmt = aggregate(stimmeingabeDocument.stimmzettelUnbestimmt, stimmzettelUnbestimmt);
    stimmeingabeDocument.stimmzettelGesamt = aggregate(stimmeingabeDocument.stimmzettelGesamt, stimmzettelGesamt);

    stimmeingabeDocument.stimmzettelWahlvorschlagUnveraendert = aggregate(stimmeingabeDocument.stimmzettelWahlvorschlagUnveraendert, stimmzettelWahlvorschlagUnveraendert);
    stimmeingabeDocument.stimmzettelWahlvorschlagVeraendert = aggregate(stimmeingabeDocument.stimmzettelWahlvorschlagVeraendert, stimmzettelWahlvorschlagVeraendert);
    stimmeingabeDocument.stimmzettelWahlvorschlagPanaschiert = aggregate(stimmeingabeDocument.stimmzettelWahlvorschlagPanaschiert, stimmzettelWahlvorschlagPanaschiert);
    stimmeingabeDocument.stimmzettelWahlvorschlagGesamt = aggregate(stimmeingabeDocument.stimmzettelWahlvorschlagGesamt, stimmzettelWahlvorschlagGesamt);

    stimmeingabeDocument.stimmzettelKeinWahlvorschlagVeraendert = aggregate(stimmeingabeDocument.stimmzettelKeinWahlvorschlagVeraendert, stimmzettelKeinWahlvorschlagVeraendert);
    stimmeingabeDocument.stimmzettelKeinWahlvorschlagPanaschiert = aggregate(stimmeingabeDocument.stimmzettelKeinWahlvorschlagPanaschiert, stimmzettelKeinWahlvorschlagPanaschiert);
    stimmeingabeDocument.stimmzettelKeinWahlvorschlagGesamt = aggregate(stimmeingabeDocument.stimmzettelKeinWahlvorschlagGesamt, stimmzettelKeinWahlvorschlagGesamt);

    stimmeingabeDocument.politischeGruppen = GruppeStimmenDocument.aggregate(context, stimmeingabeDocumentBuilder, stimmeingabeDocument.politischeGruppen, politischeGruppen);
    stimmeingabeDocument.direktkandidaten = KandidatStimmenDocument.aggregate(context, stimmeingabeDocumentBuilder, stimmeingabeDocument.direktkandidaten, direktkandidaten);
    stimmeingabeDocument.listen = ListeStimmenDocument.aggregate(context, stimmeingabeDocumentBuilder, stimmeingabeDocument.listen, listen);
    stimmeingabeDocument.referendumVorlagen = ReferendumVorlageStimmenDocument.aggregate(context, stimmeingabeDocumentBuilder, stimmeingabeDocument.referendumVorlagen, referendumVorlagen);
  }

  @Override
  public GebietDokument getWahlkreis() {
    return wahlkreis;
  }

  @Override
  public GebietDokument getStimmkreis() {
    return stimmkreis;
  }

  @Override
  public GebietDokument getWahlbereich() {
    return wahlbereich;
  }

  @Override
  public GebietDokument getBundesland() {
    return bundesland;
  }

  @Override
  public GebietDokument getLandkreis() {
    return landkreis;
  }

  @Override
  public GebietDokument getGemeindeverwaltung() {
    return gemeindeverwaltung;
  }

  @Override
  public GebietDokument getGemeindeverband() {
    return gemeindeverband;
  }

  @Override
  public GebietDokument getGemeinde() {
    return gemeinde;
  }

  @Override
  public GebietDokument getOrtsbezirk() {
    return ortsbezirk;
  }

  @Override
  public GebietDokument getStadtbezirk() {
    return stadtbezirk;
  }

  protected Long aggregate(@Nullable Long target, Long source) {
    return AbstractStimmenDocument.aggregate(target, source);
  }
}
