diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java index 672cbb3..436ad38 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java @@ -508,7 +508,11 @@ public class MongoDBHandler { * Justus Jonas operations * ======================= */ - + /** + * Fügt eine Session in die Datenbank ein. + * + * @param session Das Session-Objekt, das eingefügt werden soll. + */ public void insertSession(Session session) { Document sessionDocument = new Document("sessionId", session.getId()) .append("dateTime", session.getDateTime()) @@ -518,6 +522,15 @@ public class MongoDBHandler { sessionsCollection.insertOne(sessionDocument); } + /** + * Erstellt eine neue Session anhand der übergebenen Parameter, generiert eine eindeutige sessionId, + * fügt sie in die Datenbank ein und gibt die erstellte Session zurück. + * + * @param dateTime Startzeit der Session. + * @param endTime Endzeit der Session. + * @param legislativePeriod Die Legislaturperiode. + * @return Die neu erstellte Session. + */ public Session insertSession(String dateTime, String endTime, String legislativePeriod) { // get a new random sessionId that is not already in use int sessionId = 0; @@ -535,13 +548,22 @@ public class MongoDBHandler { return session; } - + /** + * Fügt eine Liste von Sessions in die Datenbank ein. + * + * @param sessions Liste der Sessions, die eingefügt werden sollen. + */ public void insertSessions(List sessions) { for (Session session : sessions) { insertSession(session); } } + /** + * Fügt eine Liste von AgendaItems in die Datenbank ein. + * + * @param agendaItems Liste der AgendaItems, die eingefügt werden sollen. + */ public void insertAgendaItems(List agendaItems) { List agendaItemDocuments = new ArrayList<>(); for (AgendaItem agendaItem : agendaItems) { @@ -555,7 +577,15 @@ public class MongoDBHandler { agendaItemsCollection.insertMany(agendaItemDocuments); } - + /** + * Erstellt ein neues AgendaItem für eine bestimmte Session und einen Titel. + * + * @param sessionId Die Session-ID, zu der das AgendaItem gehört. + * @param title Der Titel des AgendaItems. + * @return Das neu erstellte AgendaItem. + * @throws SessionNotFoundException Falls keine Session mit der angegebenen sessionId existiert. + * @throws ServerErrorException Falls ein Serverfehler auftritt. + */ public AgendaItem insertAgendaItem(int sessionId, String title) throws SessionNotFoundException, ServerErrorException { // check if session exists List sessions = retrieveAllSessions(Filters.eq("sessionId", sessionId)); @@ -579,6 +609,11 @@ public class MongoDBHandler { return agendaItem; } + /** + * Fügt eine Liste von Speech-Objekten in die Datenbank ein. + * + * @param speeches Liste der Speeches, die eingefügt werden sollen. + */ public void insertSpeeches(List speeches) { // Convert each Speech to a Document List speechDocuments = new ArrayList<>(); @@ -629,7 +664,11 @@ public class MongoDBHandler { speechesCollection.insertMany(speechDocuments); } - + /** + * Ruft alle Speech-Dokumente ohne Filter ab und wandelt sie in eine Liste von Speech-Objekten um. + * + * @return Eine Liste aller Speeches. + */ public List retrieveAllSpeeches() { List speeches = speechesCollection.find().into(new ArrayList<>()); List result = new ArrayList<>(); @@ -640,6 +679,13 @@ public class MongoDBHandler { return result; } + + /** + * Ruft alle Speech-Dokumente ab, die dem übergebenen Filter entsprechen, und wandelt sie in eine Liste von Speech-Objekten um. + * + * @param filter Der Filter als Bson-Objekt. + * @return Eine Liste der Speeches, die dem Filter entsprechen. + */ public List retrieveAllSpeeches(Bson filter) { List speeches = speechesCollection.find(filter).into(new ArrayList<>()); List result = new ArrayList<>(); @@ -650,6 +696,11 @@ public class MongoDBHandler { return result; } + /** + * Ruft alle Session-Dokumente ohne Filter ab und wandelt sie in eine Liste von Session-Objekten um. + * + * @return Eine Liste aller Sessions. + */ public List retrieveAllSessions() { List sessions = sessionsCollection.find().into(new ArrayList<>()); List result = new ArrayList<>(); @@ -660,6 +711,12 @@ public class MongoDBHandler { return result; } + /** + * Ruft alle Session-Dokumente ab, die dem übergebenen Filter entsprechen, und wandelt sie in eine Liste von Session-Objekten um. + * + * @param filter Der Filter als Bson-Objekt. + * @return Eine Liste der Sessions, die dem Filter entsprechen. + */ public List retrieveAllSessions(Bson filter) { List speeches = sessionsCollection.find(filter).into(new ArrayList<>()); List result = new ArrayList<>(); @@ -670,6 +727,11 @@ public class MongoDBHandler { return result; } + /** + * Ruft alle AgendaItem-Dokumente ohne Filter ab und wandelt sie in eine Liste von AgendaItem-Objekten um. + * + * @return Eine Liste aller AgendaItems. + */ public List retrieveAllAgendaItems() { List agendaItems = agendaItemsCollection.find().into(new ArrayList<>()); List result = new ArrayList<>(); @@ -680,6 +742,12 @@ public class MongoDBHandler { return result; } + /** + * Ruft alle AgendaItem-Dokumente ab, die dem übergebenen Filter entsprechen, und wandelt sie in eine Liste von AgendaItem-Objekten um. + * + * @param filter Der Filter als Bson-Objekt. + * @return Eine Liste der AgendaItems, die dem Filter entsprechen. + */ public List retrieveAllAgendaItems(Bson filter) { List speeches = agendaItemsCollection.find(filter).into(new ArrayList<>()); List result = new ArrayList<>(); @@ -690,6 +758,13 @@ public class MongoDBHandler { return result; } + /** + * Aktualisiert das Speech-Dokument, das durch den speechKey identifiziert wird, + * und setzt das Feld "xmiData" auf den übergebenen xmiContent. + * + * @param speechKey Der Schlüssel der Rede. + * @param xmiContent Der XMI-Inhalt als String. + */ public void updateXmiData(String speechKey, String xmiContent) { speechesCollection.updateOne( Filters.eq("speechKey", speechKey), @@ -697,6 +772,9 @@ public class MongoDBHandler { ); } + /** + * Löscht alle Dokumente, die mit den Reden, Sessions, AgendaItems (und History) zusammenhängen. + */ public void deleteSpeechRelatedDocuments() { speechesCollection.deleteMany(new Document()); sessionsCollection.deleteMany(new Document()); @@ -704,6 +782,11 @@ public class MongoDBHandler { //historyCollection.deleteMany(new Document()); } + /** + * Führt einen Bulk-Write für NLP-bezogene Updates in der Speech-Collection aus. + * + * @param bulkOperations Eine Liste von Bulk-Update-Operationen. + */ public void bulkWriteNlpData(List> bulkOperations) { if (!bulkOperations.isEmpty()) { BulkWriteOptions options = new BulkWriteOptions().ordered(false); @@ -721,6 +804,11 @@ public class MongoDBHandler { } } + /** + * Zählt die Anzahl der Speech-Dokumente, die ein Feld "analysisResults" besitzen. + * + * @return Die Anzahl der Speech-Dokumente mit einem "analysisResults"-Feld. + */ public long checkAnalysisResultsField() { return speechesCollection.countDocuments(Filters.exists("analysisResults")); } @@ -781,7 +869,12 @@ public class MongoDBHandler { } } - + /** + * Überprüft, ob eine Session mit der angegebenen Session-Nummer in der sessionsCollection existiert. + * + * @param sessionNumber Die Session-Nummer als String. + * @return true, wenn mindestens ein Dokument mit der angegebenen sessionId existiert, andernfalls false. + */ public boolean sessionExists(String sessionNumber) { Document filter = new Document("sessionId", Integer.valueOf(sessionNumber)); long count = sessionsCollection.countDocuments(filter); @@ -796,10 +889,19 @@ public class MongoDBHandler { return photoDocument.getString("base64"); } + /** + * Schließt die MongoDB-Verbindung. + */ public void close() { mongoClient.close(); } + /** + * Gibt ein einzelnes Speech-Dokument zurück, das dem angegebenen Filter entspricht. + * + * @param filter Der Filter als Document. + * @return Das erste Speech-Dokument, das dem Filter entspricht, oder null, wenn keines gefunden wird. + */ public Document getSpeech(Document filter) { return speechesCollection.find(filter).first(); } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java index 17e125b..8d6d4cd 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java @@ -315,6 +315,15 @@ public class NlpUtils { } + /** + * Führt den Remote-NLP-Driver auf unprozessierten Reden aus und aktualisiert die Datenbank. + *

+ * Es werden alle Reden ohne "analysisResults" abgerufen, mit den Remote-Komponenten (spaCy und Vader) + * verarbeitet, die NLP-Ergebnisse extrahiert und per Bulk-Update in der Datenbank gespeichert. + *

+ * + * @throws Exception falls ein Fehler auftritt. + */ public static void runRemoteDriver() throws Exception { DUUILuaContext luaContext = new DUUILuaContext().withJsonLibrary(); pComposer = new DUUIComposer() diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java index 4198ec1..ee9ae85 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java @@ -327,7 +327,19 @@ public abstract class PPRUtils { }); } - + /** + * Liest XML-Protokolle von der Bundestag-OpenData-URL und verarbeitet sie. + * + *

+ * Diese Methode ruft wiederholt Seiten mit XML-Links (Protokollen) ab, basierend auf einem + * Offset und Limit. Für jeden gefundenen Link wird die XML-Datei heruntergeladen und geparst. + * Einzigartige Protokolle werden anhand des "sitzung-nr"-Attributs identifiziert. Falls ein Protokoll + * bereits verarbeitet wurde (gespeichert in {@code processedProtocols}), wird es übersprungen. + * Die verarbeiteten XML-Dokumente werden in der globalen Menge {@code xmlProtocols} gesammelt. + *

+ * + * @return Ein Set von {@code org.w3c.dom.Document}, das die verarbeiteten XML-Protokolle enthält. + */ public static Set processXML() { int offset = 0; int limit = 10; @@ -425,6 +437,24 @@ public abstract class PPRUtils { return fileNames; } + /** + * Ruft neue Protokoll-XML-Dokumente von der Bundestag OpenData-API ab und verarbeitet sie. + * + * Diese Methode verwendet eine paginierte Abfrage (über Offset und Limit) der URL + * "https://www.bundestag.de/ajax/filterlist/de/services/opendata/866354-866354". + * Für jeden gefundenen XML-Link wird anhand des Dateinamens (z.B "20212.xml") die Sitzungsnummer extrahiert. + * Protokolle mit den Dateinamen "20007" oder "20212" werden als fehlerhaft erkannt und übersprungen. + * Falls die extrahierte Sitzungsnummer (nach Entfernen eines möglichen "20"-Präfixes) noch nicht in der Datenbank existiert + * (bestimmt durch mongoDBHandler.sessionExists(sessionNumber)), wird das XML-Dokument heruntergeladen und geparst. + * Die neu verarbeiteten XML-Dokumente werden in einem Set gesammelt und zurückgegeben. + * + * Die Pagination erfolgt über das HTML-Element
mit dem Attribut + * data-nextoffset. Ist kein nächster Offset vorhanden, wird die Schleife beendet. + * + * + * @param mongoDBHandler der MongoDBHandler, der für die Prüfung der Existenz einer Session in der Datenbank verwendet wird + * @return ein Setvon org.w3c.dom.Document, das alle neuen (noch nicht verarbeiteten) Protokoll-XML-Dokumente enthält + */ public static Set checkAndProcessNewProtocols(MongoDBHandler mongoDBHandler) { Set newProtocols = new HashSet<>(); int offset = 0; diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/SpeechVideoUpdater.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/SpeechVideoUpdater.java index 80ce882..21db09a 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/SpeechVideoUpdater.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/SpeechVideoUpdater.java @@ -24,7 +24,12 @@ public class SpeechVideoUpdater { private static final String BASE_URL = "https://cldf-od.r53.cdn.tv1.eu/1000153copo/ondemand/app144277506/145293313/"; private static final String SUFFIX = "_h264_720_400_2000kb_baseline_de_2192.mp4?fdl=1"; - + /** + * Initialisiert den Video-Upload-Prozess. + * Diese Methode prüft, ob bereits ein Video für die erste Rede (speechId 0) in Session 187 und AgendaItem 4 vorhanden ist. + * Falls ein Video vorhanden ist, wird der Download übersprungen. Andernfalls wird findVideos() aufgerufen, + * um die Videos herunterzuladen und in GridFS hochzuladen sowie die Speech-Dokumente zu aktualisieren. + */ public static void init() { MongoDBHandler mongoDBHandler = new MongoDBHandler(); try { @@ -49,6 +54,13 @@ public class SpeechVideoUpdater { } } + /** + * Lädt Videos für Reden in Session 187, AgendaItem 4 herunter und lädt diese in GridFS hoch. + * Anschließend wird für jede Rede (speechId 0 bis 8) ein Bulk-Update erstellt, um das Speech-Dokument + * mit dem Videolink (GridFS-ID als Hex-String) zu aktualisieren. + * + * @throws Exception Falls beim Download oder Upload ein Fehler auftritt. + */ public static void findVideos() throws Exception { MongoDBHandler mongoDBHandler = new MongoDBHandler(); @@ -93,6 +105,14 @@ public class SpeechVideoUpdater { mongoDBHandler.close(); } + /** + * Lädt das Video von der angegebenen URL herunter und speichert es als temporäre Datei. + * + * @param videoUrl Die URL des Videos. + * @param fileName Der gewünschte Dateiname für die temporäre Datei. + * @return Eine {@code File}-Instanz, die auf die heruntergeladene Datei verweist. + * @throws IOException Falls beim Download oder Schreiben der Datei ein Fehler auftritt. + */ private static File downloadVideo(String videoUrl, String fileName) throws IOException { URL url = new URL(videoUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); @@ -110,6 +130,15 @@ public class SpeechVideoUpdater { return tempFile; } + /** + * Lädt die übergebene Videodatei in GridFS hoch. + * + * @param gridFSBucket Der {@code GridFSBucket}, der für die Collection "videos" in der Datenbank konfiguriert ist. + * @param videoFile Die zu hochladende Videodatei. + * @param fileName Der Name, unter dem die Datei in GridFS gespeichert werden soll. + * @return Die {@code ObjectId} der in GridFS gespeicherten Datei. + * @throws IOException Falls beim Hochladen der Datei ein Fehler auftritt. + */ private static ObjectId uploadVideoToGridFS(GridFSBucket gridFSBucket, File videoFile, String fileName) throws IOException { try (InputStream streamToUploadFrom = new FileInputStream(videoFile)) { GridFSUploadOptions options = new GridFSUploadOptions() diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/SpeechParser.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/SpeechParser.java index 1750a36..e7e3ede 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/SpeechParser.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/SpeechParser.java @@ -39,6 +39,13 @@ public class SpeechParser { public void setParseLegislativePeriods(Boolean parseLegislativePeriods) { } + /** + * Parst alle Sessions aus den globalen XML-Dokumenten, die über PPRUtils.processXML() abgerufen werden. + * Dabei werden auch die zugehörigen Reden und AgendaItems (sowie deren Inhalte) geparst. + * Die temporären Dateien werden nach der Verarbeitung gelöscht. + * + * @return Eine Liste von Session-Objekten, die aus den XML-Dokumenten erstellt wurden. + */ public List parseAllSessions() { List sessions = new ArrayList<>(); this.speeches = new ArrayList<>(); @@ -60,6 +67,15 @@ public class SpeechParser { } + /** + * Parst alle neuen Sessions aus den übergebenen XML-Dokumenten. + * Diese Methode wird verwendet, wenn bereits ein Set von XML-Dokumenten (z. B. von neuen Protokollen) + * vorliegt. Für jedes XML-Dokument wird eine temporäre Datei erstellt, geparst und anschließend gelöscht. + * + * @param xmlDocuments Ein Set von XML-Dokumenten (als org.w3c.dom.Document), + * die geparst werden sollen. + * @return Eine Liste von Session-Objekten, die aus den XML-Dokumenten erstellt wurden. + */ public List parseAllSessions(Set xmlDocuments) { List sessions = new ArrayList<>(); this.speeches = new ArrayList<>(); @@ -80,6 +96,21 @@ public class SpeechParser { } + /** + * Parst eine einzelne Session aus einer XML-Datei. + * + * + * Diese Methode erstellt mithilfe eines DocumentBuilder ein org.w3c.dom.Document aus der übergebenen Datei. + * Anschließend werden die Sitzungsdaten (z. B. Legislaturperiode, Sitzung-Nummer, Datum und Uhrzeit) aus dem Root-Element extrahiert. + * Danach werden die AgendaItems der Session und die zugehörigen Reden (inkl. Redner und Inhalte) geparst. + * Für jeden AgendaItem werden die zugehörigen Reden aus den untergeordneten XML-Elementen ("rede") extrahiert. + * Die geparsten Daten werden in Objekten vom Typ Session_File_Impl und AgendaItem_File_Impl abgelegt. + * + * + * @param file Die temporäre XML-Datei, die die Session-Daten enthält. + * @return Ein Session-Objekt, das aus der XML-Datei erstellt wurde. + * @throws Exception Falls beim Parsen der XML-Datei oder der Konvertierung in ein Session-Objekt ein Fehler auftritt. + */ private Session parseSessionFile(File file) throws Exception { //file = removeDoctypeAnnotation(file.getAbsolutePath()); @@ -184,6 +215,16 @@ public class SpeechParser { return session; } + /** + * Retrieves the text content of the first child element with the specified tag name. + * The method searches for child elements with the given tag name in the provided element. + * If at least one such element is found, its text content is returned after trimming leading and trailing whitespace. + * If no child element with the specified tag name exists, the method returns null. + * + * @param parent the parent XML element in which to search for the child element + * @param tagName the name of the child element whose text content is to be retrieved + * @return the trimmed text content of the first matching child element, or null if no such element is found + */ private static String getOptionalTextContent(Element parent, String tagName) { NodeList nodes = parent.getElementsByTagName(tagName); if (nodes.getLength() > 0) {