All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.svws_nrw.data.stundenplan.DataStundenplanKurse Maven / Gradle / Ivy

Go to download

Diese Bibliothek unterstützt bei dem Zugriff auf Datenbanken für die Schulverwaltungssoftware in NRW

There is a newer version: 1.0.3
Show newest version
package de.svws_nrw.data.stundenplan;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import de.svws_nrw.core.data.stundenplan.StundenplanKurs;
import de.svws_nrw.data.DataManager;
import de.svws_nrw.db.DBEntityManager;
import de.svws_nrw.db.dto.current.schild.faecher.DTOFach;
import de.svws_nrw.db.dto.current.schild.kurse.DTOKurs;
import de.svws_nrw.db.dto.current.schild.kurse.DTOKursLehrer;
import de.svws_nrw.db.dto.current.schild.kurse.DTOKursSchueler;
import de.svws_nrw.db.dto.current.schild.stundenplan.DTOStundenplan;
import de.svws_nrw.db.dto.current.schild.stundenplan.DTOStundenplanSchienen;
import de.svws_nrw.db.utils.ApiOperationException;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;

/**
 * Diese Klasse erweitert den abstrakten {@link DataManager} für den
 * Core-DTO {@link StundenplanKurs}.
 */
public final class DataStundenplanKurse extends DataManager {

	private final Long stundenplanID;

	/**
	 * Erstellt einen neuen {@link DataManager} für den Core-DTO {@link StundenplanKurs}.
	 *
	 * @param conn            die Datenbank-Verbindung für den Datenbankzugriff
	 * @param stundenplanID   die ID des Stundenplans, dessen Kurse abgefragt werden
	 */
	public DataStundenplanKurse(final DBEntityManager conn, final Long stundenplanID) {
		super(conn);
		this.stundenplanID = stundenplanID;
	}


	/**
	 * Lambda-Ausdruck zum Umwandeln eines Datenbank-DTOs {@link DTOKurs} in einen Core-DTO {@link StundenplanKurs}.
	 */
	private static final BiFunction dtoMapper = (final DTOKurs k, final DTOFach f) -> {
		final StundenplanKurs daten = new StundenplanKurs();
		daten.id = k.ID;
		daten.idFach = k.Fach_ID;
		daten.bezeichnung = k.KurzBez;
		daten.wochenstunden = k.WochenStd;
		if (k.Sortierung != null)
			daten.sortierung = k.Sortierung;
		else if (f.SortierungAllg != null)
			daten.sortierung = f.SortierungAllg;
		else
			daten.sortierung = (f.SortierungSekII == null) ? 32000 : f.SortierungSekII;
		return daten;
	};


	@Override
	public Response getAll() throws ApiOperationException {
		return this.getList();
	}

	/**
	 * Gibt die Kurse des Stundenplans zurück.
	 *
	 * @param conn            die Datenbankverbindung
	 * @param idStundenplan   die ID des Stundenplans
	 *
	 * @return die Liste der Kurse
	 *
	 * @throws ApiOperationException im Fehlerfall
	 */
	public static List getKurse(final @NotNull DBEntityManager conn, final long idStundenplan) throws ApiOperationException {
		final DTOStundenplan stundenplan = conn.queryByKey(DTOStundenplan.class, idStundenplan);
		if (stundenplan == null)
			throw new ApiOperationException(Status.NOT_FOUND, "Es wurde kein Stundenplan mit der ID %d gefunden.".formatted(idStundenplan));
		final List kurse = conn.queryList(DTOKurs.QUERY_BY_SCHULJAHRESABSCHNITTS_ID, DTOKurs.class, stundenplan.Schuljahresabschnitts_ID);
		if (kurse.isEmpty())
			return new ArrayList<>();
		final List kursIDs = kurse.stream().map(k -> k.ID).toList();
		// Schüler bestimmen
		final Map> mapKursSchuelerIDs = conn.queryList(
				"SELECT e FROM DTOKursSchueler e WHERE e.Kurs_ID IN ?1 AND e.LernabschnittWechselNr = 0", DTOKursSchueler.class, kursIDs)
				.stream().collect(Collectors.groupingBy(ks -> ks.Kurs_ID, Collectors.mapping(ks -> ks.Schueler_ID, Collectors.toList())));
		// Lehrer bestimmen
		final Map> mapKursZusatzkraefte = conn.queryList(DTOKursLehrer.QUERY_LIST_BY_KURS_ID, DTOKursLehrer.class, kursIDs)
				.stream().collect(Collectors.groupingBy(ks -> ks.Kurs_ID, Collectors.mapping(ks -> ks.Lehrer_ID, Collectors.toList())));
		// Fächer bestimmen
		final List faecherIDs = kurse.stream().map(k -> k.Fach_ID).toList();
		final Map mapFaecher = conn.queryByKeyList(DTOFach.class, faecherIDs).stream().collect(Collectors.toMap(f -> f.ID, f -> f));
		// Map für Schienen-IDs bestimmen
		final Map> mapNummerJahrgangID = conn.queryList(DTOStundenplanSchienen.QUERY_BY_STUNDENPLAN_ID,
				DTOStundenplanSchienen.class, idStundenplan).stream()
				.collect(Collectors.groupingBy(s -> s.Nummer, Collectors.toMap(s -> s.Jahrgang_ID, s -> s.ID)));
		// Erstelle die Core-DTOs
		final ArrayList daten = new ArrayList<>();
		for (final DTOKurs k : kurse) {
			final DTOFach f = mapFaecher.get(k.Fach_ID);
			if (f == null)
				throw new ApiOperationException(Status.NOT_FOUND,
						"Es wurde kein Fach mit der ID %d für den Kurs mit der ID %d gefunden.".formatted(k.Fach_ID, k.ID));
			final StundenplanKurs kurs = dtoMapper.apply(k, f);
			if (k.Jahrgang_ID == null) {
				kurs.jahrgaenge.addAll(strLongToList(k.Jahrgaenge));
			} else {
				kurs.jahrgaenge.add(k.Jahrgang_ID);
			}
			if (k.Schienen != null) {
				for (final Long schienenNummer : strLongToList(k.Schienen)) {
					final Map mapJahrgangID = mapNummerJahrgangID.get(schienenNummer.intValue());
					if ((mapJahrgangID != null) && (!mapJahrgangID.isEmpty())) {
						for (final Long jgID : kurs.jahrgaenge) {
							final Long schienenID = mapJahrgangID.get(jgID);
							if (schienenID != null)
								kurs.schienen.add(schienenID);
						}
					}
				}
			}
			final List schuelerIDs = mapKursSchuelerIDs.get(k.ID);
			if (schuelerIDs != null)
				kurs.schueler.addAll(schuelerIDs);
			if (k.Lehrer_ID != null)
				kurs.lehrer.add(k.Lehrer_ID);
			final List zusatzkraefteIDs = mapKursZusatzkraefte.get(k.ID);
			if (zusatzkraefteIDs != null)
				kurs.lehrer.addAll(zusatzkraefteIDs);
			daten.add(kurs);
		}
		return daten;
	}


	@Override
	public Response getList() throws ApiOperationException {
		final List daten = getKurse(conn, this.stundenplanID);
		return Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(daten).build();
	}


	private static List strLongToList(final String str) {
		final List result = new ArrayList<>();
		if (str == null)
			return result;
		final String[] parts = str.split(",");
		for (final String part : parts) {
			try {
				result.add(Long.parseLong(part.trim()));
			} catch (@SuppressWarnings("unused") final NumberFormatException e) {
				// der Fehler wird hier ignoriert und keine ID übernommen
			}
		}
		return result;
	}


	@Override
	public Response get(final Long id) throws ApiOperationException {
		final DTOStundenplan stundenplan = conn.queryByKey(DTOStundenplan.class, stundenplanID);
		if (stundenplan == null)
			throw new ApiOperationException(Status.NOT_FOUND, "Es wurde kein Stundenplan mit der ID %d gefunden.".formatted(stundenplanID));
		if (id == null)
			throw new ApiOperationException(Status.BAD_REQUEST, "Eine Anfrage zu einem Kurs mit der ID null ist unzulässig.");
		final DTOKurs kurs = conn.queryByKey(DTOKurs.class, id);
		if (kurs == null)
			throw new ApiOperationException(Status.NOT_FOUND, "Es wurde kein Kurs mit der ID %d gefunden.".formatted(id));
		if (kurs.Schuljahresabschnitts_ID != stundenplan.Schuljahresabschnitts_ID)
			throw new ApiOperationException(Status.BAD_REQUEST,
					"Der Schuljahresabschnitt %d des Kurses mit der ID %d stimmt nicht mit dem Schuljahresabschitt %d bei dem Stundenplan mit der ID %d überein."
							.formatted(kurs.Schuljahresabschnitts_ID, kurs.ID, stundenplan.Schuljahresabschnitts_ID, stundenplan.ID));
		// Jahrgänge bestimmen
		final List jahrgangsIDs = new ArrayList<>();
		if (kurs.Jahrgang_ID == null) {
			jahrgangsIDs.addAll(strLongToList(kurs.Jahrgaenge));
		} else {
			jahrgangsIDs.add(kurs.Jahrgang_ID);
		}
		// Schienen-IDs bestimmen
		final Map> mapNummerJahrgangID = conn.queryList(DTOStundenplanSchienen.QUERY_BY_STUNDENPLAN_ID,
				DTOStundenplanSchienen.class, stundenplan.ID).stream()
				.collect(Collectors.groupingBy(s -> s.Nummer, Collectors.toMap(s -> s.Jahrgang_ID, s -> s.ID)));
		// Schüler bestimmen
		final List schuelerIDs = conn.queryList(
				"SELECT e FROM DTOKursSchueler e WHERE e.Kurs_ID = :value AND e.LernabschnittWechselNr IS NULL", DTOKursSchueler.class, kurs.ID)
				.stream().map(ks -> ks.Schueler_ID).toList();
		// Fachdefinition laden
		final DTOFach fach = conn.queryByKey(DTOFach.class, kurs.Fach_ID);
		if (fach == null)
			throw new ApiOperationException(Status.NOT_FOUND,
					"Es wurde kein Fach mit der ID %d für den Kurs mit der ID %d gefunden.".formatted(kurs.Fach_ID, kurs.ID));
		// DTO erstellen
		final StundenplanKurs daten = dtoMapper.apply(kurs, fach);
		daten.jahrgaenge.addAll(jahrgangsIDs);
		if (kurs.Schienen != null) {
			for (final Long schienenNummer : strLongToList(kurs.Schienen)) {
				final Map mapJahrgangID = mapNummerJahrgangID.get(schienenNummer.intValue());
				if ((mapJahrgangID != null) && (!mapJahrgangID.isEmpty())) {
					for (final Long jgID : jahrgangsIDs) {
						final Long schienenID = mapJahrgangID.get(jgID);
						if (schienenID != null)
							daten.schienen.add(schienenID);
					}
				}
			}
		}
		daten.schueler.addAll(schuelerIDs);
		return Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(daten).build();
	}


	@Override
	public Response patch(final Long id, final InputStream is) {
		throw new UnsupportedOperationException();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy