de.svws_nrw.data.stundenplan.DataStundenplanKlassen Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of svws-db-utils Show documentation
Show all versions of svws-db-utils Show documentation
Diese Bibliothek unterstützt bei dem Zugriff auf Datenbanken für die Schulverwaltungssoftware in NRW
package de.svws_nrw.data.stundenplan;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import de.svws_nrw.core.data.stundenplan.StundenplanKlasse;
import de.svws_nrw.data.DataManager;
import de.svws_nrw.db.DBEntityManager;
import de.svws_nrw.db.dto.current.schild.klassen.DTOKlassen;
import de.svws_nrw.db.dto.current.schild.schueler.DTOSchuelerLernabschnittsdaten;
import de.svws_nrw.db.dto.current.schild.schule.DTOJahrgang;
import de.svws_nrw.db.dto.current.schild.stundenplan.DTOStundenplan;
import de.svws_nrw.db.dto.current.schild.stundenplan.DTOStundenplanUnterrichtKlasse;
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 StundenplanKlasse}.
*/
public final class DataStundenplanKlassen extends DataManager {
private final Long stundenplanID;
/**
* Erstellt einen neuen {@link DataManager} für den Core-DTO
* {@link StundenplanKlasse}.
*
* @param conn die Datenbank-Verbindung für den Datenbankzugriff
* @param stundenplanID die ID des Stundenplans, dessen Klassen abgefragt werden
*/
public DataStundenplanKlassen(final DBEntityManager conn, final Long stundenplanID) {
super(conn);
this.stundenplanID = stundenplanID;
}
/**
* Lambda-Ausdruck zum Umwandeln eines Datenbank-DTOs {@link DTOKlassen} in
* einen Core-DTO {@link StundenplanKlasse}.
*/
private static final Function dtoMapper = (final DTOKlassen k) -> {
final StundenplanKlasse daten = new StundenplanKlasse();
daten.id = k.ID;
daten.kuerzel = k.Klasse;
daten.bezeichnung = (k.Bezeichnung == null) ? "" : k.Bezeichnung;
daten.sortierung = (k.Sortierung == null) ? 32000 : k.Sortierung;
daten.istSichtbar = k.Sichtbar;
return daten;
};
@Override
public Response getAll() throws ApiOperationException {
return this.getList();
}
/**
* Gibt die Klassen des Stundenplans zurück.
*
* @param conn die Datenbankverbindung
* @param idStundenplan die ID des Stundenplans
*
* @return die Liste der Klassen
*
* @throws ApiOperationException im Fehlerfall
*/
public static List getKlassen(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 klassen = conn.queryList(DTOKlassen.QUERY_BY_SCHULJAHRESABSCHNITTS_ID, DTOKlassen.class, stundenplan.Schuljahresabschnitts_ID);
if (klassen.isEmpty())
return new ArrayList<>();
final List klassenIDs = klassen.stream().map(k -> k.ID).toList();
final List jahrgaengsIDs = DataStundenplanJahrgaenge.getJahrgaenge(conn, idStundenplan).stream().map(j -> j.id).toList();
// Bestimme die Schüler-Lernabschnitte für die Zuordnung der Schüler zu den Klassen
final List lernabschnitte = conn.queryList(
"SELECT e FROM DTOSchuelerLernabschnittsdaten e WHERE e.Schuljahresabschnitts_ID = ?1 AND e.Klassen_ID IN ?2 AND e.WechselNr = 0",
DTOSchuelerLernabschnittsdaten.class, idStundenplan, klassenIDs);
final Map> mapKlasseSchuelerIDs = lernabschnitte.stream()
.collect(Collectors.groupingBy(la -> la.Klassen_ID, Collectors.mapping(la -> la.Schueler_ID, Collectors.toList())));
// Erstelle die Core-DTOs
final ArrayList daten = new ArrayList<>();
for (final DTOKlassen k : klassen) {
final StundenplanKlasse klasse = dtoMapper.apply(k);
if (k.Jahrgang_ID == null) {
klasse.jahrgaenge.addAll(jahrgaengsIDs);
} else {
klasse.jahrgaenge.add(k.Jahrgang_ID);
}
final List schuelerIDs = mapKlasseSchuelerIDs.get(klasse.id);
if ((schuelerIDs != null) && (!schuelerIDs.isEmpty()))
klasse.schueler.addAll(schuelerIDs);
daten.add(klasse);
}
return daten;
}
@Override
public Response getList() throws ApiOperationException {
final List daten = getKlassen(conn, this.stundenplanID);
return Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(daten).build();
}
/**
* Ermittelt die Informationen zu der angegebenen Klasse für den angegebenen Stundenplan.
*
* @param conn die Datenbank-Verbindung
* @param idStundenplan die ID des Stundenplans
* @param idKlasse die ID der Klasse
*
* @return die Informationen zu der angegebenen Klasse für den angegebenen Stundenplan
*
* @throws ApiOperationException im Fehlerfall
*/
public static StundenplanKlasse getById(final DBEntityManager conn, final long idStundenplan, final long idKlasse) 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 DTOKlassen klasse = conn.queryByKey(DTOKlassen.class, idKlasse);
if (klasse == null)
throw new ApiOperationException(Status.NOT_FOUND, "Es wurde keine Klasse mit der ID %d gefunden.".formatted(idKlasse));
if (klasse.Schuljahresabschnitts_ID != stundenplan.Schuljahresabschnitts_ID)
throw new ApiOperationException(Status.BAD_REQUEST,
"Der Schuljahresabschnitt %d der Klasse mit der ID %d stimmt nicht mit dem Schuljahresabschitt %d bei dem Stundenplan mit der ID %d überein."
.formatted(klasse.Schuljahresabschnitts_ID, klasse.ID, stundenplan.Schuljahresabschnitts_ID, stundenplan.ID));
// Jahrgänge bestimmen
final List jahrgangsIDs = new ArrayList<>();
if (klasse.Jahrgang_ID == null) {
jahrgangsIDs.addAll(conn.queryAll(DTOJahrgang.class).stream().map(j -> j.ID).toList());
} else {
jahrgangsIDs.add(klasse.Jahrgang_ID);
}
// Bestimme die Schüler-Lernabschnitte für die Zuordnung der Schüler zu den Klassen
final List lernabschnitte = conn.queryList(
"SELECT e FROM DTOSchuelerLernabschnittsdaten e WHERE e.Schuljahresabschnitts_ID = ?1 AND e.Klassen_ID = ?2 AND e.WechselNr = 0",
DTOSchuelerLernabschnittsdaten.class, idStundenplan, klasse.ID);
final List schuelerIDs = lernabschnitte.stream().map(la -> la.Schueler_ID).distinct().toList();
// DTO erstellen
final StundenplanKlasse daten = dtoMapper.apply(klasse);
daten.jahrgaenge.addAll(jahrgangsIDs);
daten.schueler.addAll(schuelerIDs);
return daten;
}
@Override
public Response get(final Long id) throws ApiOperationException {
if (id == null)
throw new ApiOperationException(Status.BAD_REQUEST, "Eine Anfrage zu einer Klasse mit der ID null ist unzulässig.");
final StundenplanKlasse daten = getById(conn, stundenplanID, id);
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();
}
/**
* Erstellt eine Map, in der Klassen den gegebenen UnterrichtIds eines
* Stundenplans zugeordnet werden.
*
* @param conn die Datenbankverbindung
* @param idStundenplan die ID des Stundenplans
* @param unterrichtIds die unterrichte, denen die Klassen zugeordnet werden sollen
*
* @return eine Map, in der allen UnterrichtsIds die Klassen zugeordnet werden
*
* @throws ApiOperationException im Fehlerfall
*/
public static Map> getKlassenByUnterrichtIds(final DBEntityManager conn,
final Long idStundenplan, final List unterrichtIds) throws ApiOperationException {
final Map> result = new HashMap<>();
if (unterrichtIds == null)
throw new ApiOperationException(Status.NOT_FOUND, "Keine Unterricht-IDs gegeben.");
if (unterrichtIds.isEmpty())
return result;
final List klassen = DataStundenplanKlassen.getKlassen(conn, idStundenplan);
if (klassen.isEmpty())
return result;
final Map klasseById = klassen.stream().collect(Collectors.toMap(k -> k.id, Function.identity()));
final List unterrichtKlassen = conn.queryList(
DTOStundenplanUnterrichtKlasse.QUERY_LIST_BY_UNTERRICHT_ID, DTOStundenplanUnterrichtKlasse.class, unterrichtIds);
List klassenByUnterrichtId;
for (final DTOStundenplanUnterrichtKlasse unterrichtKlasse : unterrichtKlassen) {
klassenByUnterrichtId = result.computeIfAbsent(unterrichtKlasse.Unterricht_ID, unterrichtId -> new ArrayList<>());
klassenByUnterrichtId.add(klasseById.get(unterrichtKlasse.Klasse_ID));
}
return result;
}
}