Merge branch 'main' of https://ppr.gitlab.texttechnologylab.org/s1188354/multimodal_parliament_explorer_05_1
This commit is contained in:
commit
4db18688b5
108 changed files with 6418 additions and 1235 deletions
38
Benutzerhandbuch.txt
Normal file
38
Benutzerhandbuch.txt
Normal file
|
@ -0,0 +1,38 @@
|
|||
BENUTZERHANDBUCH MULTIMODAL PARLIAMENT EXPLORER
|
||||
GRUPPE_05_01
|
||||
|
||||
Der Multimodal Parliament Explorer ist eine client-server basierte Anwendung zum automatischen abrufen, analysieren, visualisieren und exportieren aller Reden des Bundestags der aktuellen Legislaturperiode.
|
||||
|
||||
Mit unserem Programm kann man Reden des Bundestags interaktiv erkunden, Statistiken zu den zugehörigen Reden einsehen und diese selbst weiterverwenden.
|
||||
|
||||
|
||||
1. Systemanforderungen
|
||||
|
||||
- Java 17+
|
||||
- Maven
|
||||
- Einen modernen Webbrowser (Chrome, Firefox, Edge)
|
||||
- Einen Internetzugang
|
||||
|
||||
|
||||
2. Hauptfunktionen
|
||||
|
||||
Datenimport:
|
||||
Automatischer Download der XML Protokolle inklusive Videos
|
||||
|
||||
NLP-Analyse:
|
||||
Analyse der Reden durch einen NLP-Docker
|
||||
|
||||
Datenexploration:
|
||||
Filterbar nach Redner, Thema und Datum
|
||||
|
||||
Visualisierung der analysierten Daten:
|
||||
Durch verschiedene Charts werden die Analysedaten anschaulich und verdaubar wiedergegeben
|
||||
|
||||
Export:
|
||||
Alle Reden können als PDF und XML exportiert werden.
|
||||
|
||||
|
||||
3. Support und Weiterführende Dokumentation
|
||||
|
||||
Detaillierte Entwicklungs‑ und Nutzungsanleitungen finden Sie im Repository unter /doc oder auf unserer GitLab-Page bei https://ppr.gitlab.texttechnologylab.org/leonkastner/multimodal-parliament-explorer-docu
|
||||
Bei Fragen oder Fehlern können sie sich gerne bei uns melden.
|
188
README.md
188
README.md
|
@ -1,12 +1,196 @@
|
|||
# Multimodal Parliament Explorer (Gruppe_05_1)
|
||||
|
||||
## Umgebung - wichtiger Hinweis!
|
||||
|
||||
### Docker und NLP
|
||||
|
||||
Damit der Zugriff auf die Docker-Treiber funktioniert, muss man in IntelliJ folgendes tun:
|
||||
|
||||
Edit Run Environment --> Modify Option --> Add VM options
|
||||
|
||||
Dann im neu erscheinenden "VM options"-Feld folgendes schreiben:
|
||||
|
||||
--add-opens java.base/java.util=ALL-UNNAMED
|
||||
|
||||
### LaTex Export
|
||||
|
||||
Damit der LaTeX Export funktioniert, muss der LaTeX Compiler installiert sein.
|
||||
|
||||
Unter Ubuntu (Linux) kann das Paket mit dem folgenden Befehl installiert werden:
|
||||
|
||||
```shell
|
||||
sudo apt install texlive-latex-extra
|
||||
```
|
||||
|
||||
Unter Windows ist die Installation über MikTex möglich.
|
||||
|
||||
Ist kein Compiler installiert, wird beim Start des Programms eine Warnung ausgegeben:
|
||||
|
||||
```shell
|
||||
-------------------------------------------------o
|
||||
TeX SDK not installed. PDF export will not work.
|
||||
-------------------------------------------------o
|
||||
```
|
||||
|
||||
## Aufruf
|
||||
|
||||
Der Nutzer führt die **Main.java** Datei aus.
|
||||
Folgende Command Line Argumente werden akzeptiert:
|
||||
|
||||
- onlyRunWeb: Fährt die WebServies hoch und wartet auf Requests. Die Einstiegsseite kann im Browser geöffnet werden: http://localhost:5876 (Port 5876 ist in der Resourcendatei javalin.properties definiert). In der Regel würde man Main nur mit diesem Parameter aufrufen.
|
||||
- uploadMemberPhotos: Um Parlamentarierfotos vom Resource-Verzeichnis in die Datenbank hochzuladen.
|
||||
- forceUploadMembers: Lädt die Daten der Parlamentariern erneut in die Datenbank.
|
||||
- forceUploadSpeeches: Lädt die Reden erneut in die Datenbank, führt die NLP-Analyse auf der Reden und speichert die Analyseergebnisse in die Datenbank.
|
||||
- rebuildMetadata: Berechnet die Metadaten neu. In der Metadata-Collection stehen Daten, welche oft benötigt werden, aber nicht jedes Mal erneut berechnet werden sollen. Momentan sind es die Liste der Parteien und die Liste der möglichen NLP-Topics.
|
||||
- debugLogging: Diese Flag bestimmt, ob Debug-Ausgaben des Loggers angezeigt werden sollen.
|
||||
|
||||
## Dokumentation
|
||||
|
||||
- Use Case Diagramm
|
||||
- Package/Klassen-Diagramm
|
||||
- Die Planung
|
||||
- Das Gantt Diagramm
|
||||
stehen im "doku"-Verzeichnis.
|
||||
|
||||
Die Planung beinhaltet:
|
||||
- Die Liste der Aufgaben, nach Bereichen gruppiert. Die Bereiche sind: Planung, Domain-Entitäten, XML, Datenbank, Rest Services, Front End, NLP-Verarbeitug, Export, Dokumentation
|
||||
- Wer macht was
|
||||
- Geschätzter Aufwand (niedrig / mittel / hoch)
|
||||
|
||||
|
||||
### Classdiagram puml generator
|
||||
|
||||
Das Classdiagram wird durch den puml generator generiert:
|
||||
|
||||
## Classdiagram puml generator
|
||||
```shell
|
||||
python puml_generator.py
|
||||
```
|
||||
|
||||
## Upload member Images
|
||||
Die aktuelle Version des Klassen-/Package-Diagramms ist bei der Abgabe unter `generated_class_diagram.puml` zu finden. Außerdem gibt es das Diagram auch als LaTe, PDF und Bild (png) Version im `/doc` Ordner zu funden.
|
||||
|
||||
## Datenbank
|
||||
|
||||
Die wichtigsten Collections sind *"speech"* und *"speaker"*. In "pictures" stehen die Bilder der Abgeordneten. In "metadata" stehen die bereits erwähnten Metadaten.
|
||||
Die Collections "agendaItems" und "sessions" werden zwar initial befüllt und kurzzeitig verwendet, um die Zeitstempel der Reden sowie die Agendapunkte zu konstruieren, werden aber danach nicht weiter verwendet.
|
||||
|
||||
## Erzeugung der NLP-Daten
|
||||
Ressourcenbereitstellung:
|
||||
- Die benötigten Annotationen werden aus dem Ressourcenordner geladen
|
||||
- Es wird vorausgesetzt, dass in der "speeches"-Collection eine ZIP-Datei (20.zip) vorhanden ist, die alle erforderlichen Annotationen enthält
|
||||
- Zusätzlich muss das TypeSystem in Form der Datei TypeSystem.xml vorliegen, um die korrekte Umwandlung der Annotationen in den JCas zu ermöglichen.
|
||||
|
||||
Abruf der Reden:
|
||||
- Die Reden werden anhand der eindeutigen ID (speechKey) aus der Datenbank abgerufen.
|
||||
- Dabei werden die Reden, die bereits annotiert vorliegen, zur weiteren Verarbeitung selektiert
|
||||
|
||||
Annotationen verarbeiten:
|
||||
- Die geladenen Annotationen werden in einen JCas (Java Common Analysis Structure) umgewandelt.
|
||||
- Im JCas werden die Annotationen serialisiert, sodass sie in einem einheitlichen Format vorliegen.
|
||||
- Anschließend werden diese serialisierten Daten in der Datenbank dem entsprechenden Speech-Dokument zugeordnet und gespeichert
|
||||
|
||||
Remote-Verarbeitung:
|
||||
- Reden, die nicht in der 20.zip vorhanden sind – also noch nicht lokal annotiert wurden – werden anschließend durch den RemoteDriver verarbeitet.
|
||||
- Der RemoteDriver ruft dabei externe NLP-Komponenten (z. B. spaCy oder Vader) auf, um fehlende Annotationen zu erzeugen.
|
||||
- Auch die Ergebnisse der Remote-Verarbeitung werden serialisiert und in der Datenbank an das zugehörige Speech-Dokument angehängt.
|
||||
|
||||
|
||||
## Komponenten und Package Struktur
|
||||
- database: die Klasse *MongoDBHandler* kümmert sich um die Herstellung der Datenbankverbindung und um generelle CRUD-Operationen. Die Klasse *MongoPprUtils* kümmert sich um das Lesen der Objekte und Datenstrukturen, die für diese Übung notwendig sind.
|
||||
|
||||
- domain: hier werden die Entitäten definiert. Subpackage "database" behandelt die Objekte, die aus der Datenbank kommen. Subpackage "html" behandelt die Objekte, die nicht in der Datenbank sind und lediglich angezeigt werden.
|
||||
|
||||
- rest: alles, was mit den WebServices zu tun hat - die 4 Controller (für Parlamentarier, Fotos, Videos und Reden), eine Configklasse und der Handler. Im Handler wird die Javalin-Konfiguration definiert sowie die Routes für die 8 Endpoints.
|
||||
|
||||
- export: alles, was mit dem Export (LaTex/PDF, XML) zu tun hat, findet hier Platz.
|
||||
|
||||
- xml: für das Einlesen der Parlamentarier- und Rede-Daten.
|
||||
|
||||
- util: eine kleine Sammlung von Utility-Klassen.
|
||||
|
||||
- nlp: Utils für die NLP-Verarbeitung
|
||||
|
||||
- exceptions: für die Exceptions
|
||||
|
||||
|
||||
## Struktur des resources-Ordner
|
||||
|
||||
- config: config files für javalin und für XML (im letzteren steht die URL zum Herunterladen der Parlamentarier)
|
||||
|
||||
- plenarprotokolle: enthält die DTD-Datei zum Parsen der Abgeordnetendaten
|
||||
|
||||
- speeches: enthält die Datei TypeSystem.xml
|
||||
|
||||
- static: enthält das Stylesheet und das Favicon
|
||||
|
||||
- templates: enthält die FreeMarker-Templates
|
||||
|
||||
- tex: enthält die nötigen Resourcen für Latex, etwa die preamble.tex
|
||||
|
||||
|
||||
## Ablauf / Workflow
|
||||
|
||||
Wir gehen hier vom Workflow des Endnutzers aus.
|
||||
|
||||
Wie man die Daten hochlädt, wurde bereit oben kurz erklärt.
|
||||
|
||||
1. Die Klasse Main wird ausgefüht und zwar mit dem "onlyRunWeb" Parameter.
|
||||
2. Javalin fährt die Webservices hoch und wartet auf Requests.
|
||||
3. Der User lädt die Einstiegsseite im Browser, etwas http://localhost:5876 . Die Startseite wird angezeigt. Das Hauptmenü enthält im Burgermenü Links zu "Parlamentarier", "Reden", "Exportieren" sowie "Home" und "Über".
|
||||
|
||||
### Parlamentarier-Seite
|
||||
|
||||
Eine Liste der Parlamentarier wird angezeigt. Man kann die Liste filtern. Man kann auf die jeweiligen Parlamentarier klicken und gelangt dann auf die Seite eines Parlamentariers.
|
||||
|
||||
Die Seite eines Parlamentariers beinhaltet Name, Foto, persöhnliche Daten, Mitgliedschaften und einen Link zu den Reden des Parlamentariers.
|
||||
|
||||
### Reden-Seite
|
||||
|
||||
Es werden alle Reden der jetzigen Legislaturperiode angezeigt.
|
||||
Man kann die Liste filtern (MOMENTAN NOCH ZU IMPLEMENTIEREN). Man kann auf die jeweilige Rede klicken und gelangt dann auf die Rede-Seite.
|
||||
|
||||
### Redeseite
|
||||
|
||||
Folgende Informationen werden angezeigt:
|
||||
- Informationen zum Redner (Name, Partei, Foto).
|
||||
- Informationen zur Rede (Datum, Uhrzeit, Agendapunkt).
|
||||
- Redetext. Vorstellung und Kommentare werden farblich gekennzeichnet.
|
||||
- Video bei Reden der Sitzung 187 Tagesordnungspunkt 4
|
||||
- NLP Informationen.
|
||||
|
||||
Der NLP-Abschnitt beinhaltet folgende Informationen:
|
||||
- Topics Information (als Bubble Chart): dabei entspricht die Größe der Bubbles der Häufigkeit/Prävalenz der Topics. Durch einen Mouse-Hover verändert sich die Schriftgröße, damit man auch die Texte der kleinen Bubbles sehen kann.
|
||||
- POS Information (als Bar Chart): Auf der X-Achse werden alle verschiedenen POS-Elemente die in der Rede erfasst wurden abgebildet, auf der Y-Achse die genaue Anzahl dieser Elemente.
|
||||
- Sentiments Information (als Radar Chart): Dieses Chart besitzt 3 Achsen, eine für den wert des positiven sentiments, eine für das negative sentiment, und die letzte für das neutrale sentiment. Die mitte des Charts steht für den Wert 0, und jede Ecke steht für den Wert 1 des zugehörigen sentiments. Es wird jeder analysierte Satz inklusive die gesamte Rede abgebildet. Ein Polygon steht hierbei für einen bestimmten analysierten Abschnitt der rede. Rechts neben dem Chart ist eine Legende aller Analysierten Objekte, von welchem das erste die Werte der gesamten Rede, und alle danach die einzelnen Satzteile darstellen.
|
||||
- Named Entities (als Sunburst Chart): der innere Kreis steht für den Typ (LOC, PER, ORG, MISC). Der äußere Kreis steht für die jeweiligen Named Entities. Die Größe der Bögen entsprechen den Häufigkeiten der Entitäten bzw. der Typen.
|
||||
|
||||
|
||||
Ein "Zurück"-Button ist auf den Seiten implementiert. Er führt erwartungsgemäß zur vorherigen Seite.
|
||||
|
||||
### Charts-Seite
|
||||
|
||||
Gleiche Struktur wie die Charts für die einzelnen reden, hier nur auf alle in der Datenbank vorhandenen Reden angewendet. Die sammlung der Daten passiert hier dynamisch ab Abruf der Seite.
|
||||
|
||||
### Export-Seite
|
||||
|
||||
Wie auch auf den einzelnen Seiten, gibt es hier die Option Reden zu exportieren. Es kann zwischen PDF und XML gewählt werden. Die verschiedenen Export-Optionen sind:
|
||||
- Export einer einzelnen Rede (mit Reden-ID)
|
||||
- Export aller Reden eines Parlamentariers (mit Parlamentarier-ID)
|
||||
- Export aller Reden eines NLP-Topics (mit Topic-String)
|
||||
- Export aller Reden (ohne Parameter)
|
||||
|
||||
Achtung: Der Export kann je nach Anzahl der Reden und der gewählten Option einige Zeit in Anspruch nehmen. Meist wird der Nutzer darüber informiert, dass der Prozess länger dauern kann.
|
||||
|
||||
|
||||
## Verschiedenes
|
||||
|
||||
### Nachladen neuer Reden (Thread)
|
||||
|
||||
Alle 10 Minuten checkt das Programm, ob auf der Bundestags.de Website neue Reden erschienen sind.
|
||||
Wenn neue Reden erkannt werden, werden diese heruntergeladen, mit dem RemoteDriver verarbeitert und abschließend noch in
|
||||
die Datenbank hochegladen. Auch wenn einfach so Reden in die Datenbank hinzugefügt werden, werden diese verarbeitet.
|
||||
|
||||
|
||||
### Upload member Images
|
||||
Crawl member images (not required as already in repository)
|
||||
```shell
|
||||
cd src/main/resources
|
||||
|
|
BIN
doc/Gantt_Chart_PPR_Abschlussprojekt.ods
Normal file
BIN
doc/Gantt_Chart_PPR_Abschlussprojekt.ods
Normal file
Binary file not shown.
BIN
doc/Gantt_Chart_PPR_Abschlussprojekt.pdf
Normal file
BIN
doc/Gantt_Chart_PPR_Abschlussprojekt.pdf
Normal file
Binary file not shown.
BIN
doc/PPR_Mockup.jpg
Normal file
BIN
doc/PPR_Mockup.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 187 KiB |
77
doc/UseCasePlantUML
Normal file
77
doc/UseCasePlantUML
Normal file
|
@ -0,0 +1,77 @@
|
|||
@startuml
|
||||
left to right direction
|
||||
actor Admin
|
||||
actor Nutzer
|
||||
actor SystemScheduler as "Zeitgesteuerter Dienst"
|
||||
|
||||
rectangle "Multimodal Parliament Explorer" {
|
||||
|
||||
package "Datenimport" {
|
||||
usecase "XML Protokolle herunterladen" as UC1
|
||||
usecase "XML verarbeiten & speichern" as UC2
|
||||
usecase "Videos herunterladen & speichern" as UC3
|
||||
usecase "Fotos der Abgeordneten speichern" as UC4
|
||||
usecase "NLP-Daten einlesen & verarbeiten" as UC5
|
||||
}
|
||||
|
||||
package "NLP Verarbeitung" {
|
||||
usecase "NLP Analyse mit DUUI durchführen" as UC6
|
||||
usecase "NLP-Resultate serialisieren\n& in DB speichern" as UC7
|
||||
}
|
||||
|
||||
package "Export / Serialisierung" {
|
||||
usecase "Rede als PDF exportieren" as UC8
|
||||
usecase "Rede als XML exportieren" as UC9
|
||||
usecase "Rede als XMI exportieren" as UC10
|
||||
}
|
||||
|
||||
package "Visualisierung & UI" {
|
||||
usecase "Reden durchsuchen" as UC11
|
||||
usecase "Rede anzeigen (HTML, NLP, Video)" as UC12
|
||||
usecase "POS / Sentiment / NER / Topics visualisieren" as UC13
|
||||
}
|
||||
|
||||
package "Datenbankoperationen" {
|
||||
usecase "Reden / Sessions / AgendaItems\nin MongoDB speichern" as UC14
|
||||
usecase "Metadaten zu Reden abfragen" as UC15
|
||||
usecase "Video-Referenzen zu Reden abfragen" as UC16
|
||||
}
|
||||
|
||||
package "Systemdienste" {
|
||||
usecase "Auf neue Protokolle automatisch prüfen und herunterladen" as UC17
|
||||
usecase "Neue NLP-Reden automatisch analysieren" as UC18
|
||||
}
|
||||
|
||||
' Verbindungen
|
||||
Admin--> UC1
|
||||
Admin--> UC2
|
||||
Admin--> UC3
|
||||
Admin--> UC4
|
||||
Admin--> UC5
|
||||
Admin--> UC6
|
||||
Admin--> UC7
|
||||
Admin--> UC8
|
||||
Admin--> UC9
|
||||
Admin--> UC10
|
||||
Nutzer--> UC8
|
||||
Nutzer--> UC9
|
||||
Nutzer--> UC10
|
||||
Nutzer --> UC11
|
||||
Nutzer --> UC12
|
||||
Nutzer --> UC13
|
||||
|
||||
UC6 --> UC7
|
||||
UC5 --> UC6
|
||||
UC2 --> UC14
|
||||
UC3 --> UC14
|
||||
UC4 --> UC14
|
||||
UC14 --> UC15
|
||||
UC14 --> UC16
|
||||
|
||||
UC12 --> UC13
|
||||
UC12 --> UC16
|
||||
|
||||
SystemScheduler --> UC17
|
||||
SystemScheduler --> UC18
|
||||
}
|
||||
@enduml
|
BIN
doc/class_diagram.pdf
Normal file
BIN
doc/class_diagram.pdf
Normal file
Binary file not shown.
BIN
doc/class_diagram.png
Normal file
BIN
doc/class_diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
3564
doc/class_diagram.tex
Normal file
3564
doc/class_diagram.tex
Normal file
File diff suppressed because it is too large
Load diff
BIN
doc/usecasediagram.png
Normal file
BIN
doc/usecasediagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 198 KiB |
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,7 @@ import org.texttechnologylab.project.gruppe_05_1.nlp.XmiExtractor;
|
|||
import org.texttechnologylab.project.gruppe_05_1.rest.RESTHandler;
|
||||
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
||||
import org.texttechnologylab.project.gruppe_05_1.util.PPRUtils;
|
||||
import org.texttechnologylab.project.gruppe_05_1.util.SpeechVideoUpdater;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.FileObjectFactory;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Session;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.SpeechParser;
|
||||
|
@ -43,6 +44,13 @@ public class Main {
|
|||
public static final String MEMBER_IMAGES_DIR = "src/main/resources/membersOfParliamentImages/";
|
||||
public static final String TEMP_EXPORT_DIR = "src/main/resources/tempExport/";
|
||||
|
||||
/**
|
||||
* Main Methode zum Start des Multimodalen Parlament Explorers
|
||||
* Programm-Flag Implementierung und DIR Konstanten von Jonas
|
||||
*
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
UPLOAD_MEMBER_PHOTOS = Arrays.asList(args).contains("uploadMemberPhotos");
|
||||
FORCE_UPLOAD_MEMBERS = Arrays.asList(args).contains("forceUploadMembers");
|
||||
|
@ -146,8 +154,9 @@ public class Main {
|
|||
|
||||
if (UPLOAD_MEMBER_PHOTOS) {
|
||||
Logger.pink("Uploading Member Photos to DB...");
|
||||
mongoDBHandler.uploadMemberPhotos();
|
||||
mongoDBHandler.uploadMemberPhotosFromResourceFolder();
|
||||
}
|
||||
SpeechVideoUpdater.init();
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
|
|
|
@ -4,11 +4,10 @@ import com.mongodb.MongoClientSettings;
|
|||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.bulk.BulkWriteResult;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.*;
|
||||
import com.mongodb.client.model.*;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.html.HtmlSpeech;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.nlp.Topic;
|
||||
import org.texttechnologylab.project.gruppe_05_1.exceptions.ServerErrorException;
|
||||
import org.texttechnologylab.project.gruppe_05_1.exceptions.SessionNotFoundException;
|
||||
import org.bson.Document;
|
||||
|
@ -31,6 +30,8 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import static com.mongodb.client.model.Filters.eq;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.Main.MEMBER_IMAGES_DIR;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.util.PPRUtils.fetchMemberImageBase64FromNameString;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.util.PPRUtils.getSessionCookies;
|
||||
|
||||
public class MongoDBHandler {
|
||||
|
||||
|
@ -57,7 +58,9 @@ public class MongoDBHandler {
|
|||
private MongoCollection<Document> memberPhotoCollection;
|
||||
private MongoCollection<Document> historyCollection;
|
||||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
*/
|
||||
public MongoDBHandler() {
|
||||
// Set loglevel for slf4j to avoid spam // TODO: Fix this (optional)
|
||||
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "error");
|
||||
|
@ -116,6 +119,7 @@ public class MongoDBHandler {
|
|||
/**
|
||||
* Get the MongoDB according to properties.
|
||||
* If a local server URI is defined, use it. Otherwise, use remote server.
|
||||
* Implementiert von Valentin
|
||||
* @return MongoDatabase
|
||||
*/
|
||||
static public MongoDatabase getMongoDatabase() {
|
||||
|
@ -176,6 +180,7 @@ public class MongoDBHandler {
|
|||
/**
|
||||
*
|
||||
* @return List<String> with the names of all collections
|
||||
* Implementiert von Valentin
|
||||
*/
|
||||
public Set<String> getCollectionNames() {
|
||||
// return getDatabase().listCollectionNames().into(new ArrayList<>());
|
||||
|
@ -186,6 +191,7 @@ public class MongoDBHandler {
|
|||
*
|
||||
* @param name Name of collection to check for existance
|
||||
* @return does the collection exist
|
||||
* Implementiert von Valentin
|
||||
*/
|
||||
public boolean collectionExists(String name) {
|
||||
return getDatabase().listCollectionNames().into(new ArrayList<>()).contains(name);
|
||||
|
@ -194,6 +200,7 @@ public class MongoDBHandler {
|
|||
|
||||
/**
|
||||
* Tries to create a collection. If the collection exists and contains documents, throw an exception
|
||||
* Implementiert von Valentin
|
||||
* @param database
|
||||
* @param collectionName
|
||||
*/
|
||||
|
@ -219,6 +226,7 @@ public class MongoDBHandler {
|
|||
|
||||
/**
|
||||
* Create Collection
|
||||
* Implementiert von Valentin
|
||||
* @param database
|
||||
* @param collectionName
|
||||
*/
|
||||
|
@ -237,6 +245,7 @@ public class MongoDBHandler {
|
|||
|
||||
/**
|
||||
* Creates a collection. If the collection exists already, delete all its document
|
||||
* Implementiert von Valentin
|
||||
* @param database
|
||||
* @param collectionName
|
||||
*/
|
||||
|
@ -252,7 +261,12 @@ public class MongoDBHandler {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param indexName
|
||||
* @param isAscending
|
||||
*/
|
||||
static public void createIndexForCollection(MongoCollection<Document> collection, String indexName, boolean isAscending) {
|
||||
// MongoDB creates automatically an index on "_id"
|
||||
if (indexName.equals(DEFAULT_ID_FIELD_NAME)) {
|
||||
|
@ -266,6 +280,12 @@ public class MongoDBHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param indexNames
|
||||
* @param isAscending
|
||||
*/
|
||||
static public void createIndexForCollection(MongoCollection<Document> collection, List<String> indexNames, boolean isAscending) {
|
||||
// MongoDB creates automatically an index on "_id"
|
||||
if (indexNames.contains(DEFAULT_ID_FIELD_NAME)) {
|
||||
|
@ -280,6 +300,9 @@ public class MongoDBHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
*/
|
||||
public void createIndicesForSpeakerCollection() {
|
||||
if (speakerCollection.listIndexes().into(new ArrayList<>()).size() == 1) {
|
||||
MongoDBHandler.createIndexForCollection(speakerCollection,"name", true);
|
||||
|
@ -288,10 +311,15 @@ public class MongoDBHandler {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
*/
|
||||
public void createIndicesForSpeechCollection() {
|
||||
if (speechesCollection.listIndexes().into(new ArrayList<>()).size() == 1) {
|
||||
MongoDBHandler.createIndexForCollection(speechesCollection, "speakerId", true);
|
||||
MongoDBHandler.createIndexForCollection(speechesCollection, "speechKey", true);
|
||||
MongoDBHandler.createIndexForCollection(speechesCollection, "dateTime", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,6 +329,7 @@ public class MongoDBHandler {
|
|||
|
||||
/**
|
||||
* Does a document with a given ID (for the "_id"-field) exists in a given collection?
|
||||
* Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param id
|
||||
* @return
|
||||
|
@ -314,6 +343,7 @@ public class MongoDBHandler {
|
|||
|
||||
/**
|
||||
* Find a document with a given ID (for the "_id"-field) in a given collection
|
||||
* Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param id
|
||||
* @return the document (null if not found)
|
||||
|
@ -325,7 +355,7 @@ public class MongoDBHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*Implementiert von Valentin
|
||||
* @param collection
|
||||
* @return count of documents in the collection
|
||||
*/
|
||||
|
@ -339,7 +369,7 @@ public class MongoDBHandler {
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
*Implementiert von Valentin
|
||||
* @param database
|
||||
* @param collectionName
|
||||
* @return count of documents in the collection
|
||||
|
@ -353,7 +383,7 @@ public class MongoDBHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*Implementiert von Valentin
|
||||
* @param database
|
||||
* @param collectionName
|
||||
*/
|
||||
|
@ -372,6 +402,7 @@ public class MongoDBHandler {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Creates a BSON document containing only simple fields according to fields given in a map
|
||||
* @param attributes
|
||||
* @return
|
||||
|
@ -390,6 +421,7 @@ public class MongoDBHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Creates a BSON document containing simple fields (attributes) as well as other (possibly nested) objects
|
||||
* @param attributes the simple fields
|
||||
* @param fields the (possibly nested) objects
|
||||
|
@ -418,6 +450,7 @@ public class MongoDBHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert ein Feldwert aks Double, auch wenn er in der Datenbank als Integer oder String steht
|
||||
* @param doc Mongo-Dokument
|
||||
* @param fieldName Feldname
|
||||
|
@ -439,7 +472,7 @@ public class MongoDBHandler {
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
*Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param doc
|
||||
* @return
|
||||
|
@ -449,7 +482,7 @@ public class MongoDBHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param docs
|
||||
* @return
|
||||
|
@ -459,7 +492,7 @@ public class MongoDBHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param fieldName
|
||||
* @param fieldValue
|
||||
|
@ -471,6 +504,7 @@ public class MongoDBHandler {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Searches a document and performs an update on it
|
||||
* The document to update must be matched by name and value of a certain field
|
||||
* @param collection
|
||||
|
@ -493,7 +527,7 @@ public class MongoDBHandler {
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
*Implementiert von Valentin
|
||||
* @param collection
|
||||
* @param searchCriteriaName search criteria: name of the field
|
||||
* @param searchCriteriaValue search criteria: value of the field
|
||||
|
@ -504,11 +538,12 @@ public class MongoDBHandler {
|
|||
collection.deleteOne(deleteQuery);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 +553,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 +579,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<Session> 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<AgendaItem> agendaItems) {
|
||||
List<Document> agendaItemDocuments = new ArrayList<>();
|
||||
for (AgendaItem agendaItem : agendaItems) {
|
||||
|
@ -555,7 +608,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<Session> sessions = retrieveAllSessions(Filters.eq("sessionId", sessionId));
|
||||
|
@ -579,6 +640,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<Speech> speeches) {
|
||||
// Convert each Speech to a Document
|
||||
List<Document> speechDocuments = new ArrayList<>();
|
||||
|
@ -629,7 +695,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<Speech> retrieveAllSpeeches() {
|
||||
List<Document> speeches = speechesCollection.find().into(new ArrayList<>());
|
||||
List<Speech> result = new ArrayList<>();
|
||||
|
@ -640,6 +710,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<Speech> retrieveAllSpeeches(Bson filter) {
|
||||
List<Document> speeches = speechesCollection.find(filter).into(new ArrayList<>());
|
||||
List<Speech> result = new ArrayList<>();
|
||||
|
@ -650,6 +727,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<Session> retrieveAllSessions() {
|
||||
List<Document> sessions = sessionsCollection.find().into(new ArrayList<>());
|
||||
List<Session> result = new ArrayList<>();
|
||||
|
@ -660,6 +742,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<Session> retrieveAllSessions(Bson filter) {
|
||||
List<Document> speeches = sessionsCollection.find(filter).into(new ArrayList<>());
|
||||
List<Session> result = new ArrayList<>();
|
||||
|
@ -670,6 +758,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<AgendaItem> retrieveAllAgendaItems() {
|
||||
List<Document> agendaItems = agendaItemsCollection.find().into(new ArrayList<>());
|
||||
List<AgendaItem> result = new ArrayList<>();
|
||||
|
@ -680,6 +773,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<AgendaItem> retrieveAllAgendaItems(Bson filter) {
|
||||
List<Document> speeches = agendaItemsCollection.find(filter).into(new ArrayList<>());
|
||||
List<AgendaItem> result = new ArrayList<>();
|
||||
|
@ -690,6 +789,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 +803,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 +813,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<WriteModel<Document>> bulkOperations) {
|
||||
if (!bulkOperations.isEmpty()) {
|
||||
BulkWriteOptions options = new BulkWriteOptions().ordered(false);
|
||||
|
@ -721,6 +835,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"));
|
||||
}
|
||||
|
@ -737,6 +856,12 @@ public class MongoDBHandler {
|
|||
return loadMemberImageFromFileByName(firstName, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt das Bild eines Mitglieds aus dem Ordner resources/membersOfParliamentImages anhand des Namens.
|
||||
* @param firstName Der Vorname des Mitglieds.
|
||||
* @return das Bild des Mitglieds als base64-String.
|
||||
* Implementiert von Jonas
|
||||
**/
|
||||
public String loadMemberImageFromFileByName(String firstName, String name) {
|
||||
// get the member photo from the resources/membersOfParliamentImages folder
|
||||
File photo = new File(MEMBER_IMAGES_DIR + name + "_" + firstName + ".jpg");
|
||||
|
@ -754,6 +879,12 @@ public class MongoDBHandler {
|
|||
return image_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt das Bild eines Mitglieds aus dem Ordner resources/membersOfParliamentImages anhand des Namens.
|
||||
* @param memberId Der Vorname des Mitglieds.
|
||||
* @param base64String Der base64-String des Bildes.
|
||||
* Implementiert von Jonas
|
||||
**/
|
||||
public void uploadMemberPhoto(String memberId, String base64String) {
|
||||
if (memberPhotoCollection.find(eq("memberId", memberId)).first() != null) {
|
||||
Logger.warn("Member photo for " + memberId + " already exists in the database. Overwriting...");
|
||||
|
@ -764,7 +895,41 @@ public class MongoDBHandler {
|
|||
memberPhotoCollection.insertOne(photoDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt die Bilder aller Mitglieder in die Datenbank.
|
||||
* Implementiert von Jonas
|
||||
**/
|
||||
public void uploadMemberPhotos() {
|
||||
// get a list of the string of first and last name of all members from the DB
|
||||
// only fetch the first and lastname
|
||||
List<Document> speakers = speakerCollection.find().projection(Projections.include("_id", "name", "firstName")).into(new ArrayList<>());
|
||||
|
||||
try {
|
||||
Logger.pink(getSessionCookies());
|
||||
} catch (IOException e) {
|
||||
Logger.error("Failed to get session cookies: " + e.getMessage());
|
||||
}
|
||||
|
||||
for (Document speaker : speakers) {
|
||||
String memberId = speaker.getString("_id");
|
||||
String name = speaker.getString("name");
|
||||
String firstName = speaker.getString("firstName");
|
||||
|
||||
try {
|
||||
String base64String = fetchMemberImageBase64FromNameString(firstName + " " + name);
|
||||
uploadMemberPhoto(memberId, base64String);
|
||||
Logger.debug("Uploaded member photo for " + firstName + " " + name);
|
||||
} catch (IOException e) {
|
||||
Logger.error("Failed to fetch member image for " + firstName + " " + name + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt die Bilder aller Mitglieder aus dem Ordner resources/membersOfParliamentImages in die Datenbank.
|
||||
* Implementiert von Jonas
|
||||
**/
|
||||
public void uploadMemberPhotosFromResourceFolder() {
|
||||
Logger.info("Found " + PPRUtils.listFilesInDirectory(MEMBER_IMAGES_DIR).size() + " member photos to upload.");
|
||||
// loop over file names in the directory
|
||||
// for each file name, extract the name of the member
|
||||
|
@ -781,6 +946,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);
|
||||
|
@ -795,8 +966,20 @@ 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class MongoObjectFactory {
|
|||
private static MongoObjectFactory factory = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*Gesamte File implementiert von Valentin
|
||||
* @return MongoObjectFactory
|
||||
*/
|
||||
public static MongoObjectFactory getFactory() {
|
||||
|
|
|
@ -4,6 +4,10 @@ import org.bson.Document;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @param <T>
|
||||
*/
|
||||
public interface MongoOperations<T> {
|
||||
MongoObjectFactory factory = MongoObjectFactory.getFactory();
|
||||
public Document createEntity(T entity);
|
||||
|
|
|
@ -57,11 +57,18 @@ public class MongoPprUtils {
|
|||
private static MongoCollection<Document> commentCollection = null;
|
||||
private static MongoCollection<Document> metadataCollection = null;
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @return
|
||||
*/
|
||||
public static MongoCollection<Document> getSpeakerCollection() {
|
||||
if (speakerCollection == null) speakerCollection = MongoDBHandler.getMongoDatabase().getCollection(SPEAKER_COLLECTION_NAME);
|
||||
return speakerCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @return
|
||||
*/
|
||||
public static MongoCollection<Document> getSpeechCollection() {
|
||||
if (speechCollection == null) speechCollection = MongoDBHandler.getMongoDatabase().getCollection(SPEECH_COLLECTION_NAME);
|
||||
return speechCollection;
|
||||
|
@ -82,12 +89,17 @@ public class MongoPprUtils {
|
|||
return picturesCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @return
|
||||
*/
|
||||
public static MongoCollection<Document> getMetadataCollection() {
|
||||
if (metadataCollection == null) metadataCollection = MongoDBHandler.getMongoDatabase().getCollection(METADATA_COLLECTION_NAME);
|
||||
return metadataCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Create the Speaker Collection and useful indices for it
|
||||
*/
|
||||
public static void createIndexForSpeakerCollection() {
|
||||
|
@ -98,6 +110,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Create the Speech Collection and useful indices for it
|
||||
*/
|
||||
public static void createIndexForSpeechCollection() {
|
||||
|
@ -107,6 +120,7 @@ public class MongoPprUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Truncate the Speaker Collection.
|
||||
* Note that it is quicker (and saves space) to drop and re-create rather than removing all documents using "remove({})"
|
||||
*/
|
||||
|
@ -123,6 +137,7 @@ public class MongoPprUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Holt alle Parlamentarier, die einen Suchkriterium erfüllen.
|
||||
* Das Suchkriterium wird auf allen Feldern angewandt: Vorname, Nachname, Partei.
|
||||
* Ist das Suchkriterium leer, werden alle Parlamentarier zurückgeliefert
|
||||
|
@ -161,6 +176,14 @@ public class MongoPprUtils {
|
|||
return plist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetched alle Parlamentarier, die einen Suchkriterium erfüllen.
|
||||
* Das Suchkriterium wird auf allen Feldern angewandt: Vorname, Nachname, Partei.
|
||||
* Ist das Suchkriterium leer, werden alle Parlamentarier zurückgeliefert
|
||||
* Implementiert von Jonas
|
||||
* @param ctx Session Context
|
||||
* @return List<Parlamentarier>
|
||||
*/
|
||||
public static List<Parlamentarier> getFilteredMembers(Context ctx) {
|
||||
// Get optional filter arguments
|
||||
String memberIdParam = ctx.queryParam("memberId");
|
||||
|
@ -229,6 +252,14 @@ public class MongoPprUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetched alle Parlamentarier aus der Datenbank, die einen Filter erfüllen
|
||||
* es wird nur die gegebene Projektion zurückgegeben
|
||||
* Implementiert von Jonas
|
||||
* @param filter Filter, der auf die Datenbank angewendet wird
|
||||
* @param projection Projektion, die auf die Datenbank angewendet wird
|
||||
* @return Liste von Parlamentariern
|
||||
**/
|
||||
public static List<Parlamentarier> retrieveAllMembersOfParliament(Bson filter, Bson projection) throws IOException {
|
||||
List<Document> speeches = getSpeakerCollection().find(filter).projection(projection).into(new ArrayList<>());
|
||||
List<Parlamentarier> result = new ArrayList<>();
|
||||
|
@ -246,6 +277,103 @@ public class MongoPprUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Hole alle Reden gefiltert nach den Form-Parameter
|
||||
* @param ctx Session Context, aus dem man alle Parameter abfragen kann
|
||||
* @return
|
||||
*/
|
||||
public static List<SpeechOverview> getFilteredSpeechesOverview(Context ctx) {
|
||||
|
||||
String name = ctx.queryParam("name");
|
||||
|
||||
String party = (!Objects.equals(ctx.queryParam("party"), "")) ? ctx.queryParam("party") : null;
|
||||
String topic = (!Objects.equals(ctx.queryParam("topic"), "")) ? ctx.queryParam("topic") : null;
|
||||
|
||||
|
||||
List<Bson> filters = new ArrayList<>();
|
||||
if (name != null) filters.add(Filters.regex("speakerName", ".*" + name + ".*", "i"));
|
||||
if (party != null) filters.add(Filters.regex("fraction", ".*" + party + ".*", "i"));
|
||||
|
||||
Bson filter;
|
||||
if (filters.isEmpty()) {
|
||||
filter = Filters.empty();
|
||||
} else {
|
||||
filter = Filters.and(filters);
|
||||
}
|
||||
|
||||
List<SpeechOverview> result = new ArrayList<>();
|
||||
|
||||
MongoCollection<Document> collection = getSpeechCollection();
|
||||
|
||||
Document projection = new Document("speechKey", 1)
|
||||
.append("speakerId", 1)
|
||||
.append("dateTimeString", 1)
|
||||
.append("speakerName", 1)
|
||||
.append("fraction", 1)
|
||||
.append("agendaTitel", 1);
|
||||
|
||||
List<Document> docs = collection.find(filter)
|
||||
.projection(projection)
|
||||
.sort(Sorts.descending("dateTime"))
|
||||
.into(new ArrayList<>());
|
||||
|
||||
for (Document doc : docs) {
|
||||
result.add(new SpeechOverview(
|
||||
doc.getString("speechKey"),
|
||||
doc.getInteger("speakerId"),
|
||||
doc.getString("dateTimeString"),
|
||||
doc.getString("speakerName"),
|
||||
doc.getString("fraction"),
|
||||
doc.getString("agendaTitel")
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Holt alle Reden eines Parlamentariers
|
||||
* @param speakerId
|
||||
* @return
|
||||
*/
|
||||
public static List<SpeechOverview> getSpeechesOverviewForSpeaker(Integer speakerId) {
|
||||
|
||||
List<SpeechOverview> result = new ArrayList<>();
|
||||
|
||||
MongoCollection<Document> collection = getSpeechCollection();
|
||||
|
||||
Document projection = new Document("speechKey", 1)
|
||||
.append("speakerId", 1)
|
||||
.append("dateTimeString", 1)
|
||||
.append("speakerName", 1)
|
||||
.append("fraction", 1)
|
||||
.append("agendaTitel", 1);
|
||||
|
||||
Bson filter = Filters.eq("speakerId", speakerId);
|
||||
|
||||
List<Document> docs = collection.find(filter)
|
||||
.projection(projection)
|
||||
.sort(Sorts.descending("dateTime"))
|
||||
.into(new ArrayList<>());
|
||||
|
||||
for (Document doc : docs) {
|
||||
result.add(new SpeechOverview(
|
||||
doc.getString("speechKey"),
|
||||
doc.getInteger("speakerId"),
|
||||
doc.getString("dateTimeString"),
|
||||
doc.getString("speakerName"),
|
||||
doc.getString("fraction"),
|
||||
doc.getString("agendaTitel")
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liest einen Parlamentarier von der MongoDB
|
||||
* @param doc - MongoDB Dokument eines Parlamentariers
|
||||
* @return Parlamentarier
|
||||
|
@ -298,8 +426,9 @@ public class MongoPprUtils {
|
|||
|
||||
/**
|
||||
* Holt einen Speaker aus der Datenbank
|
||||
* @param id
|
||||
* @return
|
||||
* Implementiert von Jonas
|
||||
* @param id ID des Parlamentariers
|
||||
* @return Speaker
|
||||
*/
|
||||
public static Speaker_MongoDB_Impl getSpeakerById(String id) {
|
||||
Logger.debug("ID: " + id);
|
||||
|
@ -312,6 +441,7 @@ public class MongoPprUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Holt die Details eines Parlamentariers
|
||||
* @param id Parlamentarier-ID (Integer)
|
||||
* @return ParlamentarierDetails
|
||||
|
@ -419,9 +549,9 @@ public class MongoPprUtils {
|
|||
|
||||
// Speech
|
||||
|
||||
// TODO: kopiere die Speech-Sachen von Übung 4 hierher!
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Aufzählen, wie viele Reden eines bestimmten Redners gespeichert sind
|
||||
* @param speakerId
|
||||
* @return Anzahl Reden
|
||||
|
@ -432,6 +562,7 @@ public class MongoPprUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert alle Reden eines Redners zurück
|
||||
* @param speakerId
|
||||
* @return Alle Reden eines Redners
|
||||
|
@ -450,6 +581,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert alle Reden zurück
|
||||
* Die Auswahl kann durch einen (textuellen) Filter eingeschränkt werden
|
||||
* @param filter
|
||||
|
@ -486,6 +618,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert Metadaten (aber keine Inhalte!) für alle Reden eines Redners zurück.
|
||||
* Als Metadaten zählen das Datum, Agenda-ID etc.
|
||||
* @param speakerId
|
||||
|
@ -529,6 +662,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert Metadaten (aber keine Inhalte!) für alle Reden zurück.
|
||||
* Die Auswahl kann durch einen (textuellen) Filter eingeschränkt werden
|
||||
* Als Metadaten zählen das Datum, Agenda-ID etc.
|
||||
|
@ -591,6 +725,7 @@ public class MongoPprUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Holt die Redeinformationen aus der Datenbank, die wichtig sind, um eine Liste der Reden in HTML darzustellen
|
||||
* @return
|
||||
*/
|
||||
|
@ -626,8 +761,48 @@ public class MongoPprUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Holt die Redeinformationen aus der Datenbank, die wichtig sind, um eine Liste der Reden eines Parlamentariers in HTML darzustellen
|
||||
* @param speakerId
|
||||
* @return
|
||||
*/
|
||||
public static List<SpeechOverview> getSpeechOverviewBySpeaker(Integer speakerId) {
|
||||
|
||||
List<SpeechOverview> result = new ArrayList<>();
|
||||
|
||||
MongoCollection<Document> collection = getSpeechCollection();
|
||||
|
||||
Document projection = new Document("speechKey", 1)
|
||||
.append("speakerId", 1)
|
||||
.append("dateTimeString", 1)
|
||||
.append("speakerName", 1)
|
||||
.append("fraction", 1)
|
||||
.append("agendaTitel", 1);
|
||||
|
||||
Bson filter = Filters.eq("speakerId", speakerId);
|
||||
|
||||
List<Document> docs = collection.find(filter)
|
||||
.projection(projection)
|
||||
.sort(Sorts.descending("dateTime"))
|
||||
.into(new ArrayList<>());
|
||||
|
||||
for (Document doc : docs) {
|
||||
result.add(new SpeechOverview(
|
||||
doc.getString("speechKey"),
|
||||
doc.getInteger("speakerId"),
|
||||
doc.getString("dateTimeString"),
|
||||
doc.getString("speakerName"),
|
||||
doc.getString("fraction"),
|
||||
doc.getString("agendaTitel")
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Füge Rede-Metadaten (welche in der Session-Collection stehen) der Rede hinzu.
|
||||
* Achtung: Redezeit ist in der Datenbank in unterschiedlichen Formaten vorhanden.
|
||||
* @param sessionId
|
||||
|
@ -653,6 +828,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert das Datum und die Uhrzeit einer Sitzung zurück
|
||||
* @param sessionId
|
||||
* @return
|
||||
|
@ -668,6 +844,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert den Agenda-Titel zurück
|
||||
* @param sessionId
|
||||
* @return
|
||||
|
@ -684,6 +861,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert die Rede-Informationen für die Anzeige einer Rede:
|
||||
* - die Rede-ID
|
||||
* - Name und Fraktion des Redners
|
||||
|
@ -702,6 +880,12 @@ public class MongoPprUtils {
|
|||
return new HtmlSpeech(speechDoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Jonas
|
||||
* Liefert die Rede-Informationen für die Anzeige einer Rede
|
||||
* @param key: Rede ID
|
||||
* @return Speech
|
||||
*/
|
||||
public static Speech getSpeechByKey(String key) {
|
||||
Document filter = new Document("speechKey", key);
|
||||
Document speechDoc = getSpeechCollection().find(filter).first();
|
||||
|
@ -734,6 +918,7 @@ public class MongoPprUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Aktualisiert (or erzeugt, falls nicht bereits vorhanden) diverse Metadaten:
|
||||
* - Die Liste der Parteien/Fraktionen, wie sie im Speaker-Collection stehen
|
||||
* - Die Liste der Parteien/Fraktionen, wie sie im Speech-Collection stehen (diese Listen sind recht unterschiedlich)
|
||||
|
@ -786,6 +971,11 @@ public class MongoPprUtils {
|
|||
Logger.info("Updating Metadata Collection: end");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @param speakerId
|
||||
* @return
|
||||
*/
|
||||
public static List<Speech> getSpeechesBySpeakerId(String speakerId) {
|
||||
List<Speech> speechIds = new ArrayList<>();
|
||||
Document filter = new Document("speakerId", Integer.parseInt(speakerId));
|
||||
|
@ -796,6 +986,10 @@ public class MongoPprUtils {
|
|||
return speechIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* @return
|
||||
*/
|
||||
public static List<Speech> getAllSpeeches() {
|
||||
List<Speech> speechIds = new ArrayList<>();
|
||||
Document filter = new Document();
|
||||
|
@ -806,6 +1000,12 @@ public class MongoPprUtils {
|
|||
return speechIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Jonas
|
||||
* Liefert alle Reden zurück, die ein bestimmtes Topic haben
|
||||
* @param topic Topic der Reden
|
||||
* @return Liste von Reden
|
||||
*/
|
||||
public static List<Speech> getAllSpeechesWithTopic(String topic) {
|
||||
List<Speech> speechIds = new ArrayList<>();
|
||||
Document filter = new Document("analysisResults.topics.topic", topic);
|
||||
|
@ -815,6 +1015,13 @@ public class MongoPprUtils {
|
|||
}
|
||||
return speechIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Jonas
|
||||
* Liefert eine Map der POS Einträge und deren Häufigkeit für eine Rede
|
||||
* @param speechId ID der Rede
|
||||
* @return Map<String, Integer> POS Einträge und deren Häufigkeit
|
||||
*/
|
||||
public static Map<String, Integer> getPOSInformationCardinalitiesForSpeechById(String speechId) {
|
||||
List<Token> tokens = getHtmlSpeechByKey(speechId).getNlp().getTokens();
|
||||
Map<String, Integer> posCounts = Token.countPOS(tokens);
|
||||
|
@ -826,6 +1033,12 @@ public class MongoPprUtils {
|
|||
return posCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Jonas
|
||||
* Liefert eine Map der Named Entities und deren Häufigkeit für eine Rede
|
||||
* @param speechId ID der Rede
|
||||
* @return Map<String, Integer> Named Entities und deren Häufigkeit
|
||||
*/
|
||||
public static Map<String, Integer> getNamedEntitiesInformationCardinalitiesForSpeechById(String speechId) {
|
||||
Map<String, Map<String, Integer>> namedEntitiesMapOfMaps = new HashMap<>();
|
||||
|
||||
|
@ -856,6 +1069,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert die Liste aller Parteien/Fraktionen, welche in der Liste der Parlamentarier stehen, zurück.
|
||||
* Diese Liste dient zur Filterung der Parlamentarier auf der entsprechenden Seite.
|
||||
* @return List<String> Liste aller Parteien/Fraktionen, welche in der Liste der Parlamentarier stehen
|
||||
|
@ -877,6 +1091,7 @@ public class MongoPprUtils {
|
|||
);
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert die Liste aller Parteien/Fraktionen, welche in der Liste der Reden stehen, zurück.
|
||||
* Diese Liste dient zur Filterung der Reden auf der entsprechenden Seite.
|
||||
* Da die Datenqualität dieses Feldes extrem schlecht ist, muss man hier etwas tricksen:
|
||||
|
@ -893,6 +1108,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Reichere die Rede-Dokumente um Informationen an:
|
||||
* - Datum und Uhrzeit der Rede (als DateTime und textuell): dateTimeString , dateTime
|
||||
* - Agenda-Titel: agendaTitel
|
||||
|
@ -958,6 +1174,7 @@ public class MongoPprUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Liefert die Liste aller Topics, zurück.
|
||||
* Diese Liste dient zur Filterung der Reden auf der entsprechenden Seite.
|
||||
* @return Liste aller Topics
|
||||
|
|
|
@ -4,7 +4,9 @@ import org.bson.Document;
|
|||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.AgendaItem_File_Impl;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.AgendaItem;
|
||||
|
||||
|
||||
/**
|
||||
* Datei implementiert von Henry
|
||||
*/
|
||||
public class AgendaItem_MongoDB_Impl extends AgendaItem_File_Impl implements AgendaItem {
|
||||
public AgendaItem_MongoDB_Impl(Document mongoDocument) {
|
||||
super(
|
||||
|
|
|
@ -11,6 +11,9 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class BiographicalInformation_MongoDB_Impl extends BiografischeAngaben implements MongoOperations<BiografischeAngaben> {
|
||||
@Override
|
||||
public Document createEntity(BiografischeAngaben entity) {
|
||||
|
|
|
@ -10,6 +10,9 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Institution_MongoDB_Impl extends Institution implements MongoOperations<Institution> {
|
||||
@Override
|
||||
public Document createEntity(Institution entity) {
|
||||
|
|
|
@ -11,6 +11,9 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class LegislativePeriod_MongoDB_Impl extends Wahlperiode implements MongoOperations<Wahlperiode> {
|
||||
@Override
|
||||
public Document createEntity(Wahlperiode entity) {
|
||||
|
|
|
@ -10,6 +10,9 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class MdbName_MongoDB_Impl extends MdbName implements MongoOperations<MdbName> {
|
||||
@Override
|
||||
public Document createEntity(MdbName entity) {
|
||||
|
|
|
@ -11,6 +11,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Mdb_MongoDB_Impl extends Mdb implements MongoOperations<Mdb> {
|
||||
@Override
|
||||
public Document createEntity(Mdb entity) {
|
||||
|
|
|
@ -10,6 +10,9 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Membership_MongoDB_Impl extends Membership implements MongoOperations<Membership> {
|
||||
@Override
|
||||
public Document createEntity(Membership entity) {
|
||||
|
|
|
@ -4,7 +4,9 @@ import org.bson.Document;
|
|||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Session_File_Impl;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Session;
|
||||
|
||||
|
||||
/**
|
||||
* Datei implementiert von Henry
|
||||
*/
|
||||
public class Session_MongoDB_Impl extends Session_File_Impl implements Session {
|
||||
|
||||
public Session_MongoDB_Impl(Document mongoDocument) {
|
||||
|
|
|
@ -17,6 +17,11 @@ import java.util.*;
|
|||
import static org.texttechnologylab.project.gruppe_05_1.Main.TEMP_EXPORT_DIR;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.getMemberPhoto;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* Datei modifiziert von Jonas
|
||||
* toTeX() und toXML() hinzugefügt von Jonas
|
||||
*/
|
||||
public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations<Speaker> {
|
||||
public Speaker_MongoDB_Impl createSpeakerMongoDBImpl(Document mongoDocument) {
|
||||
this.setId(mongoDocument.getString("_id"));
|
||||
|
|
|
@ -19,6 +19,11 @@ import java.util.List;
|
|||
import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.getAgendaTitle;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.getSessionDateTime;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Henry
|
||||
* Modifiziert von Jonas
|
||||
* toTeX und toXML von Jonas
|
||||
*/
|
||||
public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech {
|
||||
public Speech_MongoDB_Impl(Document mongoDocument, boolean includeContent) {
|
||||
super(
|
||||
|
@ -50,29 +55,41 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den vollständigen Text der Rede zurück, indem alle Zeilen- und Kommentarinhalte
|
||||
* zusammengesetzt werden. Inhalte vom Typ "speaker" werden dabei ignoriert.
|
||||
*
|
||||
* @return Der vollständige Redetext als String
|
||||
*/
|
||||
public String getFullText() {
|
||||
StringBuilder fullText = new StringBuilder();
|
||||
// Iteriere über alle Inhalte, die bereits in der Rede gespeichert wurden.
|
||||
|
||||
for (Object content : this.getSpeechContents()) {
|
||||
if (content instanceof Line_MongoDB_Impl) {
|
||||
// Wir gehen davon aus, dass Line_MongoDB_Impl eine Methode getContent() hat, die den Text zurückgibt.
|
||||
|
||||
String lineText = ((Line_MongoDB_Impl) content).getContent();
|
||||
if (lineText != null && !lineText.isEmpty()) {
|
||||
fullText.append(lineText).append("\n");
|
||||
}
|
||||
} else if (content instanceof Comment_MongoDB_Impl) {
|
||||
// Wir gehen davon aus, dass Comment_MongoDB_Impl eine Methode getComment() hat, die den Kommentartext liefert.
|
||||
|
||||
String commentText = ((Comment_MongoDB_Impl) content).getComment();
|
||||
if (commentText != null && !commentText.isEmpty()) {
|
||||
fullText.append(commentText).append("\n");
|
||||
}
|
||||
}
|
||||
// Inhalte vom Typ "speaker" werden ignoriert.
|
||||
|
||||
}
|
||||
return fullText.toString().trim();
|
||||
}
|
||||
|
||||
//TODO not going fuckin insane
|
||||
/**
|
||||
* Wandelt die aktuelle Rede in ein JCas-Objekt um, um sie z. B. für NLP-Verarbeitung
|
||||
* weiterzuverwenden.
|
||||
*
|
||||
* @return JCas mit dem Redetext und der speechKey als Metadaten
|
||||
* @throws UIMAException falls ein Fehler bei der Erstellung des JCas auftritt
|
||||
*/
|
||||
public JCas toCas() throws UIMAException {
|
||||
JCas jCas = JCasFactory.createJCas();
|
||||
jCas.setDocumentText(this.getFullText());
|
||||
|
@ -82,6 +99,11 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech {
|
|||
return jCas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exportiert die Rede im LaTeX-Format inkl. Platzhalter für Sprecher- und NLP-Informationen.
|
||||
*
|
||||
* @return LaTeX-Darstellung der Rede
|
||||
*/
|
||||
public String toTeX() {
|
||||
StringBuilder tex = new StringBuilder();
|
||||
|
||||
|
@ -117,6 +139,12 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech {
|
|||
return tex.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wandelt die Rede in ein XML-Element um, das in ein vollständiges XML-Dokument eingefügt werden kann.
|
||||
*
|
||||
* @param doc das übergeordnete XML-Dokument
|
||||
* @return das XML-Element, das die Rede darstellt
|
||||
*/
|
||||
public Element toXML(org.w3c.dom.Document doc) {
|
||||
Element speech = doc.createElement("speech");
|
||||
speech.setAttribute("sessionId", String.valueOf(this.getSessionId()));
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Comment_File
|
|||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Comment;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/*
|
||||
* Klassen-Implementieren von Jonas
|
||||
*/
|
||||
public class Comment_MongoDB_Impl extends Comment_File_Impl implements Comment {
|
||||
|
||||
public Comment_MongoDB_Impl(Document mongoDocument) {
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Line_File_Im
|
|||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Line;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/*
|
||||
* Klassen-Implementieren von Jonas
|
||||
*/
|
||||
public class Line_MongoDB_Impl extends Line_File_Impl implements Line {
|
||||
public Line_MongoDB_Impl(Document mongoDocument) {
|
||||
super(
|
||||
|
|
|
@ -5,6 +5,9 @@ import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Speaker_File
|
|||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speaker;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/*
|
||||
* Klassen-Implementieren von Jonas
|
||||
*/
|
||||
public class Speaker_MongoDB_Impl extends Speaker_File_Impl implements Speaker {
|
||||
public Speaker_MongoDB_Impl(Document mongoDocument) {
|
||||
super(
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.domain;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public enum Gender { // TODO: Delete
|
||||
|
||||
M("männlich"),
|
||||
|
|
|
@ -10,6 +10,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public class HtmlSpeech {
|
||||
String speechKey;
|
||||
|
@ -19,6 +22,8 @@ public class HtmlSpeech {
|
|||
String agendaTitle; // aus "agendaItems" Collection
|
||||
List<SpeechContent> content = new ArrayList<>();
|
||||
NlpInfo nlp = null;
|
||||
String video = null;
|
||||
String videoData;
|
||||
|
||||
public HtmlSpeech() {
|
||||
}
|
||||
|
@ -27,7 +32,7 @@ public class HtmlSpeech {
|
|||
setSpeechKey(doc.getString("speechKey"));
|
||||
setSpeakerName(doc.getString("speakerName"));
|
||||
setFraction(doc.getString("fraction"));
|
||||
|
||||
setVideo(doc.getString("video"));
|
||||
List<Document> contentDocList = doc.get("speechContents", MongoDBHandler.DOC_LIST_CLASS);
|
||||
if (contentDocList == null) {
|
||||
setContent(new ArrayList<>());
|
||||
|
@ -51,13 +56,13 @@ public class HtmlSpeech {
|
|||
// Ergänzung um NLP-Informationen
|
||||
Document nlpDoc = (Document) doc.get("analysisResults");
|
||||
nlp = readNlpInfo(nlpDoc);
|
||||
|
||||
}
|
||||
|
||||
private NlpInfo readNlpInfo(Document nlpDoc) {
|
||||
if (nlpDoc == null) return null;
|
||||
NlpInfo nlp = new NlpInfo();
|
||||
|
||||
// TODO: HERE
|
||||
List<Document> tokensDocs = nlpDoc.get("tokens", MongoDBHandler.DOC_LIST_CLASS);
|
||||
nlp.setTokens(Token.readTokensFromMongo(tokensDocs));
|
||||
|
||||
|
@ -74,7 +79,6 @@ public class HtmlSpeech {
|
|||
List<Document> topicsDocs = nlpDoc.get("topics", MongoDBHandler.DOC_LIST_CLASS);
|
||||
nlp.setTopics(Topic.readTopicsFromMongo(topicsDocs));
|
||||
|
||||
// TODO: Video
|
||||
|
||||
return nlp;
|
||||
}
|
||||
|
@ -157,4 +161,20 @@ public class HtmlSpeech {
|
|||
.add("nlp=" + nlp)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public void setVideo(String video) {
|
||||
this.video = video;
|
||||
}
|
||||
|
||||
public void setVideoData(String videoData) {
|
||||
this.videoData = videoData;
|
||||
}
|
||||
|
||||
public String getVideo() {
|
||||
return video;
|
||||
}
|
||||
|
||||
public String getVideoData() {
|
||||
return videoData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.html;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Parlamentarier {
|
||||
String id;
|
||||
String vorname;
|
||||
|
|
|
@ -8,7 +8,9 @@ import java.time.LocalDate;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class ParlamentarierDetails {
|
||||
String id;
|
||||
String vorname;
|
||||
|
|
|
@ -2,6 +2,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.html;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public class SpeechOverview {
|
||||
String speechKey;
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.mdb;
|
|||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public abstract class BiografischeAngaben {
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.mdb;
|
|||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public abstract class Institution {
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.domain.mdb;
|
||||
|
||||
public enum Mandatsart {
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
DIREKT("Direktwahl"),
|
||||
LANDESLISTE("Landesliste"),
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.mdb;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public abstract class Mdb {
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.mdb;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public abstract class MdbDocument {
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.mdb;
|
|||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public abstract class MdbName {
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ import java.time.LocalDate;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public abstract class Wahlperiode {
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.nlp;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class AudioToken {
|
||||
|
||||
private int begin;
|
||||
|
|
|
@ -2,7 +2,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.nlp;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Dependency {
|
||||
String type;
|
||||
String governor;
|
||||
|
|
|
@ -7,7 +7,10 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* toXML implementiert von Jonas
|
||||
*/
|
||||
public class NamedEntity {
|
||||
String type; // PER, LOC etc.
|
||||
String text;
|
||||
|
|
|
@ -4,7 +4,9 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class NlpInfo {
|
||||
List<Token> tokens;
|
||||
List<Sentence> sentences;
|
||||
|
|
|
@ -4,7 +4,10 @@ import org.w3c.dom.Element;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* toXML implementiert von Jonas
|
||||
*/
|
||||
public class Pos {
|
||||
String posValue; // ART, NN...
|
||||
String coarseValue; // PROPN...
|
||||
|
|
|
@ -2,10 +2,10 @@ package org.texttechnologylab.project.gruppe_05_1.domain.nlp;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Sentence {
|
||||
// int begin; // TODO: momentan nicht in MongoDB
|
||||
// int end; // TODO: momentan nicht in MongoDB
|
||||
String text;
|
||||
|
||||
public Sentence() {
|
||||
|
|
|
@ -8,7 +8,10 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* toXML-Methode implementiert von Jonas
|
||||
*/
|
||||
public class Sentiment {
|
||||
int begin;
|
||||
int end;
|
||||
|
|
|
@ -3,7 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.nlp;
|
|||
import org.bson.Document;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Token {
|
||||
String text;
|
||||
String pos;
|
||||
|
@ -67,6 +69,7 @@ public class Token {
|
|||
* Die Token-Dokumente (Speech --> analysisResults --> token) aus der MongoDB lesen
|
||||
* @param tokenDocs Eine Liste von Mongo-Dokumenten
|
||||
* @return Eine Liste der Token
|
||||
* Implementiert von Leon
|
||||
*/
|
||||
public static List<Token> readTokensFromMongo(List<Document> tokenDocs) {
|
||||
List<Token> tokens = new ArrayList<>();
|
||||
|
@ -83,6 +86,7 @@ public class Token {
|
|||
* Zählt alle verschiedenen POS Vorkommen auf
|
||||
* @param tokenList
|
||||
* @return Jede POS art mit ihrer Anzahl an Vorkommen
|
||||
* Implementiert von Leon
|
||||
*/
|
||||
public static Map<String, Integer> countPOS(List<Token> tokenList) {
|
||||
Map<String, Integer> posCounts = new HashMap<>();
|
||||
|
|
|
@ -5,7 +5,10 @@ import org.w3c.dom.Element;
|
|||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* toXML-Methode implementiert von Jonas
|
||||
*/
|
||||
public class Topic {
|
||||
String topic;
|
||||
Double score;
|
||||
|
|
|
@ -3,7 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.nlp;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class VideoInformation {
|
||||
List<AudioToken> audioTokens;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.texttechnologylab.project.gruppe_05_1.domain.nlp.html;
|
|||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* Diese Klasse ordnet das entspreche Sentiment zu einem Satz zu.
|
||||
* Sie ist ein Datencontainer für die Darstellung über FreeMarker
|
||||
*/
|
||||
|
|
|
@ -3,12 +3,14 @@ package org.texttechnologylab.project.gruppe_05_1.domain.speaker;
|
|||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class Membership {
|
||||
String role;
|
||||
String member; // TODO: wozu? Dr. Abrami hat hier die ID des Parlamentariers gespeichert
|
||||
LocalDate begin; // TODO: in Mongo eigentlich Date?
|
||||
LocalDate end; // TODO: in Mongo eigentlich Date?
|
||||
String member;
|
||||
LocalDate begin;
|
||||
LocalDate end;
|
||||
String label;
|
||||
Integer wp;
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ import java.time.LocalDate;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public abstract class Speaker {
|
||||
String id;
|
||||
String name;
|
||||
|
@ -23,9 +25,6 @@ public abstract class Speaker {
|
|||
String primaryFoto;
|
||||
List<Membership> memberships;
|
||||
|
||||
// TODO: List<Speech> speeches;
|
||||
|
||||
// TODO: Photos
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
|
|
|
@ -2,7 +2,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.speech;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public abstract class Agenda {
|
||||
String index;
|
||||
String id;
|
||||
|
|
|
@ -4,7 +4,9 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public abstract class Comment {
|
||||
|
||||
String id;
|
||||
|
|
|
@ -4,7 +4,9 @@ import java.time.LocalDate;
|
|||
import java.time.LocalTime;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public abstract class Protocol {
|
||||
LocalDate date;
|
||||
LocalTime startTime;
|
||||
|
|
|
@ -3,7 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.speech;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public abstract class Speech {
|
||||
String id;
|
||||
String text;
|
||||
|
|
|
@ -5,16 +5,17 @@ import java.util.Objects;
|
|||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* Diese Klasse dient der Darstellung aller Reden eines Parlamentariers.
|
||||
*/
|
||||
public class SpeechMetaData {
|
||||
// aus "speech" Collection
|
||||
String speechKey; // z.B. "ID2011400300"
|
||||
int speechId; // TODO: nötig?
|
||||
int speechId;
|
||||
int speakerId;
|
||||
String speakerName;
|
||||
String fraktion;
|
||||
int sessionId; // TODO: nötig?
|
||||
int sessionId;
|
||||
|
||||
// aus "sessions" Collection
|
||||
LocalDateTime dateTime;
|
||||
|
|
|
@ -2,7 +2,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.speech;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public abstract class TextContent {
|
||||
String id;
|
||||
String speakerId;
|
||||
|
|
|
@ -24,6 +24,10 @@ import static org.texttechnologylab.project.gruppe_05_1.Main.RESOURCES_DIR;
|
|||
import static org.texttechnologylab.project.gruppe_05_1.Main.TEMP_EXPORT_DIR;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.*;
|
||||
|
||||
/**
|
||||
* Utility Klasse für die Erstellung von TeX-Dateien und Konvertierung in Base64-kodierte PDF-Dateien.
|
||||
* Implementiert von Jonas
|
||||
*/
|
||||
public class TeXUtil {
|
||||
private static final String PREAMBLE = readFileContentFromTeXDir();
|
||||
private static final String BEGIN_DOCUMENT = "\\begin{document}\n";
|
||||
|
|
|
@ -19,6 +19,10 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||
|
||||
import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.*;
|
||||
|
||||
/**
|
||||
* Utility Klasse für die Erstellung von XML-Dateien und Konvertierung in Base64-kodierte PDF-Dateien.
|
||||
* Implementiert von Jonas
|
||||
*/
|
||||
public class XMLUtil {
|
||||
public static String documentToString(Document doc) {
|
||||
try {
|
||||
|
|
|
@ -48,9 +48,10 @@ public class NlpUtils {
|
|||
private static final String TYPE_SYSTEM_DESCRIPTOR_PATH = "/speeches/TypeSystem.xml.gz";
|
||||
private static final int MAX_FEATURE_LENGTH = 10000;
|
||||
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public static void createNlpData() {
|
||||
// Source: Dr. Abrami - Beispiel TODO
|
||||
duuiInit();
|
||||
runDockerDriver();
|
||||
try {
|
||||
|
@ -68,6 +69,9 @@ public class NlpUtils {
|
|||
createSentimentInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
private static void duuiInit() {
|
||||
|
||||
DUUILuaContext ctx;
|
||||
|
@ -116,6 +120,7 @@ public class NlpUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
* Initialization of a sample CAS document
|
||||
* @return JCas object
|
||||
*/
|
||||
|
@ -143,7 +148,9 @@ public class NlpUtils {
|
|||
return pCas;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public static void runDockerDriver() {
|
||||
|
||||
// reset existing pipeline-components
|
||||
|
@ -188,7 +195,9 @@ public class NlpUtils {
|
|||
Logger.info(JCasUtil.selectCovered(org.hucompute.textimager.uima.type.Sentiment.class, sentence).toString());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
private static void casInit() {
|
||||
JCas jcas;
|
||||
try {
|
||||
|
@ -242,6 +251,7 @@ public class NlpUtils {
|
|||
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
* Execution of video processing via DUUI using the RemoteDriver
|
||||
* @throws Exception in case of an error
|
||||
*/
|
||||
|
@ -315,6 +325,15 @@ public class NlpUtils {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt den Remote-NLP-Driver auf unprozessierten Reden aus und aktualisiert die Datenbank.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @throws Exception falls ein Fehler auftritt.
|
||||
*/
|
||||
public static void runRemoteDriver() throws Exception {
|
||||
DUUILuaContext luaContext = new DUUILuaContext().withJsonLibrary();
|
||||
pComposer = new DUUIComposer()
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.mongodb.client.model.WriteModel;
|
|||
import org.apache.uima.fit.util.JCasUtil;
|
||||
import org.bson.Document;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -24,7 +23,12 @@ import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
|||
|
||||
import static org.texttechnologylab.project.gruppe_05_1.Main.JCAS_SPEECHES_TYPESYSTEM_DIR;
|
||||
|
||||
|
||||
/**
|
||||
* Extrahiert NLP‑Analyseergebnisse aus komprimierten XMI‑Dateien und lädt sie batchweise in MongoDB hoch.
|
||||
* Liest .xmi.gz Dateien aus einem ZIP‑Archiv, erstellt für jede Rede ein "analysisResults" Dokument und führt Bulk‑Writes durch.
|
||||
* Implementiert von Leon
|
||||
* Modifiziert von Henry
|
||||
*/
|
||||
public class XmiExtractor {
|
||||
|
||||
private final List<WriteModel<Document>> bulkOperations = Collections.synchronizedList(new ArrayList<>());
|
||||
|
@ -36,6 +40,13 @@ public class XmiExtractor {
|
|||
mongoDBHandler = new MongoDBHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Liest alle .xmi.gz Dateien aus dem ZIP‑Archiv "speeches/20.zip", extrahiert deren NLP‑Daten
|
||||
* und lädt sie in Form von BATCH_SIZE Dokumenten in MongoDB hoch.
|
||||
* @throws IOException falls die ZIP‑Datei nicht gefunden oder ein Lese-/Schreibfehler auftritt
|
||||
* Implementiert von Leon
|
||||
* Modifiziert von Henry
|
||||
*/
|
||||
public void extractAndUploadXmiData() throws IOException {
|
||||
InputStream resourceStream = getClass().getClassLoader().getResourceAsStream("speeches/20.zip");
|
||||
if (resourceStream == null) {
|
||||
|
@ -85,6 +96,13 @@ public class XmiExtractor {
|
|||
mongoDBHandler.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Liest ein komprimiertes XMI ein und erstellt Bulk‑Update‑Operationen für MongoDB.
|
||||
* @param inputStream komprimierter XMI‑InputStream
|
||||
* @param filename Name der Datei im ZIP‑Archiv (für speechKey)
|
||||
* Implementiert von Leon
|
||||
* Modifiziert von Henry
|
||||
*/
|
||||
private void processXmiGzStream(InputStream inputStream, String filename) {
|
||||
JCas jCas = null;
|
||||
try (GZIPInputStream gis = new GZIPInputStream(inputStream)) {
|
||||
|
@ -181,11 +199,21 @@ public class XmiExtractor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrahiert aus dem Dateinamen (z.B. "20/ABC123.xmi.gz") den speechKey.
|
||||
* @param filename Name der Datei innerhalb des ZIP‑Archivs
|
||||
* @return speechKey oder null, wenn das Format nicht erkannt wird
|
||||
* Implementiert von Leon
|
||||
*/
|
||||
private static String extractSpeechKeyFromFilename(String filename) {
|
||||
String baseName = filename.replace(".xmi.gz", "");
|
||||
return baseName.replace("20/", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt alle gesammelten BulkWrite-Operationen in MongoDB aus und leert den Batch.
|
||||
* Implementiert von Henry
|
||||
*/
|
||||
private synchronized void flushBatch() {
|
||||
if (!bulkOperations.isEmpty()) {
|
||||
mongoDBHandler.bulkWriteNlpData(bulkOperations);
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.rest;
|
||||
|
||||
import gnu.trove.impl.sync.TSynchronizedShortObjectMap;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.openapi.*;
|
||||
import org.apache.commons.collections.bag.SynchronizedSortedBag;
|
||||
import org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.html.HtmlSpeech;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.html.Parlamentarier;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.html.ParlamentarierDetails;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.nlp.Sentiment;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.nlp.Token;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.nlp.Topic;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.speech.SpeechMetaData;
|
||||
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
||||
import org.texttechnologylab.project.gruppe_05_1.util.PPRUtils;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech;
|
||||
import com.mongodb.client.model.Aggregates;
|
||||
import com.mongodb.client.model.Accumulators;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.model.Projections;
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.texttechnologylab.project.gruppe_05_1.util.PPRUtils.listFractionsFromMembers;
|
||||
|
||||
/**
|
||||
* Controller für die Frontend‑Routen.
|
||||
* Größtenteils implementiert von Jonas
|
||||
*/
|
||||
public class FrontEndController {
|
||||
@OpenApi(
|
||||
summary = "Get the homepage.",
|
||||
|
@ -39,6 +42,20 @@ public class FrontEndController {
|
|||
ctx.render("home.ftl");
|
||||
}
|
||||
|
||||
@OpenApi(
|
||||
summary = "Get the about page.",
|
||||
description = "Get the about",
|
||||
operationId = "getAbout",
|
||||
path = "/about",
|
||||
methods = HttpMethod.GET,
|
||||
tags = {"About"},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200")
|
||||
})
|
||||
public static void getAbout(Context ctx) {
|
||||
ctx.render("about.ftl");
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: getAllParlamentarier gibt es hier UND im ParlamentarierController (etwas unterschiedliche Implementierungen)
|
||||
--> konsolidieren!
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.io.InputStream;
|
|||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* Diese Klasse dient der Konfiguruerung von Javalin
|
||||
*/
|
||||
public class JavalinConfig extends Properties {
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* Dieser Kontroller zeigt Informationen um den Parlamentariern:
|
||||
* 1. Die Einstiegsseite: eine Filter-fähige Auflistung der Parlamentariern.
|
||||
* Angezeigt werden Vor- und Nachname, Partei sowie ID.
|
||||
|
|
|
@ -15,6 +15,9 @@ import java.io.IOException;
|
|||
import static org.texttechnologylab.project.gruppe_05_1.Main.JAVALIN_STATIC_FILES_DIR;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.Main.JAVALIN_TEMPLATE_DIR;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public class RESTHandler {
|
||||
public void startJavalin() {
|
||||
|
||||
|
@ -66,8 +69,14 @@ public class RESTHandler {
|
|||
app.get("/reden/{id}", SpeechController::listSpeeches); // zeige Reden eines Parlamentariers an
|
||||
app.get("/reden/{id}/{redeId}", SpeechController::showSpeech); // zeige eine bestimmte Rede des Parlamentariers an
|
||||
|
||||
|
||||
app.get("/reden", SpeechController::listAllSpeeches); // zeige alle Reden an (Filtern möglich)
|
||||
|
||||
// Charts
|
||||
app.get("/charts", FrontEndController::getCharts);
|
||||
|
||||
app.get("/about", FrontEndController::getAbout);
|
||||
|
||||
app.get("/export/pdf/speech/{id}", SpeechesLatexExportController::exportSpeech); // exportiere eine Rede als PDF
|
||||
app.get("/export/pdf/speech", SpeechesLatexExportController::exportSpeech); // exportiere eine Rede als PDF
|
||||
app.get("/export/pdf/speaker/{id}", SpeechesLatexExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.rest;
|
||||
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.http.staticfiles.Location;
|
||||
import io.javalin.openapi.plugin.OpenApiPlugin;
|
||||
import io.javalin.openapi.plugin.redoc.ReDocPlugin;
|
||||
import io.javalin.rendering.template.JavalinFreemarker;
|
||||
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.texttechnologylab.project.gruppe_05_1.Main.JAVALIN_STATIC_FILES_DIR;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.Main.JAVALIN_TEMPLATE_DIR;
|
||||
|
||||
public class RESTHandlerOld {
|
||||
|
||||
public void startJavalin() {
|
||||
|
||||
// Javalin Konfiguration (z.B. port)
|
||||
JavalinConfig jlConfig = new JavalinConfig();
|
||||
int port = jlConfig.getPort();
|
||||
|
||||
// FreeMarker Konfiguration
|
||||
Configuration fmConfig = new Configuration(Configuration.VERSION_2_3_33);
|
||||
fmConfig.setDefaultEncoding("UTF-8");
|
||||
try {
|
||||
fmConfig.setDirectoryForTemplateLoading(new File(JAVALIN_TEMPLATE_DIR));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
fmConfig.setLogTemplateExceptions(true);
|
||||
fmConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
|
||||
// Erzeuge die Javalin app
|
||||
Javalin app = Javalin.create(config -> {
|
||||
config.staticFiles.add(JAVALIN_STATIC_FILES_DIR, Location.EXTERNAL); // momentan nicht benutzt
|
||||
|
||||
config.fileRenderer(new JavalinFreemarker(fmConfig));
|
||||
|
||||
config.registerPlugin(new OpenApiPlugin(pluginConfig -> {
|
||||
// Define OpenAPI spec configuration
|
||||
pluginConfig.withDefinitionConfiguration((version, definition) -> {
|
||||
definition.withOpenApiInfo(info -> info.setTitle("Javalin OpenAPI Documentation"));
|
||||
});
|
||||
}));
|
||||
|
||||
config.registerPlugin(new ReDocPlugin());
|
||||
|
||||
})
|
||||
.start(port);
|
||||
Logger.info("Javalin app started on http://localhost:" + port);
|
||||
|
||||
// Routes
|
||||
// ======
|
||||
|
||||
// Parlamentarier
|
||||
app.get("/", ParlamentarierController::getAllParlamentarier);
|
||||
app.get("/portfolio/{id}", ParlamentarierController::getParlamentarierDetails);
|
||||
|
||||
// Reden
|
||||
app.get("/reden/{id}", SpeechController::listSpeeches); // zeige Reden eines Parlamentariers an
|
||||
app.get("/reden/{id}/{redeId}", SpeechController::showSpeech); // zeige eine bestimmte Rede des Parlamentariers an
|
||||
|
||||
}
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.rest;
|
||||
|
||||
import com.mongodb.client.gridfs.GridFSBucket;
|
||||
import com.mongodb.client.gridfs.GridFSBuckets;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.openapi.*;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.texttechnologylab.project.gruppe_05_1.database.MongoDBHandler;
|
||||
import org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.html.HtmlSpeech;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.html.ParlamentarierDetails;
|
||||
|
@ -14,11 +18,13 @@ import org.texttechnologylab.project.gruppe_05_1.domain.speech.SpeechMetaData;
|
|||
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SpeechController {
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* Liste alle Reden eines Parlamentariers an
|
||||
* @param ctx Javalin Context
|
||||
*/
|
||||
|
@ -39,8 +45,7 @@ public class SpeechController {
|
|||
String parlamentarierId = ctx.pathParam("id");
|
||||
|
||||
ParlamentarierDetails p = MongoPprUtils.getParlamentarierDetailsByID(parlamentarierId);
|
||||
List<SpeechMetaData> speechMetaDataList = MongoPprUtils.getSpeechesMetadataForSpeaker(parlamentarierId);
|
||||
|
||||
List<SpeechOverview> speechMetaDataList = MongoPprUtils.getSpeechesOverviewForSpeaker(Integer.parseInt(parlamentarierId));
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("p", p);
|
||||
attributes.put("speechesMetaDataList", speechMetaDataList);
|
||||
|
@ -50,6 +55,8 @@ public class SpeechController {
|
|||
/**
|
||||
* Zeige eine bestimmte Rede des Parlamentariers an
|
||||
* @param ctx Javalin Context
|
||||
* Implementiert von Valentin
|
||||
* Modifiziert von Leon
|
||||
*/
|
||||
@OpenApi(
|
||||
summary = "Zeige eine bestimmte Rede des Parlamentariers an",
|
||||
|
@ -79,6 +86,24 @@ public class SpeechController {
|
|||
}
|
||||
attributes.put("s", speech);
|
||||
|
||||
|
||||
if (speech.getVideo() != null && !speech.getVideo().trim().isEmpty()) {
|
||||
MongoDBHandler mongoDBHandler = new MongoDBHandler();
|
||||
try {
|
||||
GridFSBucket gridFSBucket = GridFSBuckets.create(mongoDBHandler.getDatabase(), "videos");
|
||||
ObjectId fileId = new ObjectId(speech.getVideo());
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
gridFSBucket.downloadToStream(fileId, baos);
|
||||
byte[] videoBytes = baos.toByteArray();
|
||||
String base64Video = Base64.getEncoder().encodeToString(videoBytes);
|
||||
speech.setVideoData(base64Video);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error fetching video from GridFS: " + e.getMessage());
|
||||
} finally {
|
||||
mongoDBHandler.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Foto des Abgeordnetes
|
||||
String picture = MongoPprUtils.getParlamentarierPictureByID(parlamentarierId);
|
||||
attributes.put("picture", picture);
|
||||
|
@ -105,7 +130,7 @@ public class SpeechController {
|
|||
Map<String, Integer> posCounts = Token.countPOS(tokens);
|
||||
|
||||
List<Token> posList = posCounts.entrySet().stream()
|
||||
.map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), "")) // Lemma remains empty
|
||||
.map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), ""))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Logger.debug("Sending POS List to NLP - " + posList);
|
||||
|
@ -114,7 +139,7 @@ public class SpeechController {
|
|||
|
||||
} else {
|
||||
Logger.debug("POS List is EMPTY");
|
||||
speech.getNlp().setPosList((List) new ArrayList<Token>()); // Ensure it's never null
|
||||
speech.getNlp().setPosList((List) new ArrayList<Token>());
|
||||
}
|
||||
|
||||
// NLP: Named Entities
|
||||
|
@ -151,10 +176,8 @@ public class SpeechController {
|
|||
attributes.put("na_info", null);
|
||||
}
|
||||
|
||||
// TODO: Token wird momentan etwas komisch abgespeichert, da im Attribut text die POS art steht, und in pos die Anzahl dieser POS arten. Umstrukturieren damit keine Verwirrung herrscht
|
||||
|
||||
// NLP: Sentiments
|
||||
// Der erste Sentiment gilt der gesamten Rede. Die weitere Sentiments entsprechen die Sätze.
|
||||
// Der erste Sentiment gilt der gesamten Rede. Die weitere Sentiments entsprechen die Sätze. overallSentiments speichert alle Analyseobjekte und sentiments nur die der einzelnen Sätze
|
||||
List<Sentiment> sentiments = speech.getNlp().getSentiments();
|
||||
if ((sentiments != null) && ! sentiments.isEmpty()) {
|
||||
List<Sentiment> overallSentiments = new ArrayList<>(sentiments);
|
||||
|
@ -212,30 +235,25 @@ public class SpeechController {
|
|||
tags = {"Rede"},
|
||||
queryParams = {
|
||||
@OpenApiParam(name = "filter", description = "Full-Text-Filter. Kann Vorname, Nachname oder Partei filtern", required = false),
|
||||
// TODO: Topic Filter
|
||||
},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = Speech[].class)})
|
||||
})
|
||||
public static void listAllSpeeches(Context ctx) {
|
||||
String filter = ctx.queryParam("filter");
|
||||
Logger.info("Filter: '" + filter + "'");
|
||||
|
||||
List<SpeechOverview> speechOverviews = MongoPprUtils.getSpeechOverview();
|
||||
List<SpeechOverview> speechOverviews = MongoPprUtils.getFilteredSpeechesOverview(ctx);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("speechesMetaDataList", speechOverviews);
|
||||
|
||||
// Filtern nach Text
|
||||
attributes.put("filter", filter == null || filter.isBlank() ? null : filter);
|
||||
String name = ctx.queryParam("name");
|
||||
if ((name != null) && ( ! name.isBlank())) attributes.put("name", name);
|
||||
|
||||
// Filtern nach Partei/Fraktion
|
||||
attributes.put("parties", MongoPprUtils.getAllPartiesFromSpeeches());
|
||||
|
||||
// Filtern nach Topics
|
||||
List<String> topics = MongoPprUtils.getAllTopics();
|
||||
attributes.put("topics", topics);
|
||||
|
||||
ctx.render("showAllSpeechesList.ftl", attributes);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,10 @@ import java.util.List;
|
|||
|
||||
import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.*;
|
||||
|
||||
/**
|
||||
* Controller für die Endpunkte zum Export von Reden als PDF.
|
||||
* Implementiert von Jonas
|
||||
*/
|
||||
public class SpeechesLatexExportController {
|
||||
@OpenApi(
|
||||
summary = "Get a speech as a PDF",
|
||||
|
|
|
@ -16,6 +16,10 @@ import java.util.List;
|
|||
import static org.texttechnologylab.project.gruppe_05_1.export.XMLUtil.*;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.*;
|
||||
|
||||
/**
|
||||
* Controller für die Endpunkte zum Export von Reden als XML.
|
||||
* Implementiert von Jonas
|
||||
*/
|
||||
public class SpeechesXMLExportController {
|
||||
@OpenApi(
|
||||
summary = "Get a speech as XML",
|
||||
|
|
|
@ -17,6 +17,7 @@ public abstract class FileUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
* Creates a (possibly nested) directory
|
||||
* @param dir (e.g. "generated" , "level1/level2/level3" etc.
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,7 @@ import java.time.format.DateTimeParseException;
|
|||
public abstract class GeneralUtils {
|
||||
|
||||
/**
|
||||
*
|
||||
* Datei implementiert von Valentin
|
||||
* @param integer the integer to be parsed
|
||||
* @return the parsed integer or null if the integer could not be parsed
|
||||
*/
|
||||
|
|
|
@ -4,6 +4,10 @@ import java.time.LocalTime;
|
|||
import java.time.format.DateTimeFormatter;
|
||||
import static org.texttechnologylab.project.gruppe_05_1.Main.DEBUG_LOGGING;
|
||||
|
||||
/**
|
||||
* Logger Klasse für die Ausgabe von Lognachrichten
|
||||
* Implementiert von Jonas
|
||||
*/
|
||||
public class Logger {
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
// info, warn, error with message and colors and datetime
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.util;
|
||||
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
|
@ -22,6 +24,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -41,6 +44,7 @@ public abstract class PPRUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Von Valentin angelegt, von allen verändert
|
||||
* Alle Informationen lesen...
|
||||
* - Parlamentarier
|
||||
* - Reden
|
||||
|
@ -61,21 +65,16 @@ public abstract class PPRUtils {
|
|||
Logger.warn("Members already in the DB. Skipping...");
|
||||
}
|
||||
|
||||
// Reden und Kommentare einlesen und persistieren - TODO
|
||||
// Reden und Kommentare einlesen und persistieren
|
||||
readSpeechesAndComments(xmlFactory, mongoFactory);
|
||||
|
||||
// Fotos hochladen - TODO
|
||||
// Fotos hochladen
|
||||
readPhotos(mongoFactory);
|
||||
|
||||
// NLP-Analyse (Text und Video)
|
||||
// TODO: Anpassung notwendig, Daten aus dem NEtz statt aus resources holen
|
||||
// Achtung: läuft nicht unter Windows. Verwende Linux (nativ oder im Virtual Box)
|
||||
// NlpUtils.createNlpData();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fotos hochladen - TODO
|
||||
* Fotos hochladen
|
||||
* @param mongoFactory Factory für die MongoDB-Objekte
|
||||
*/
|
||||
public static void readPhotos(MongoObjectFactory mongoFactory) {
|
||||
|
@ -83,7 +82,7 @@ public abstract class PPRUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Reden und Kommentare einlesen - TODO
|
||||
* Reden und Kommentare einlesen
|
||||
* @param xmlFactory Factory für die XML-Objekte
|
||||
* @param mongoFactory Factory für die MongoDB-Objekte
|
||||
*/
|
||||
|
@ -99,7 +98,6 @@ public abstract class PPRUtils {
|
|||
public static void readAndPersistMdbs(String mdbUrl, FileObjectFactory xmlFactory, MongoObjectFactory mongoFactory) {
|
||||
org.w3c.dom.Document mdbRoot = getMdbFromRemoteXmlZipfile(mdbUrl);
|
||||
Element rootElement = mdbRoot.getDocumentElement();
|
||||
// TODO: optional! persist the metadata of the <VERSION>1723434311</VERSION> element
|
||||
|
||||
List<Node> mdbNodes = XmlUtils.getChildrenByName(rootElement, "MDB");
|
||||
|
||||
|
@ -114,12 +112,9 @@ public abstract class PPRUtils {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: persist each speaker!
|
||||
// TODO: guard: if not in the DB already
|
||||
|
||||
}
|
||||
|
||||
// TODO - HERE
|
||||
private static boolean mdbActiveInWp(Speaker speaker, Integer legislaturPeriode) {
|
||||
List<Integer> wps = speaker.getMemberships().stream()
|
||||
.map(Membership::getWp)
|
||||
|
@ -156,7 +151,7 @@ public abstract class PPRUtils {
|
|||
zipInputStream.closeEntry();
|
||||
}
|
||||
|
||||
if (xmlOutputStream.size() == 0 || dtdOutputStream.size() == 0) { // TODO
|
||||
if (xmlOutputStream.size() == 0 || dtdOutputStream.size() == 0) {
|
||||
// throw new FileNotFoundException("XML or DTD not found in the ZIP archive");
|
||||
}
|
||||
InputStream xmlInputStreamFinal = new ByteArrayInputStream(xmlOutputStream.toByteArray());
|
||||
|
@ -171,7 +166,6 @@ public abstract class PPRUtils {
|
|||
return doc;
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@ -209,8 +203,6 @@ public abstract class PPRUtils {
|
|||
});
|
||||
}
|
||||
|
||||
// TODO: altes Zeug, sortieren...
|
||||
|
||||
/**
|
||||
* Alle Parteien (aus einer Liste der MdBs) herausfinden.
|
||||
* null-Einträge durch einen Platzhalter ersetzen, damit später keine null pointer exceptions auftretten
|
||||
|
@ -327,7 +319,19 @@ public abstract class PPRUtils {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Liest XML-Protokolle von der Bundestag-OpenData-URL und verarbeitet sie.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @return Ein Set von {@code org.w3c.dom.Document}, das die verarbeiteten XML-Protokolle enthält.
|
||||
*/
|
||||
public static Set<org.w3c.dom.Document> processXML() {
|
||||
int offset = 0;
|
||||
int limit = 10;
|
||||
|
@ -411,6 +415,12 @@ public abstract class PPRUtils {
|
|||
return doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listet die Dateien im gegebenen Verzeichnis auf.
|
||||
* Implementiert von Jonas
|
||||
* @param directory Verzeichnis
|
||||
* @return Liste der Dateinamen
|
||||
*/
|
||||
public static ArrayList<String> listFilesInDirectory(String directory) {
|
||||
File folder = new File(directory);
|
||||
File[] files = folder.listFiles();
|
||||
|
@ -425,6 +435,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 <div class="meta-slider"> 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<org.w3c.dom.Document> checkAndProcessNewProtocols(MongoDBHandler mongoDBHandler) {
|
||||
Set<org.w3c.dom.Document> newProtocols = new HashSet<>();
|
||||
int offset = 0;
|
||||
|
@ -485,6 +513,12 @@ public abstract class PPRUtils {
|
|||
return newProtocols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listet die Fraktionen von einer Liste an Membern auf
|
||||
* Implementiert von Jonas
|
||||
* @param mdbList Liste der Mitglieder
|
||||
* @return Liste der Fraktionen
|
||||
*/
|
||||
public static ArrayList<String> listFractionsFromMembers(List<Parlamentarier> mdbList) {
|
||||
ArrayList<String> fractions = new ArrayList<>();
|
||||
for (Parlamentarier parlamentarier : mdbList) {
|
||||
|
@ -500,4 +534,105 @@ public abstract class PPRUtils {
|
|||
}
|
||||
return fractions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetched das Bild eines Mitglieds aus der Bundestagsdatenbank und gibt es als Base64-String zurück
|
||||
* Implementiert von Jonas
|
||||
* @param inputString Name des Mitglieds
|
||||
* @return Base64-String des Bildes
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String fetchMemberImageBase64FromNameString(String inputString) throws IOException {
|
||||
// Step 1: Send POST request
|
||||
String urlString = "https://bilddatenbank.bundestag.de/ajax/picture-result";
|
||||
URL url = new URL(urlString);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
conn.setRequestProperty("Cookie", getSessionCookies());
|
||||
conn.setDoOutput(true);
|
||||
|
||||
// Form data
|
||||
String postData = "query=" + URLEncoder.encode(inputString, "UTF-8") + "&sortVal=2";
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
byte[] input = postData.getBytes("UTF-8");
|
||||
os.write(input, 0, input.length);
|
||||
}
|
||||
|
||||
// Read response
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"))) {
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
|
||||
// Parse JSON response
|
||||
JSONObject jsonResponse = new JSONObject(response.toString());
|
||||
JSONArray fotosArray = jsonResponse.optJSONArray("fotos");
|
||||
if (fotosArray != null && !fotosArray.isEmpty()) {
|
||||
String hqBild = fotosArray.getJSONObject(0).optString("hqBild", "");
|
||||
if (!hqBild.isEmpty()) {
|
||||
// Step 2: Fetch image
|
||||
String imageUrl = "https://bilddatenbank.bundestag.de/fotos/" + hqBild;
|
||||
URL imageDownloadUrl = new URL(imageUrl);
|
||||
HttpURLConnection imageConn = (HttpURLConnection) imageDownloadUrl.openConnection();
|
||||
imageConn.setRequestMethod("GET");
|
||||
|
||||
if (imageConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
try (InputStream is = imageConn.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "Error: Unable to retrieve image";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Session-Cookies zurück, die für die Requests der Bildersuche benötigt werden
|
||||
* Implementiert von Jonas
|
||||
* @return Session-Cookies
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String getSessionCookies() throws IOException {
|
||||
String urlString = "https://bilddatenbank.bundestag.de/search/picture-result?query=Angela+Merkel&sortVal=2";
|
||||
URL url = new URL(urlString);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
|
||||
// get both header fields with the name "Set-Cookie"
|
||||
Map<String, List<String>> headerFields = conn.getHeaderFields();
|
||||
|
||||
String phpSessId = "";
|
||||
String csrfToken = "";
|
||||
|
||||
// iterate over the header fields
|
||||
for (Map.Entry<String, List<String>> entry : headerFields.entrySet()) {
|
||||
// if header field is "Set-Cookie"
|
||||
if (entry.getKey() != null && entry.getKey().equals("set-cookie")) {
|
||||
// iterate over the values of the header field
|
||||
for (String value : entry.getValue()) {
|
||||
// if value contains "PHPSESSID"
|
||||
if (value.contains("PHPSESSID")) {
|
||||
phpSessId = value.split(";")[0];
|
||||
}
|
||||
// if value contains "_csrf"
|
||||
if (value.contains("_csrf")) {
|
||||
csrfToken = value.split(";")[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "PHPSESSID=" + phpSessId + "; _csrf=" + csrfToken;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package org.texttechnologylab.project.gruppe_05_1.util;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
public abstract class PropertiesUtils {
|
||||
|
||||
public static Properties readPropertiesFromResource(String propertiesFileName) {
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.util;
|
||||
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.gridfs.GridFSBucket;
|
||||
import com.mongodb.client.gridfs.GridFSBuckets;
|
||||
import com.mongodb.client.gridfs.model.GridFSUploadOptions;
|
||||
import com.mongodb.client.model.UpdateOneModel;
|
||||
import com.mongodb.client.model.WriteModel;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.texttechnologylab.project.gruppe_05_1.database.MongoDBHandler;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
//Implementiert von Henry
|
||||
|
||||
public class SpeechVideoUpdater {
|
||||
|
||||
|
||||
private static final int BASE_VIDEO_ID = 7615435;
|
||||
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 {
|
||||
|
||||
Document filter = new Document("sessionId", 187)
|
||||
.append("agendaItemId", 4)
|
||||
.append("speechId", 0);
|
||||
Document firstSpeech = mongoDBHandler.getSpeech(filter);
|
||||
if (firstSpeech != null && firstSpeech.containsKey("video")
|
||||
&& firstSpeech.getString("video") != null
|
||||
&& !firstSpeech.getString("video").trim().isEmpty()) {
|
||||
Logger.info("Videos sind bereits vorhanden. Kein Download notwendig.");
|
||||
} else {
|
||||
Logger.info("Keine Videos gefunden. Starte Download für die Reden der Session 187, AgendaItem 4...");
|
||||
findVideos();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Fehler beim Prüfen der Video-Felder: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
mongoDBHandler.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
MongoDatabase db = mongoDBHandler.getDatabase();
|
||||
|
||||
|
||||
GridFSBucket gridFSBucket = GridFSBuckets.create(db, "videos");
|
||||
|
||||
List<WriteModel<Document>> bulkOperations = new ArrayList<>();
|
||||
|
||||
|
||||
for (int speechId = 0; speechId < 9; speechId++) {
|
||||
int videoId = BASE_VIDEO_ID + speechId;
|
||||
String videoUrl = BASE_URL + videoId + "/" + videoId + SUFFIX;
|
||||
Logger.info("Downloading video for speech " + speechId + ": " + videoUrl);
|
||||
|
||||
|
||||
File videoFile = downloadVideo(videoUrl, "video_" + videoId + ".mp4");
|
||||
|
||||
|
||||
ObjectId gridFsId = uploadVideoToGridFS(gridFSBucket, videoFile, "video_" + videoId + ".mp4");
|
||||
Logger.info("Uploaded video with GridFS ID: " + gridFsId);
|
||||
|
||||
|
||||
Document filter = new Document("sessionId", 187)
|
||||
.append("agendaItemId", 4)
|
||||
.append("speechId", speechId);
|
||||
|
||||
Document update = new Document("$set", new Document("video", gridFsId.toHexString()));
|
||||
bulkOperations.add(new UpdateOneModel<>(filter, update));
|
||||
|
||||
|
||||
videoFile.delete();
|
||||
}
|
||||
|
||||
if (!bulkOperations.isEmpty()) {
|
||||
Logger.info("Uploading bulk update for " + bulkOperations.size() + " documents...");
|
||||
mongoDBHandler.bulkWriteNlpData(bulkOperations);
|
||||
Logger.info("Bulk update completed.");
|
||||
}
|
||||
|
||||
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();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
|
||||
File tempFile = new File(fileName);
|
||||
try (InputStream in = connection.getInputStream();
|
||||
FileOutputStream out = new FileOutputStream(tempFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
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()
|
||||
.chunkSizeBytes(358400)
|
||||
.metadata(new Document("type", "video").append("fileName", fileName));
|
||||
ObjectId fileId = gridFSBucket.uploadFromStream(fileName, streamToUploadFrom, options);
|
||||
return fileId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,9 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
/**
|
||||
* Datei implementiert von Valentin
|
||||
*/
|
||||
|
||||
public abstract class XmlUtils {
|
||||
|
||||
|
@ -43,7 +46,6 @@ public abstract class XmlUtils {
|
|||
try {
|
||||
document = builder.parse(xmlInputStream);
|
||||
|
||||
// TODO: Error handling...
|
||||
} catch (SAXException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.texttechnologylab.project.gruppe_05_1.domain.speaker.Speaker;
|
|||
import org.texttechnologylab.project.gruppe_05_1.xml.mdb.*;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.speaker.Speaker_File_Impl;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class FileObjectFactory {
|
||||
|
||||
private static FileObjectFactory oFactory = null;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package org.texttechnologylab.project.gruppe_05_1.xml;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public interface XmlOperations {
|
||||
FileObjectFactory factory = FileObjectFactory.getFactory();
|
||||
Object fromXmlNode(Node node);
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.texttechnologylab.project.gruppe_05_1.util.GeneralUtils;
|
|||
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.XmlOperations;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class BiografischeAngaben_File_Impl extends BiografischeAngaben implements XmlOperations {
|
||||
@Override
|
||||
public BiografischeAngaben fromXmlNode(Node node) {
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.texttechnologylab.project.gruppe_05_1.util.GeneralUtils;
|
|||
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.XmlOperations;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class Institution_File_Impl extends Institution implements XmlOperations {
|
||||
@Override
|
||||
public Institution fromXmlNode(Node node) {
|
||||
|
|
|
@ -8,7 +8,9 @@ import org.w3c.dom.Node;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class MdbDocument_File_Impl extends MdbDocument implements XmlOperations {
|
||||
@Override
|
||||
public MdbDocument fromXmlNode(Node node) {
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.texttechnologylab.project.gruppe_05_1.util.GeneralUtils;
|
|||
import org.texttechnologylab.project.gruppe_05_1.util.Logger;
|
||||
import org.texttechnologylab.project.gruppe_05_1.xml.XmlOperations;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class MdbName_File_Impl extends MdbName implements XmlOperations {
|
||||
@Override
|
||||
public MdbName fromXmlNode(Node node) {
|
||||
|
|
|
@ -9,7 +9,9 @@ import org.w3c.dom.Node;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class Mdb_File_Impl extends Mdb implements XmlOperations {
|
||||
@Override
|
||||
public Mdb fromXmlNode(Node node) {
|
||||
|
|
|
@ -9,7 +9,9 @@ import org.w3c.dom.Node;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class Wahlperiode_File_Impl extends Wahlperiode implements XmlOperations {
|
||||
@Override
|
||||
public Wahlperiode fromXmlNode(Node node) {
|
||||
|
|
|
@ -11,7 +11,9 @@ import org.w3c.dom.Node;
|
|||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* implementiert von Valentin
|
||||
*/
|
||||
public class Speaker_File_Impl extends Speaker implements XmlOperations {
|
||||
@Override
|
||||
public Speaker fromXmlNode(Node node) {
|
||||
|
@ -32,7 +34,7 @@ public class Speaker_File_Impl extends Speaker implements XmlOperations {
|
|||
mdbNameList.add(mdbName);
|
||||
}
|
||||
mdbNameList.sort((n1, n2 )-> n2.getHistorieVon().compareTo(n1.getHistorieVon())); // Descending order
|
||||
MdbName newestMdbName = mdbNameList.get(0); // TODO
|
||||
MdbName newestMdbName = mdbNameList.get(0);
|
||||
speaker.setName(newestMdbName.getNachname());
|
||||
speaker.setFirstName(newestMdbName.getVorname());
|
||||
speaker.setAkademischertitel(newestMdbName.getAkadTitel());
|
||||
|
|
|
@ -45,11 +45,25 @@ public class Comment_File_Impl implements Content, Comment {
|
|||
return MongoDBEntryType.SPEECH_COMMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Kommentar als LaTeX-kompatiblen String zurück.
|
||||
* Der Kommentar wird farbig dargestellt (blau) mit dem Label "Kommentar".
|
||||
*
|
||||
* @return String im LaTeX-Format für den Kommentar
|
||||
*/
|
||||
@Override
|
||||
public String toTeX() {
|
||||
return "\\textcolor{blue}{Kommentar}: " + this.getComment() + "\\\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Wandelt den Kommentar in ein XML-Element um.
|
||||
* Das erzeugte Element enthält die contentId, speechId, den Namen des Kommentators
|
||||
* sowie den eigentlichen Kommentartext als Inhalt.
|
||||
*
|
||||
* @param doc Das XML-Dokument, in das das Element eingebettet wird
|
||||
* @return Ein XML-Element, das den Kommentar repräsentiert
|
||||
*/
|
||||
@Override
|
||||
public Element toXML(Document doc) {
|
||||
Element comment = doc.createElement("comment");
|
||||
|
|
|
@ -35,6 +35,13 @@ public class Constituency_File_Impl implements Constituency {
|
|||
return MongoDBEntryType.CONSTIUENCY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gibt eine HTML-Darstellung des Wahlkreises zurück.
|
||||
* Die HTML-Ausgabe enthält die ID, den Namen und das Bundesland des Wahlkreises.
|
||||
*
|
||||
* @return HTML-String mit den Details des Wahlkreises
|
||||
*/
|
||||
@Override
|
||||
public String toHTML() {
|
||||
return "<div class='constituency'>"
|
||||
|
|
|
@ -47,6 +47,12 @@ public class Fraction_File_Impl implements Fraction {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine HTML-Darstellung der Fraktion zurück.
|
||||
* Die HTML-Ausgabe enthält den Namen sowie den Langnamen der Fraktion.
|
||||
*
|
||||
* @return HTML-String mit den Details der Fraktion
|
||||
*/
|
||||
@Override
|
||||
public String toHTML() {
|
||||
return "<div class='fraction'>"
|
||||
|
|
|
@ -42,6 +42,12 @@ public class LegislativePeriod_File_Impl implements LegislativePeriod {
|
|||
return MongoDBEntryType.LEGISLATIVE_PERIOD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine HTML-Darstellung der aktuellen Legislaturperiode zurück.
|
||||
* Die HTML-Ausgabe enthält Informationen wie ID, Start- und Enddatum sowie den Wahlkreis.
|
||||
*
|
||||
* @return HTML-String mit den Details der Legislaturperiode
|
||||
*/
|
||||
@Override
|
||||
public String toHTML() {
|
||||
return "<div class='legislative-period'>"
|
||||
|
|
|
@ -37,11 +37,25 @@ public class Line_File_Impl implements Content, Line {
|
|||
return MongoDBEntryType.SPEECH_LINE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Konvertiert die aktuelle Zeile (Line) in LaTeX-Format.
|
||||
* Jede Zeile endet mit einem Zeilenumbruch (`\\`), wie es in LaTeX üblich ist.
|
||||
*
|
||||
* @return Ein String im LaTeX-Format
|
||||
*/
|
||||
@Override
|
||||
public String toTeX() {
|
||||
return this.getContent() + "\\\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Wandelt die Zeile (Line) in ein XML-Element um.
|
||||
* Dabei werden `contentId` und `speechId` als Attribute gesetzt,
|
||||
* der eigentliche Inhalt wird als Text eingefügt.
|
||||
*
|
||||
* @param doc Das übergeordnete XML-Dokument
|
||||
* @return Ein XML-Element vom Typ <line>
|
||||
*/
|
||||
@Override
|
||||
public Element toXML(Document doc) {
|
||||
Element line = doc.createElement("line");
|
||||
|
|
|
@ -70,6 +70,12 @@ public class MemberOfParliament_File_Impl extends Individual_File_Impl implement
|
|||
return MongoDBEntryType.MEMBER_OF_PARLIAMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt eine HTML-Repräsentation eines Abgeordneten mit Basisinformationen,
|
||||
* Foto und Daten zu den legislativen Perioden.
|
||||
*
|
||||
* @return HTML-String zur Darstellung des Abgeordneten
|
||||
*/
|
||||
@Override
|
||||
public String toHTML() {
|
||||
StringBuilder html = new StringBuilder();
|
||||
|
|
|
@ -57,6 +57,12 @@ public class Session_File_Impl implements Session {
|
|||
this.agendaItems.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Session-Informationen als HTML-String zurück.
|
||||
* Enthält Angaben zur ID, zur Legislaturperiode sowie Start- und Endzeitpunkt der Sitzung.
|
||||
*
|
||||
* @return HTML-Darstellung der Sitzung als String
|
||||
*/
|
||||
@Override
|
||||
public String toHTML() {
|
||||
return "<div class='session'>"
|
||||
|
|
|
@ -52,11 +52,24 @@ public class Speaker_File_Impl implements Content, Speaker {
|
|||
return MongoDBEntryType.SPEECH_SPEAKER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Sprecherdaten als TeX-String zurück.
|
||||
* Der Name des Redners bzw. der Rednerin wird farblich hervorgehoben.
|
||||
*
|
||||
* @return TeX-Darstellung des Redners/der Rednerin
|
||||
*/
|
||||
@Override
|
||||
public String toTeX() {
|
||||
return "\\textcolor{blue}{Redner/Rednerin}: " + this.getSpeakerName() + "\\\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt ein XML-Element mit Informationen zum Redner/zur Rednerin.
|
||||
* Enthält ID, Name, Fraktion und zugehörige Redeinformationen.
|
||||
*
|
||||
* @param doc Das übergeordnete XML-Dokument
|
||||
* @return XML-Element für den Redner/die Rednerin
|
||||
*/
|
||||
@Override
|
||||
public Element toXML(Document doc) {
|
||||
Element speaker = doc.createElement("speaker");
|
||||
|
|
|
@ -83,6 +83,14 @@ public class Speech_File_Impl implements Speech {
|
|||
//Logger.pink("Added paragraph to speech: " + paragraph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Rede als HTML-Darstellung zurück.
|
||||
* Die HTML-Ausgabe enthält Informationen zur Sitzung, zum Redner und zur Fraktion.
|
||||
* <p>
|
||||
* Hinweis: Es ist geplant, die gesprochenen Textzeilen visuell hervorzuheben (siehe TODO).
|
||||
*
|
||||
* @return HTML-String, der die Metadaten der Rede repräsentiert
|
||||
*/
|
||||
@Override
|
||||
public String toHTML() {
|
||||
//TODO: Implement a logic that highlights the lines that the speaker is saying
|
||||
|
@ -105,6 +113,13 @@ public class Speech_File_Impl implements Speech {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die gesamte Rede im TeX-Format zurück.
|
||||
* Der Inhalt der Rede wird Abschnitt für Abschnitt eingebunden,
|
||||
* zusätzlich wird ein Platzhalter für NLP-Metadaten eingefügt.
|
||||
*
|
||||
* @return TeX-Darstellung der Rede inklusive NLP-Platzhalter und Redeinhalten
|
||||
*/
|
||||
@Override
|
||||
public String toTeX() {
|
||||
StringBuilder tex = new StringBuilder();
|
||||
|
@ -124,6 +139,14 @@ public class Speech_File_Impl implements Speech {
|
|||
return tex.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt ein XML-Element für die gesamte Rede.
|
||||
* Es werden alle relevanten Metadaten der Rede sowie die Inhalte
|
||||
* (z. B. Redner, Textzeilen, Kommentare) als Kindelemente hinzugefügt.
|
||||
*
|
||||
* @param doc Das XML-Dokument, zu dem das Element gehört
|
||||
* @return XML-Element, das die Rede und deren Inhalte beschreibt
|
||||
*/
|
||||
@Override
|
||||
public Element toXML(Document doc) {
|
||||
Element speech = doc.createElement("speech");
|
||||
|
|
|
@ -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<Session> parseAllSessions() {
|
||||
List<Session> 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<Session> parseAllSessions(Set<Document> xmlDocuments) {
|
||||
List<Session> 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) {
|
||||
|
@ -196,7 +237,12 @@ public class SpeechParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Konvertiert ein org.w3c.dom.Document in eine temporäre Datei.
|
||||
* Konvertiert ein XML-Dokument (org.w3c.dom.Document) in eine temporäre Datei.
|
||||
* Diese Datei wird zur weiteren Verarbeitung, z. B. mit XML-Parsern, verwendet.
|
||||
*
|
||||
* @param xmlDoc Das zu konvertierende XML-Dokument.
|
||||
* @return Eine temporäre Datei, die den Inhalt des XML-Dokuments enthält.
|
||||
* @throws Exception Falls beim Erstellen oder Schreiben der Datei ein Fehler auftritt.
|
||||
*/
|
||||
private File convertDocumentToFile(org.w3c.dom.Document xmlDoc) throws Exception {
|
||||
File tempFile = File.createTempFile("session_", ".xml");
|
||||
|
|
|
@ -2,5 +2,9 @@
|
|||
<link rel="stylesheet" href="index.css">
|
||||
</head>
|
||||
<#include "header.ftl">
|
||||
<h1>About</h1>
|
||||
<h1>Über</h1>
|
||||
<p>Alle Infos zur Nutzung und die Dokumentation kann auf der <a href="https://ppr.gitlab.texttechnologylab.org/leonkastner/multimodal-parliament-explorer-docu">Doku GitLab Repository eingesehen werden</a></p>
|
||||
<br>
|
||||
<br>
|
||||
<p>PPR WS24/25 - Gruppe_05_1</p>
|
||||
<#include "footer.ftl">
|
52
src/main/resources/templates/charts.ftl
Normal file
52
src/main/resources/templates/charts.ftl
Normal file
|
@ -0,0 +1,52 @@
|
|||
<head>
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<title>Parliament Explorer</title>
|
||||
</head>
|
||||
<#include "header.ftl">
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<body>
|
||||
<h1>Chart Sortiment</h1>
|
||||
<h2>NLP Analyse aller Reden</h2>
|
||||
<div class="chart-container">
|
||||
<div class="chart">
|
||||
<#if aggregatedTopics?? && (aggregatedTopics?size gt 0)>
|
||||
<h3>Topics Information (als Bubble Chart)</h3>
|
||||
<#assign condenseTopicInformation = aggregatedTopics>
|
||||
<#include "topicsBubbleChart.ftl">
|
||||
<#else>
|
||||
<h3>Keine Topics Information verfügbar</h3>
|
||||
</#if>
|
||||
</div>
|
||||
|
||||
<div class="chart">
|
||||
<#if aggregatedPOS?? && (aggregatedPOS?size gt 0)>
|
||||
<h3>POS Information (als Bar Chart)</h3>
|
||||
<#assign posList = aggregatedPOS>
|
||||
<#include "posBarChart.ftl">
|
||||
<#else>
|
||||
<h3>Keine POS Information verfügbar</h3>
|
||||
</#if>
|
||||
</div>
|
||||
|
||||
<div class="chart">
|
||||
<#if aggregatedSentiment?? && (aggregatedSentiment?size gt 0)>
|
||||
<h3>Sentiments Information (als Radar Chart)</h3>
|
||||
<#assign sentiments = [aggregatedSentiment]>
|
||||
<#include "sentimentsRadarChart.ftl">
|
||||
<#else>
|
||||
<h3>Keine Sentiments Information verfügbar</h3>
|
||||
</#if>
|
||||
</div>
|
||||
|
||||
<div class="chart">
|
||||
<#if aggregatedNE?? && (aggregatedNE?size gt 0)>
|
||||
<h3>Named Entities Information (als Sunburst Chart)</h3>
|
||||
<#assign neMap = aggregatedNE>
|
||||
<#include "namedEntitiesSunburstChart.ftl">
|
||||
<#else>
|
||||
<h3>Keine Named Entities Information verfügbar</h3>
|
||||
</#if>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<#include "footer.ftl">
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue