From fbf3c5b68df83d12fb6aa96becfc1f48d62391a6 Mon Sep 17 00:00:00 2001 From: vysitor Date: Sun, 9 Mar 2025 23:05:35 +0100 Subject: [PATCH 1/4] Correction to enable local database use, slight rework --- .DS_Store | Bin 6148 -> 0 bytes src/.DS_Store | Bin 6148 -> 0 bytes src/main/.DS_Store | Bin 6148 -> 0 bytes src/main/java/.DS_Store | Bin 6148 -> 0 bytes .../project/gruppe_05_1/Main.java | 23 +--- .../gruppe_05_1/database/MongoDBHandler.java | 120 +++++++++++------- .../gruppe_05_1/database/MongoPprUtils.java | 51 ++------ .../project/gruppe_05_1/util/PPRUtils.java | 17 --- src/main/resources/.DS_Store | Bin 6148 -> 0 bytes 9 files changed, 91 insertions(+), 120 deletions(-) delete mode 100644 .DS_Store delete mode 100644 src/.DS_Store delete mode 100644 src/main/.DS_Store delete mode 100644 src/main/java/.DS_Store delete mode 100644 src/main/resources/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 6799dc56e42b2b388b6a47a9c6899b991b6bd97e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5Iwu5S=9{END_v?iF%_B{C<-0YHf*C}M3IdUu?Gnp1EA?!irX^WhV%a7hup zk!GHEKD+iSc03}IHc!J^WF;aUR8gMQw4!mfB}AOmE844gXy=-DdWl_M<~ zAOmFJn*qHaGE}hyPL6hUz}N@?)Zcg$JliY*%<2G^z{wFFNb*vkm!=pol9$7uBd-Kb zj$SUwPR2fQa*7Eh+3E0SOP5p}X~_T?IAvhr%a!*3Tj(G2|7j6dWPl8u6$5G6Z~F~C zDSB)3aoTG$^d9;p$hCABYsElo#aL)7zW$Y$^%?OJI5}E5{8kR+kAU(*Ap`%xz$d5U BCcgjx diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index 7cbb9350a57ec1469c8047c4081470492225b483..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKK~BR!475v-BK1;n;4huGjSuh_#0U5iSH|{&5=G_6 z0mhPdvbHCi%ps0NL|2d7rN}}=YPg|1+cGuFn@?<3A{9{W9=qG+`lf65lgh&Z<5tqj zwcN|Yh(G(d9Ol}tX*RoVgIN9YG=DvLdp{rNw?F3hcY|j;J_D6T1*iZOpaN9jUn+o} zZC1|%xl#ctKn1=PuB-*`7%`z!%W769ggeIOz*4Jt6GT1E^F zI^wC+<$`@+&_(@Z+^3wZWkOLu9r5JlqB)Q&6`%rR1&(67u>OAmKQRA~N!(EZD)6Ti z(5hKCE4)(at&^9tUYp=o@GnEHmt*l(4D?ovjkV&_L0z(IXhxcS>-l)sZ!M39h}>{9>l1Z}D1$O49SkkPe%6L0YGJ42dn~T{qiMNZ zH6qRMUm4)DOKDDHx}|Y+e#yf}-M1`@VzMYFux0N@cTdMJuY=e>`_;d?uDu&+cttw2 zrc1h^k~Wx4c^>V624`5IC91xc``+`{iR`5{@@H4)>$lI{k5eu6b1IBX7@ z#ehqTQ8C0LX>Dyh9M@V8y@0ZCTqU?o!6cMo#BwR_L4&~Vc>>H8D?wNw_9GBzu)!Gk HQwF{PY~fF| diff --git a/src/main/java/.DS_Store b/src/main/java/.DS_Store deleted file mode 100644 index f1ac8ac2ee0489b828c3923f4b30172b71962d9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF-`+P47AA=C()d!DEABb!4e&Pq-Ka+;mGs>bK_U`Qq?$HO#Jl$nNe2yH<11XjFg-Pys4H1^%@H z=-FoVc_2qBKn1A4hXVG0NN~ekun+WK2L`|91MM2`hPl5bfXM>DT(A#B1g1d+235-w zLxYZZDs{PF9~g8|KNZNQt7RukF#Ez;5YE2q1MYWcq;~aE5^cF@#UZ{*&O*?un%-P;!X$hB4E1E JsK9S1@D65dC|v*m diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java index 21d0b64..2ab030f 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java @@ -1,26 +1,16 @@ package org.texttechnologylab.project.gruppe_05_1; -import com.mongodb.client.MongoDatabase; import org.texttechnologylab.project.gruppe_05_1.database.*; -import org.texttechnologylab.project.gruppe_05_1.domain.mdb.Mdb; -import org.texttechnologylab.project.gruppe_05_1.domain.mdb.MdbDocument; -import org.texttechnologylab.project.gruppe_05_1.nlp.NlpUtils; -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.PropertiesUtils; -import org.texttechnologylab.project.gruppe_05_1.util.XmlUtils; import org.texttechnologylab.project.gruppe_05_1.xml.FileObjectFactory; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.SpeechParser; -import org.w3c.dom.Element; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; -import java.util.List; -import java.util.Properties; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; @@ -57,10 +47,10 @@ public class Main { public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException { //TEST - + MongoDBHandler mongoDBHandler = new MongoDBHandler(); SpeechIndexFactoryImpl speechIndexFactory = new SpeechIndexFactoryImpl(); - if (MongoPprUtils.getSpeechCollection().countDocuments() != 0) { + if (mongoDBHandler.getDatabase().getCollection(MongoPprUtils.SPEECH_COLLECTION_NAME).countDocuments() != 0) { System.out.println("Speeches werden nicht gelesen, da sie bereits in der Datenbank stehen"); } else { @@ -79,8 +69,7 @@ public class Main { System.out.println("SESSIONCOUNT: " + speechIndex.getSessions().size()); System.out.println("AGENDAITEMCOUNT: " + speechIndex.getAgendaItems().size()); - MongoDBHandler mongoDBHandler = new MongoDBHandler(); - mongoDBHandler.deleteAllDocuments(); // Clear the DB + mongoDBHandler.deleteSpeechRelatedDocuments(); // Clear speeches, sessions, agendas (history) Logger.pink("Adding Sessions to DB..."); mongoDBHandler.insertSessions(speechIndex.getSessions()); @@ -90,13 +79,8 @@ public class Main { Logger.pink("Adding Speeches to DB..."); mongoDBHandler.insertSpeeches(speechIndex.getSpeeches()); - - mongoDBHandler.close(); // Close the connection to the DB } - // Stellt fest, dass alle nötigen Datenbank-Collections existieren - PPRUtils.ensureCollectionExist(); - // Alle Informationen (Parlamentarier, Reden, Kommentare etc.) lesen und in die Mongo-DB einfügen, falls diese noch nicht vorhanden sind. PPRUtils.parlamentExplorerInit(xmlFactory, mongoFactory); @@ -105,6 +89,7 @@ public class Main { // NLP-Verarbeitung - TODO // NlpUtils.importXmiData(); + mongoDBHandler.close(); // Close the connection to the DB RESTHandler restHandler = new RESTHandler(); restHandler.startJavalin(); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java index f23152c..44f84c0 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java @@ -8,16 +8,12 @@ import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.*; -import exceptions.AgendaItemNotFoundException; -import exceptions.MemberNotFoundException; import exceptions.ServerErrorException; import exceptions.SessionNotFoundException; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; -import org.texttechnologylab.DockerUnifiedUIMAInterface.connection.mongodb.MongoDBConfig; import org.texttechnologylab.project.gruppe_05_1.database.domainimp.speeches.AgendaItem_MongoDB_Impl; -import org.texttechnologylab.project.gruppe_05_1.database.domainimp.speeches.MemberOfParliament_MongoDB_Impl; import org.texttechnologylab.project.gruppe_05_1.database.domainimp.speeches.Session_MongoDB_Impl; import org.texttechnologylab.project.gruppe_05_1.database.domainimp.speeches.Speech_MongoDB_Impl; import org.texttechnologylab.project.gruppe_05_1.util.Logger; @@ -25,7 +21,6 @@ import org.texttechnologylab.project.gruppe_05_1.util.PropertiesUtils; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.*; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.*; -import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; @@ -49,8 +44,8 @@ public class MongoDBHandler { private static String collection; private static String databaseName; + private MongoCollection speakerCollection; private MongoCollection speechesCollection; - private MongoCollection sessionsCollection; private MongoCollection agendaItemsCollection; private MongoCollection historyCollection; @@ -71,27 +66,41 @@ public class MongoDBHandler { collection = mongoProperties.getProperty("remote_collection"); databaseName = mongoProperties.getProperty("remote_database"); - MongoCredential credential = MongoCredential - .createCredential( - user, - databaseName, - password.toCharArray()); + // URI für lokale Datenbank oder für eine Datenbank auf dem Server + String uri; + if ( (localServer != null) && (! localServer.isBlank())) { + uri = localServer; + mongoClient = MongoClients.create(uri); - MongoClientSettings settings = MongoClientSettings.builder() - .credential(credential) - .timeout(180, TimeUnit.HOURS) // needs increased timeout for the bulk speech inserts - .applyToClusterSettings(builder -> - builder.hosts(List.of(new ServerAddress(remoteServer, Integer.parseInt(port))))) - .build(); + // Connect + database = mongoClient.getDatabase(databaseName); + } else { + MongoCredential credential = MongoCredential + .createCredential( + user, + databaseName, + password.toCharArray()); - mongoClient = MongoClients.create(settings); - database = mongoClient.getDatabase(databaseName); - speechesCollection = database.getCollection("speech"); - sessionsCollection = database.getCollection("sessions"); - agendaItemsCollection = database.getCollection("agendaItems"); - historyCollection = database.getCollection("history"); + MongoClientSettings settings = MongoClientSettings.builder() + .credential(credential) + .timeout(180, TimeUnit.HOURS) // needs increased timeout for the bulk speech inserts + .applyToClusterSettings(builder -> + builder.hosts(List.of(new ServerAddress(remoteServer, Integer.parseInt(port))))) + .build(); + + mongoClient = MongoClients.create(settings); + database = mongoClient.getDatabase(databaseName); + } + + speakerCollection = database.getCollection(MongoPprUtils.SPEAKER_COLLECTION_NAME); + speechesCollection = database.getCollection(MongoPprUtils.SPEECH_COLLECTION_NAME); + sessionsCollection = database.getCollection(MongoPprUtils.SESSION_COLLECTION_NAME); + agendaItemsCollection = database.getCollection(MongoPprUtils.AGENDA_ITEMS_COLLECTION_NAME); + historyCollection = database.getCollection(MongoPprUtils.HISTORY_COLLECTION_NAME); + + createIndicesForSpeakerCollection(); + createIndicesForSpeechCollection(); Logger.info("Connected to MongoDB database: " + databaseName); - } public MongoDatabase getDatabase() { @@ -105,18 +114,22 @@ public class MongoDBHandler { */ static public MongoDatabase getMongoDatabase() { - if (mongoDatabase == null) { - Properties mongoProperties = PropertiesUtils.readPropertiesFromResource(propertiesFileName); - // Zugangsdaten - localServer = mongoProperties.getProperty("localserver"); - remoteServer = mongoProperties.getProperty("remote_host"); - user = mongoProperties.getProperty("remote_user"); - password = mongoProperties.getProperty("remote_password"); - port = mongoProperties.getProperty("remote_port"); - collection = mongoProperties.getProperty("remote_collection"); - databaseName = mongoProperties.getProperty("remote_database"); + if (mongoDatabase != null) { + return mongoDatabase; } + + Properties mongoProperties = PropertiesUtils.readPropertiesFromResource(propertiesFileName); + // Zugangsdaten + localServer = mongoProperties.getProperty("localserver"); + remoteServer = mongoProperties.getProperty("remote_host"); + user = mongoProperties.getProperty("remote_user"); + password = mongoProperties.getProperty("remote_password"); + port = mongoProperties.getProperty("remote_port"); + collection = mongoProperties.getProperty("remote_collection"); + databaseName = mongoProperties.getProperty("remote_database"); + + // MongoDBClient erzeugen // String uri = mongoServer + "://" + mongoUser + ":" + mongoPassword + "@" + mongoNeetwork; // cluster, network, user... @@ -158,9 +171,9 @@ public class MongoDBHandler { * * @return List with the names of all collections */ - static public Set getCollectionNames() { - // return getMongoDatabase().listCollectionNames().into(new ArrayList<>()); - return getMongoDatabase().listCollectionNames().into(new HashSet<>()); + public Set getCollectionNames() { + // return getDatabase().listCollectionNames().into(new ArrayList<>()); + return getDatabase().listCollectionNames().into(new HashSet<>()); } /** @@ -168,8 +181,8 @@ public class MongoDBHandler { * @param name Name of collection to check for existance * @return does the collection exist */ - static public boolean collectionExists(String name) { - return getMongoDatabase().listCollectionNames().into(new ArrayList<>()).contains(name); + public boolean collectionExists(String name) { + return getDatabase().listCollectionNames().into(new ArrayList<>()).contains(name); } @@ -193,8 +206,8 @@ public class MongoDBHandler { } } - static public void createCollectionIfNotExist(String collectionName) { - createCollectionIfNotExist(getMongoDatabase(), collectionName); + public void createCollectionIfNotExist(String collectionName) { + createCollectionIfNotExist(getDatabase(), collectionName); } @@ -211,8 +224,8 @@ public class MongoDBHandler { } } - static public void createCollection(String collectionName) { - createCollection(getMongoDatabase(), collectionName); + public void createCollection(String collectionName) { + createCollection(getDatabase(), collectionName); } @@ -261,8 +274,23 @@ public class MongoDBHandler { } } - static public void createOrTrancateCollection(String collectionName) { - createOrTrancateCollection(getMongoDatabase(), collectionName); + public void createIndicesForSpeakerCollection() { + if (speakerCollection.listIndexes().into(new ArrayList<>()).size() == 1) { + MongoDBHandler.createIndexForCollection(speakerCollection,"name", true); + MongoDBHandler.createIndexForCollection(speakerCollection,"firstName", true); + MongoDBHandler.createIndexForCollection(speakerCollection,"party", true); + } + + } + public void createIndicesForSpeechCollection() { + if (speechesCollection.listIndexes().into(new ArrayList<>()).size() == 1) { + MongoDBHandler.createIndexForCollection(speechesCollection, "speakerId", true); + MongoDBHandler.createIndexForCollection(speechesCollection, "speechKey", true); + } + } + + public void createOrTrancateCollection(String collectionName) { + createOrTrancateCollection(database, collectionName); } /** @@ -648,7 +676,7 @@ public class MongoDBHandler { ); } - public void deleteAllDocuments() { + public void deleteSpeechRelatedDocuments() { speechesCollection.deleteMany(new Document()); sessionsCollection.deleteMany(new Document()); agendaItemsCollection.deleteMany(new Document()); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java index aec92aa..b020bbf 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java @@ -2,7 +2,6 @@ package org.texttechnologylab.project.gruppe_05_1.database; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; -import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.texttechnologylab.project.gruppe_05_1.domain.html.Parlamentarier; import org.texttechnologylab.project.gruppe_05_1.domain.html.ParlamentarierDetails; @@ -16,7 +15,6 @@ import java.util.*; * Diese Klasse beinhaltet Mongo-Utilities, welche spezifisch für die PPR-Datenstrukturen sind. * Mongo-Utilities genereller Natur stehen in der Klasse MongoDBHandler. */ -@Slf4j public class MongoPprUtils { /* @@ -25,6 +23,10 @@ public class MongoPprUtils { */ public static final String SPEAKER_COLLECTION_NAME = "speaker"; public static final String SPEECH_COLLECTION_NAME = "speech"; + + public static final String SESSION_COLLECTION_NAME = "sessions"; + public static final String AGENDA_ITEMS_COLLECTION_NAME = "agendaItems"; + public static final String HISTORY_COLLECTION_NAME = "history"; public static final String PICTURES_COLLECTION_NAME = "pictures"; public static final String COMMENT_COLLECTION_NAME = "comment"; @@ -43,53 +45,26 @@ public class MongoPprUtils { return speechCollection; } - public static MongoCollection getPicturesCollection() { - if (picturesCollection == null) picturesCollection = MongoDBHandler.getMongoDatabase().getCollection(PICTURES_COLLECTION_NAME); - return picturesCollection; - } - - public static MongoCollection getCommentCollection() { - if (commentCollection == null) commentCollection = MongoDBHandler.getMongoDatabase().getCollection(COMMENT_COLLECTION_NAME); - return commentCollection; - } /** * Create the Speaker Collection and useful indices for it */ - public static void createSpeakerCollection() { - MongoDBHandler.createCollection(MongoPprUtils.SPEAKER_COLLECTION_NAME); - - MongoDBHandler.createIndexForCollection(getSpeakerCollection(), Arrays.asList("name", "firstName", "party"), true); + public static void createIndexForSpeakerCollection() { + // MongoDBHandler.createIndexForCollection(getSpeakerCollection(), Arrays.asList("name", "firstName", "party"), true); + MongoDBHandler.createIndexForCollection(getSpeakerCollection(),"name", true); + MongoDBHandler.createIndexForCollection(getSpeakerCollection(),"firstName", true); + MongoDBHandler.createIndexForCollection(getSpeakerCollection(),"party", true); } /** * Create the Speech Collection and useful indices for it */ - public static void createSpeechCollection() { - MongoDBHandler.createCollection(MongoPprUtils.SPEECH_COLLECTION_NAME); - MongoDBHandler.createIndexForCollection(getSpeechCollection(), "speaker", true); + public static void createIndexForSpeechCollection() { + MongoDBHandler.createIndexForCollection(getSpeechCollection(), "speakerId", true); + MongoDBHandler.createIndexForCollection(getSpeechCollection(), "speechKey", true); } - /** - * Create the Comment Collection and useful indices for it - */ - public static void createCommentCollection() { - MongoDBHandler.createCollection(MongoPprUtils.COMMENT_COLLECTION_NAME); - MongoDBHandler.createIndexForCollection(getCommentCollection(), Arrays.asList("speaker", "speech"), true); - } - - - /** - * Create the Picture Collection and useful indices for it - */ - public static void createPictureCollection() { - MongoDBHandler.createCollection(MongoPprUtils.PICTURES_COLLECTION_NAME); - - // TODO: für welche Felder sollen Indizes gebaut werden? - // MongoDBHandler.createIndexForCollection(getPicturesCollection(), Arrays.asList("field_1", "field_2"), true); - } - /** * Truncate the Speaker Collection. * Note that it is quicker (and saves space) to drop and re-create rather than removing all documents using "remove({})" @@ -97,7 +72,7 @@ public class MongoPprUtils { public static void truncateSpeakerCollection() { getSpeakerCollection().drop(); - createSpeechCollection(); + createIndexForSpeechCollection(); } /* diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java index b506a78..3da9b02 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/PPRUtils.java @@ -36,23 +36,6 @@ public abstract class PPRUtils { - /** - * Prüfe, ob die Collections existieren. Falls nicht: erzeuge sie und lege Indizes an - */ - public static void ensureCollectionExist() { - - Set existingCollectionNames = MongoDBHandler.getCollectionNames(); - - if (!existingCollectionNames.contains(MongoPprUtils.SPEAKER_COLLECTION_NAME)) { - MongoPprUtils.createSpeakerCollection(); - } - - if (!existingCollectionNames.contains(MongoPprUtils.SPEECH_COLLECTION_NAME)) { - MongoPprUtils.createSpeechCollection(); - } - - } - /** * Alle Informationen lesen... * - Parlamentarier diff --git a/src/main/resources/.DS_Store b/src/main/resources/.DS_Store deleted file mode 100644 index 558c0a3d69821fe11caa8220681a138569846b17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKu};G<5PfbdR0Km{V$8x${~%Q13%W5uT2v4Ti7L8hWk7rhJNy72z>N3-eu8(l z)y9NUSP(*Y()l^(JNx|7=4=3FIG+rF2tc1I*x6+BiO9HUOFG`NO*AscU^Fg^s^zDK zzsrEUyDkb$kmb|X`|~43nWkA@X7rUG!p_~p)8R6%C?{WxR_Co*BUH$7hAW(6#{LW? zuBn&QTt>o7_TRYH+L&gJx6e2CyN@=6GAAuSZ+LWwTa_$!8S;k3uzFY#DAbm1^|WzOSQHvWcU{0Yd! z)*U8ssI4-f41^4H-D4#6|7i97KMc|*Wk4DDR}7e5I!cG!lCQ0;%}K3|sV7ts@v9v! kLfEmTn7&eq_o!BAkEKIQJk}0rq3A)t(x8np@T&~G0}@VjjQ{`u From c028d7ed12a91ec230ac807cc5eb833f3da51ba8 Mon Sep 17 00:00:00 2001 From: Picman2000 <65342372+Picman2000@users.noreply.github.com> Date: Mon, 10 Mar 2025 12:26:42 +0100 Subject: [PATCH 2/4] - completed nlp stuff from 2.1 2) - The program now verifies whether speeches in the database are missing an NLP field and processes them accordingly. --- .../project/gruppe_05_1/Main.java | 21 ++- .../gruppe_05_1/database/MongoDBHandler.java | 21 ++- .../speeches/Speech_MongoDB_Impl.java | 38 +++++ .../project/gruppe_05_1/nlp/NlpUtils.java | 151 ++++++++++++++++-- .../project/gruppe_05_1/nlp/XmiExtractor.java | 75 ++++++--- .../xml/speeches/Impls/Speech_File_Impl.java | 12 ++ .../xml/speeches/Interfaces/Speech.java | 6 + 7 files changed, 284 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java index 21d0b64..d4a47ea 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java @@ -54,7 +54,7 @@ public class Main { private static final FileObjectFactory xmlFactory = FileObjectFactory.getFactory(); private static final MongoObjectFactory mongoFactory = MongoObjectFactory.getFactory(); private static final SpeechParser speechParser = new SpeechParser(); - public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException { + public static void main(String[] args) throws Exception { //TEST @@ -100,12 +100,23 @@ public class Main { // Alle Informationen (Parlamentarier, Reden, Kommentare etc.) lesen und in die Mongo-DB einfügen, falls diese noch nicht vorhanden sind. PPRUtils.parlamentExplorerInit(xmlFactory, mongoFactory); - // Upload der analysierten XMI dateien - - // NLP-Verarbeitung - TODO - // NlpUtils.importXmiData(); + MongoDBHandler mongoDBHandler = new MongoDBHandler(); + //das muss auf jeden fall noch angepasst werden xd + if(mongoDBHandler.checkAnalysisResultsField() < 21518) { + try { + long startTime = System.currentTimeMillis(); + XmiExtractor extractor = new XmiExtractor(); + extractor.extractAndUploadXmiData(); + long endTime = System.currentTimeMillis(); + System.out.println("Execution time: " + (endTime - startTime) + " ms"); + } catch (Exception e) { + e.printStackTrace(); + } + } + mongoDBHandler.close(); + NlpUtils.runRemoteDriver(); RESTHandler restHandler = new RESTHandler(); restHandler.startJavalin(); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java index f23152c..503194e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoDBHandler.java @@ -3,6 +3,7 @@ package org.texttechnologylab.project.gruppe_05_1.database; 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; @@ -655,9 +656,23 @@ public class MongoDBHandler { //historyCollection.deleteMany(new Document()); } - public void bulkUpdateDocuments(String collectionName, List> updates) { - BulkWriteOptions options = new BulkWriteOptions().ordered(false); - speechesCollection.bulkWrite(updates, options); + public void bulkWriteNlpData(List> bulkOperations) { + if (!bulkOperations.isEmpty()) { + BulkWriteResult result = speechesCollection.bulkWrite(bulkOperations); + int modifiedCount = result.getModifiedCount(); + int matchedCount = result.getMatchedCount(); + int upsertCount = result.getUpserts().size(); + System.out.println("Bulk write operation completed: " + + modifiedCount + " documents updated, " + + matchedCount + " documents matched, " + + upsertCount + " upserts."); + } else { + System.out.println("No operations to write."); + } + } + + public long checkAnalysisResultsField() { + return speechesCollection.countDocuments(Filters.exists("analysisResults")); } public void close() { diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimp/speeches/Speech_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimp/speeches/Speech_MongoDB_Impl.java index 5f2fbb3..729142c 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimp/speeches/Speech_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimp/speeches/Speech_MongoDB_Impl.java @@ -1,7 +1,12 @@ package org.texttechnologylab.project.gruppe_05_1.database.domainimp.speeches; +import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData; +import org.apache.uima.UIMAException; +import org.apache.uima.fit.factory.JCasFactory; +import org.apache.uima.jcas.JCas; import org.bson.Document; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Speech_File_Impl; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Content; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; @@ -37,4 +42,37 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech { } } + + 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 + public JCas toCas() throws UIMAException { + JCas jCas = JCasFactory.createJCas(); + jCas.setDocumentText(this.getFullText()); + DocumentMetaData dmd = new DocumentMetaData(jCas); + dmd.setDocumentId(this.getSpeechKey());; + dmd.addToIndexes(); + return jCas; + } + } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java index f498b9a..509ae2a 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java @@ -4,9 +4,11 @@ import com.mongodb.client.model.Filters; import com.mongodb.client.model.UpdateOneModel; import com.mongodb.client.model.Updates; import com.mongodb.client.model.WriteModel; +import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.POS; import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; +import de.tudarmstadt.ukp.dkpro.core.api.syntax.type.dependency.Dependency; import org.apache.commons.io.FileUtils; import org.apache.uima.UIMAException; import org.apache.uima.UIMAFramework; @@ -24,7 +26,9 @@ import org.apache.uima.resource.metadata.TypeSystemDescription; import org.apache.uima.util.CasCreationUtils; import org.apache.uima.util.XMLInputSource; import org.bson.Document; +import org.bson.conversions.Bson; import org.dkpro.core.io.xmi.XmiWriter; +import org.hucompute.textimager.uima.type.category.CategoryCoveredTagged; import org.texttechnologylab.DockerUnifiedUIMAInterface.DUUIComposer; import org.texttechnologylab.DockerUnifiedUIMAInterface.driver.DUUIDockerDriver; import org.texttechnologylab.DockerUnifiedUIMAInterface.driver.DUUIRemoteDriver; @@ -32,6 +36,9 @@ import org.texttechnologylab.DockerUnifiedUIMAInterface.driver.DUUIUIMADriver; import org.texttechnologylab.DockerUnifiedUIMAInterface.lua.DUUILuaContext; import org.texttechnologylab.annotation.NamedEntity; import org.texttechnologylab.project.gruppe_05_1.database.MongoDBHandler; +import org.texttechnologylab.project.gruppe_05_1.database.domainimp.speeches.Speech_MongoDB_Impl; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Content; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; import org.texttechnologylab.uima.type.Sentiment; import org.xml.sax.SAXException; @@ -42,6 +49,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -126,11 +134,12 @@ public class NlpUtils { /** * Initialization of a sample CAS document + * * @return * @throws ResourceInitializationException * @throws CASException */ - public static JCas getCas() { + public static JCas getCas() { // init a CAS with a static text. JCas pCas = null; try { @@ -155,7 +164,7 @@ public class NlpUtils { } - public static void runDockerDriver() { + public static void runDockerDriver() { // reset existing pipeline-components pComposer.resetPipeline(); @@ -195,7 +204,7 @@ public class NlpUtils { } JCasUtil.select(tCas, Sentence.class).stream().forEach(sentence -> { - System.out.println(sentence.getBegin()+"-"+sentence.getEnd()+": "+sentence.getCoveredText()); + System.out.println(sentence.getBegin() + "-" + sentence.getEnd() + ": " + sentence.getCoveredText()); System.out.println(JCasUtil.selectCovered(org.hucompute.textimager.uima.type.Sentiment.class, sentence)); }); } @@ -216,7 +225,7 @@ public class NlpUtils { jcas.setDocumentLanguage("de"); jcas.setDocumentText( - "Frau Präsidentin! Liebe Kolleginnen! Liebe Kollegen! Der Jahreswirtschaftsbericht war heute Gegenstand der Kabinettssitzung. Der Kollege Robert Habeck wird ihn im Wirtschaftsausschuss vorstellen, und morgen besteht ja auch hier Gelegenheit zur Debatte. Eine erfreuliche Nachricht ist, dass die Inflation zurückgeht. Eine der größten Bedrohungen für unsere wirtschaftliche Entwicklung und auch für den Lebensstandard der Bürgerinnen und Bürger ist die Geldentwertung. Im Zusammenwirken der Geldpolitik der Europäischen Zentralbank und der moderat restriktiven Fiskalpolitik der Bundesregierung haben wir große Fortschritte erzielt. Ich glaube, wir dürfen sagen: Die Entwicklung der Inflation ist nun beherrschbar geworden. Auf der anderen Seite ist die wirtschaftliche Entwicklung unseres Landes nicht zufriedenstellend. Wir haben eine zu geringe wirtschaftliche Dynamik. Dies hat damit zu tun, dass wir einen steigenden Zins und reduzierte Nachfrage auf den Weltmärkten aufgrund einer sich abkühlenden globalen Konjunktur haben, und auch die Folgen des Ausfalls günstiger fossiler Energieimporte nach Deutschland sind zu verzeichnen. Aber diese gegenwärtige Wachstumsschwäche unseres Landes passt sich ein in ein längeres Bild. In den vergangenen zehn Jahren, seit 2014, ist Deutschland in allen internationalen Standortvergleichen Schritt für Schritt zurückgefallen. Wir haben es also nicht mit einfachen Erklärungen zu tun, sondern mit strukturellen Aufgaben, denen wir uns stellen müssen. Ich leite daraus zwei Dinge ab: Erstens. Einfache Erklärungen sind nicht zutreffend. Zweitens. Alle, die in den vergangenen zehn Jahren Verantwortung getragen haben und heute Verantwortung tragen, sind aufgefordert, daran mitzuwirken, die Wachstumsdynamik in unserem Land zu verbessern. Ich will dazu konkret Folgendes sagen: Erstens. Die Bundesregierung setzt sich für eine Belebung auf unserem Arbeitsmarkt ein; denn der Mangel an Arbeitskräften ist eine Wachstumsbremse. In diesem Zusammenhang haben wir mit dem Fachkräfteeinwanderungsgesetz einen großen Fortschritt erzielt. Ihm müssen nun weitere Anstrengungen bei der Mobilisierung der Reserven unseres Arbeitsmarktes folgen. Zweitens. Die Bürokratiebelastung ist auf einem Allzeithoch seit dem Jahr 2012, in dem erstmals die Bürokratiebelastung gemessen worden ist. Mit den Meseberger Beschlüssen des Bundeskabinetts zum Bürokratieabbau werden diese Belastungen auf ein Allzeittief sinken, und wir müssen weitere Anstrengungen unternehmen, unsere Betriebe zu entfesseln. Drittens. Wir investieren auf einem Rekordniveau in Schiene, Straße, Wasserstraße, digitale Netze und in unsere Energieinfrastruktur. Aber diesen Anstrengungen müssen weitere folgen, insbesondere müssen jetzt die Rahmenbedingungen für private Investitionen und die Mobilisierung privaten Kapitals in Deutschland und Europa optimiert werden. Viertens. Unser steuerliches Umfeld, unsere steuerlichen Rahmenbedingungen müssen wettbewerbsfähiger werden. Die Bundesregierung und der Gesetzgeber haben ja bereits mit dem Zukunftsfinanzierungsgesetz Veränderungen vorgenommen, die sehr positiv wahrgenommen werden. Nun geht es darum, mit dem Wachstumschancengesetz einen weiteren Baustein gemeinsam zu beschließen, um im Bereich von Investitionsanreizen, zum Beispiel in der Baukonjunktur, und durch die Stärkung von privaten Forschungsvorhaben unserer Wirtschaft einen echten Schub zu geben. Hier kommt auch der Opposition eine besondere Verantwortung zu, mit dazu beizutragen, das wirtschaftliche Umfeld zu verbessern. Weitere Anstrengungen im Bereich der Steuerpolitik werden zu diskutieren sein. Liebe Kolleginnen und Kollegen, wir haben es gemeinsam im Zusammenwirken in Europa vermocht, die Geldentwertung unter Kontrolle zu bringen. Nun steht die nächste große Aufgabe vor uns: eine Wirtschaftswende, damit auch die Wachstumsdynamik unseres Landes wieder größer wird. " + "Frau Präsidentin! Liebe Kolleginnen! Liebe Kollegen! Der Jahreswirtschaftsbericht war heute Gegenstand der Kabinettssitzung. Der Kollege Robert Habeck wird ihn im Wirtschaftsausschuss vorstellen, und morgen besteht ja auch hier Gelegenheit zur Debatte. Eine erfreuliche Nachricht ist, dass die Inflation zurückgeht. Eine der größten Bedrohungen für unsere wirtschaftliche Entwicklung und auch für den Lebensstandard der Bürgerinnen und Bürger ist die Geldentwertung. Im Zusammenwirken der Geldpolitik der Europäischen Zentralbank und der moderat restriktiven Fiskalpolitik der Bundesregierung haben wir große Fortschritte erzielt. Ich glaube, wir dürfen sagen: Die Entwicklung der Inflation ist nun beherrschbar geworden. Auf der anderen Seite ist die wirtschaftliche Entwicklung unseres Landes nicht zufriedenstellend. Wir haben eine zu geringe wirtschaftliche Dynamik. Dies hat damit zu tun, dass wir einen steigenden Zins und reduzierte Nachfrage auf den Weltmärkten aufgrund einer sich abkühlenden globalen Konjunktur haben, und auch die Folgen des Ausfalls günstiger fossiler Energieimporte nach Deutschland sind zu verzeichnen. Aber diese gegenwärtige Wachstumsschwäche unseres Landes passt sich ein in ein längeres Bild. In den vergangenen zehn Jahren, seit 2014, ist Deutschland in allen internationalen Standortvergleichen Schritt für Schritt zurückgefallen. Wir haben es also nicht mit einfachen Erklärungen zu tun, sondern mit strukturellen Aufgaben, denen wir uns stellen müssen. Ich leite daraus zwei Dinge ab: Erstens. Einfache Erklärungen sind nicht zutreffend. Zweitens. Alle, die in den vergangenen zehn Jahren Verantwortung getragen haben und heute Verantwortung tragen, sind aufgefordert, daran mitzuwirken, die Wachstumsdynamik in unserem Land zu verbessern. Ich will dazu konkret Folgendes sagen: Erstens. Die Bundesregierung setzt sich für eine Belebung auf unserem Arbeitsmarkt ein; denn der Mangel an Arbeitskräften ist eine Wachstumsbremse. In diesem Zusammenhang haben wir mit dem Fachkräfteeinwanderungsgesetz einen großen Fortschritt erzielt. Ihm müssen nun weitere Anstrengungen bei der Mobilisierung der Reserven unseres Arbeitsmarktes folgen. Zweitens. Die Bürokratiebelastung ist auf einem Allzeithoch seit dem Jahr 2012, in dem erstmals die Bürokratiebelastung gemessen worden ist. Mit den Meseberger Beschlüssen des Bundeskabinetts zum Bürokratieabbau werden diese Belastungen auf ein Allzeittief sinken, und wir müssen weitere Anstrengungen unternehmen, unsere Betriebe zu entfesseln. Drittens. Wir investieren auf einem Rekordniveau in Schiene, Straße, Wasserstraße, digitale Netze und in unsere Energieinfrastruktur. Aber diesen Anstrengungen müssen weitere folgen, insbesondere müssen jetzt die Rahmenbedingungen für private Investitionen und die Mobilisierung privaten Kapitals in Deutschland und Europa optimiert werden. Viertens. Unser steuerliches Umfeld, unsere steuerlichen Rahmenbedingungen müssen wettbewerbsfähiger werden. Die Bundesregierung und der Gesetzgeber haben ja bereits mit dem Zukunftsfinanzierungsgesetz Veränderungen vorgenommen, die sehr positiv wahrgenommen werden. Nun geht es darum, mit dem Wachstumschancengesetz einen weiteren Baustein gemeinsam zu beschließen, um im Bereich von Investitionsanreizen, zum Beispiel in der Baukonjunktur, und durch die Stärkung von privaten Forschungsvorhaben unserer Wirtschaft einen echten Schub zu geben. Hier kommt auch der Opposition eine besondere Verantwortung zu, mit dazu beizutragen, das wirtschaftliche Umfeld zu verbessern. Weitere Anstrengungen im Bereich der Steuerpolitik werden zu diskutieren sein. Liebe Kolleginnen und Kollegen, wir haben es gemeinsam im Zusammenwirken in Europa vermocht, die Geldentwertung unter Kontrolle zu bringen. Nun steht die nächste große Aufgabe vor uns: eine Wirtschaftswende, damit auch die Wachstumsdynamik unseres Landes wieder größer wird. " ); Collection sentences = JCasUtil.select(jcas, Sentence.class); @@ -237,8 +246,7 @@ public class NlpUtils { for (NamedEntity entity : JCasUtil.select(jcas, NamedEntity.class)) { if (entity.getValue().equals("PER")) { System.out.println("Person: " + entity.getCoveredText()); - } - else if (entity.getValue().equals("LOC")) { + } else if (entity.getValue().equals("LOC")) { System.out.println("Location: " + entity.getCoveredText()); } } @@ -253,9 +261,9 @@ public class NlpUtils { } - /** * Execution of video processing via DUUI using the RemoteDriver + * * @throws Exception */ public static void runVideos() throws Exception { @@ -307,12 +315,12 @@ public class NlpUtils { pComposer.run(pCas); // select some data - JCasUtil.selectAll(videoCas).stream().forEach(videoAnnotation->{ + JCasUtil.selectAll(videoCas).stream().forEach(videoAnnotation -> { System.out.println(videoAnnotation); }); // select some data - JCasUtil.selectAll(transcriptCas).stream().forEach(tAnnotation->{ + JCasUtil.selectAll(transcriptCas).stream().forEach(tAnnotation -> { System.out.println(tAnnotation); }); @@ -331,4 +339,129 @@ public class NlpUtils { } + public static void runRemoteDriver() throws Exception { + DUUILuaContext luaContext = new DUUILuaContext().withJsonLibrary(); + pComposer = new DUUIComposer() + .withSkipVerification(true) + .withLuaContext(luaContext) + .withWorkers(iWorkers); + + pComposer.addDriver(new DUUIRemoteDriver()); + MongoDBHandler mongoDBHandler = new MongoDBHandler(); + Bson filter = Filters.exists("analysisResults", false); + List unprocessedSpeeches = mongoDBHandler.retrieveAllSpeeches(filter); + if (unprocessedSpeeches.isEmpty()) { + System.out.println("No unprocessed speeches found"); + } + else { + pComposer.resetPipeline(); + + pComposer.add(new DUUIRemoteDriver.Component("http://spacy.lehre.texttechnologylab.org") + .withScale(iWorkers) + .build()); + pComposer.add(new DUUIRemoteDriver.Component("http://gervader.lehre.texttechnologylab.org") + .withScale(iWorkers) + .build()); + List> bulkOperations = new ArrayList<>(); + for (Speech rede : unprocessedSpeeches) { + JCas jCas; + jCas = rede.toCas(); + pComposer.run(jCas); + System.out.println("Anzahl Sentiment-Annotationen: " + JCasUtil.select(jCas, org.hucompute.textimager.uima.type.Sentiment.class).size()); + Document analysisResults = extractAnnotations(jCas); + Bson updateFilter = Filters.eq("speechKey", rede.getSpeechKey()); + Bson update = new Document("$set", new Document("analysisResults", analysisResults)); + bulkOperations.add(new UpdateOneModel<>(updateFilter, update)); + } + if (!bulkOperations.isEmpty()) { + mongoDBHandler.bulkWriteNlpData(bulkOperations); + System.out.println("Bulk write completed for " + bulkOperations.size() + " documents."); + mongoDBHandler.close(); + } + } + } + + + /** + * @param jCas + * Liest die Annotations aus dem JCas Objekt und speichet sie in Listen ab jeweils + */ + public static Document extractAnnotations(JCas jCas) { + Document analysisResults = new Document(); + + // Tokens: Include POS, Lemma, etc. + List tokens = new ArrayList<>(); + for (Token token : JCasUtil.select(jCas, Token.class)) { + Document tokenDoc = new Document() + .append("text", token.getCoveredText()) + .append("pos", token.getPos().getPosValue()) + .append("lemma", token.getLemma().getValue()); + tokens.add(tokenDoc); + } + analysisResults.append("tokens", tokens); + + // Sentences + List sentences = JCasUtil.select(jCas, Sentence.class).stream() + .map(Sentence::getCoveredText) + .collect(Collectors.toList()); + analysisResults.append("sentences", sentences); + + // Dependencies + List dependencies = new ArrayList<>(); + for (Dependency dep : JCasUtil.select(jCas, Dependency.class)) { + Document depDoc = new Document() + .append("type", dep.getDependencyType()) + .append("governor", dep.getGovernor().getCoveredText()) + .append("dependent", dep.getDependent().getCoveredText()); + dependencies.add(depDoc); + } + analysisResults.append("dependencies", dependencies); + + // Named Entities + List namedEntities = new ArrayList<>(); + for (de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity ne : JCasUtil.select(jCas, de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity.class)) { + Document neDoc = new Document() + .append("text", ne.getCoveredText()) + .append("type", ne.getValue()); + namedEntities.add(neDoc); + } + analysisResults.append("namedEntities", namedEntities); + + // Sentiment + List sentiments = new ArrayList<>(); + for (org.hucompute.textimager.uima.type.Sentiment sentiment : + JCasUtil.select(jCas, org.hucompute.textimager.uima.type.Sentiment.class)) { + + Document sentimentDoc = new Document() + .append("begin", sentiment.getBegin()) + .append("end", sentiment.getEnd()) + .append("score", sentiment.getSentiment()) + .append("subjectivity", sentiment.getSubjectivity()); + + // Check for VaderSentiment subtype + if (sentiment instanceof org.hucompute.textimager.uima.type.VaderSentiment) { + org.hucompute.textimager.uima.type.VaderSentiment vader = + (org.hucompute.textimager.uima.type.VaderSentiment) sentiment; + sentimentDoc + .append("pos", vader.getPos()) + .append("neu", vader.getNeu()) + .append("neg", vader.getNeg()); + } + sentiments.add(sentimentDoc); + } + analysisResults.append("sentiments", sentiments); + + List topics = new ArrayList<>(); + for (CategoryCoveredTagged topic : JCasUtil.select(jCas, CategoryCoveredTagged.class)) { + Document topicDoc = new Document() + .append("topic", topic.getValue()) + .append("score", topic.getScore()) + .append("tags", topic.getTags()) + .append("text", topic.getCoveredText()); + topics.add(topicDoc); + } + topics.sort((d1, d2) -> Double.compare(d2.getDouble("score"), d1.getDouble("score"))); + analysisResults.append("topics", topics); + return analysisResults; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java index 3e56e40..dbd9165 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java @@ -3,10 +3,13 @@ package org.texttechnologylab.project.gruppe_05_1.nlp; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; +import com.mongodb.client.model.UpdateOneModel; +import com.mongodb.client.model.WriteModel; import com.mongodb.client.result.UpdateResult; import org.apache.uima.fit.util.JCasUtil; import org.bson.Document; import java.io.*; +import java.net.URL; import java.util.zip.*; import java.util.*; import java.util.stream.Collectors; @@ -19,16 +22,24 @@ import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token; import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence; import de.tudarmstadt.ukp.dkpro.core.api.syntax.type.dependency.Dependency; import de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity; +import org.texttechnologylab.project.gruppe_05_1.database.MongoDBHandler; +import org.hucompute.textimager.uima.type.category.CategoryCoveredTagged; + public class XmiExtractor { - private MongoDatabase database; // Removed 'static' - public XmiExtractor(MongoDatabase database) { - this.database = database; + private List> bulkOperations; + private MongoDBHandler mongoDBHandler; + private static final int BATCH_SIZE = 1000; + private int processedCount = 0; + public XmiExtractor() { + mongoDBHandler = new MongoDBHandler(); + this.bulkOperations = new ArrayList<>(); } public void extractAndUploadXmiData() throws IOException { - try (ZipInputStream zis = new ZipInputStream(new FileInputStream("C:/Users/Leon/Desktop/Uni/PPR/multimodal_parliament_explorer_05_1/src/main/resources/speeches/20.zip"))) { + InputStream resourceStream = getClass().getClassLoader().getResourceAsStream("speeches/20.zip"); + try (ZipInputStream zis = new ZipInputStream(resourceStream)) { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { if (entry.getName().endsWith(".xmi.gz")) { @@ -44,11 +55,13 @@ public class XmiExtractor { zis.closeEntry(); } } + flushBatch(); } private void processXmiGzStream(InputStream inputStream, String filename) { + JCas jCas = null; try (GZIPInputStream gis = new GZIPInputStream(inputStream)) { - JCas jCas = JCasFactory.createJCas(); + jCas = JCasFactory.createJCas("src/main/resources/speeches/TypeSystem"); XmiCasDeserializer.deserialize(gis, jCas.getCas(), true); // Build structured analysisResults Document @@ -116,18 +129,44 @@ public class XmiExtractor { } analysisResults.append("sentiments", sentiments); + List topics = new ArrayList<>(); + for (CategoryCoveredTagged topic : JCasUtil.select(jCas, CategoryCoveredTagged.class)) { + Document topicDoc = new Document() + .append("topic", topic.getValue()) + .append("score", topic.getScore()) + .append("tags", topic.getTags()) + .append("text", topic.getCoveredText()); + topics.add(topicDoc); + } + topics.sort((d1, d2) -> Double.compare(d2.getDouble("score"), d1.getDouble("score"))); + analysisResults.append("topics", topics); - // TODO Hochladen Topics implementieren // Upload structured Document to MongoDB String speechKey = extractSpeechKeyFromFilename(filename); if (speechKey != null) { - uploadToMongoDB(speechKey, analysisResults); + Bson filter = Filters.eq("speechKey", speechKey); + Bson update = new Document("$set", new Document("analysisResults", analysisResults)); + UpdateOneModel updateModel = new UpdateOneModel<>(filter, update); + bulkOperations.add(updateModel); + if (bulkOperations.size() >= BATCH_SIZE) { + flushBatch(); + } + processedCount++; + if (processedCount % 5000 == 0) { + System.out.println("Processed speeches: " + processedCount); + } + } } catch (Exception e) { e.printStackTrace(); } + finally { + if (jCas != null) { + jCas.reset(); + } + } } private static String extractSpeechKeyFromFilename(String filename) { @@ -135,27 +174,17 @@ public class XmiExtractor { return baseName.replace("20/", ""); } - private void uploadToMongoDB(String speechKey, Document analysisResults) { - MongoCollection collection = database.getCollection("speech"); - Bson filter = Filters.eq("speechKey", speechKey); - Bson update = new Document("$set", new Document("analysisResults", analysisResults)); - - UpdateResult result = collection.updateOne(filter, update); - if (result.getModifiedCount() > 0) { - System.out.println("Structured analysisResults updated for speechKey: " + speechKey); - } else { - System.out.println("Data has already been uploaded for speechKey: " + speechKey); + private void flushBatch() { + if (!bulkOperations.isEmpty()) { + mongoDBHandler.bulkWriteNlpData(bulkOperations); + bulkOperations.clear(); } } - public MongoDatabase getDatabase() { - return this.database; - } - /*public static void main(String[] args) { + /* + public static void main(String[] args) { try { - MongoDBHandler mongoDBHandler = new MongoDBHandler(); - MongoDatabase database = mongoDBHandler.getDatabase(); // Now works! XmiExtractor extractor = new XmiExtractor(database); extractor.extractAndUploadXmiData(); System.out.println("Processing complete."); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speech_File_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speech_File_Impl.java index 2d1dff8..dfe03ee 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speech_File_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speech_File_Impl.java @@ -1,6 +1,8 @@ package org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls; import lombok.Getter; +import org.apache.uima.UIMAException; +import org.apache.uima.jcas.JCas; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Content; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.enums.MongoDBEntryType; @@ -92,4 +94,14 @@ public class Speech_File_Impl implements Speech { + ""; } + @Override + public String getFullText() { + return ""; + } + + @Override + public JCas toCas() throws UIMAException { + return null; + } + } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Speech.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Speech.java index 9445234..642a24c 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Speech.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Speech.java @@ -1,5 +1,7 @@ package org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces; +import org.apache.uima.UIMAException; +import org.apache.uima.jcas.JCas; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.enums.MongoDBEntryType; import java.util.List; @@ -79,4 +81,8 @@ public interface Speech { * @return The HTML representation of the agenda item. */ String toHTML(); + + String getFullText(); + + JCas toCas() throws UIMAException; } From c64a2804054554d8648f8c164615f8a5f8140c74 Mon Sep 17 00:00:00 2001 From: Picman2000 <65342372+Picman2000@users.noreply.github.com> Date: Mon, 10 Mar 2025 12:40:39 +0100 Subject: [PATCH 3/4] small import fix cause i dont know my merge requests --- .../java/org/texttechnologylab/project/gruppe_05_1/Main.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java index a83e9d0..a2c51eb 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/Main.java @@ -2,6 +2,8 @@ package org.texttechnologylab.project.gruppe_05_1; import org.texttechnologylab.project.gruppe_05_1.database.*; +import org.texttechnologylab.project.gruppe_05_1.nlp.NlpUtils; +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; @@ -84,7 +86,6 @@ public class Main { // Alle Informationen (Parlamentarier, Reden, Kommentare etc.) lesen und in die Mongo-DB einfügen, falls diese noch nicht vorhanden sind. PPRUtils.parlamentExplorerInit(xmlFactory, mongoFactory); - MongoDBHandler mongoDBHandler = new MongoDBHandler(); //das muss auf jeden fall noch angepasst werden xd if(mongoDBHandler.checkAnalysisResultsField() < 21518) { try { From 8439b52f65533a90df4dd3c2dd66083db3969a91 Mon Sep 17 00:00:00 2001 From: vysitor Date: Mon, 10 Mar 2025 18:15:55 +0100 Subject: [PATCH 4/4] Frontend: List of Speeches is now displayed --- .../gruppe_05_1/database/MongoPprUtils.java | 129 ++++++++++++++++++ .../domain/speech/SpeechMetaData.java | 104 ++++++++++++++ .../rest/ParlamentarierController.java | 15 +- .../project/gruppe_05_1/rest/RESTHandler.java | 12 +- .../gruppe_05_1/rest/SpeechController.java | 105 ++++++++++++++ .../gruppe_05_1/util/GeneralUtils.java | 8 ++ .../templates/parlamentarierDetails.ftl | 4 +- .../website/templates/showSpeechesList.ftl | 43 ++++++ 8 files changed, 407 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/speech/SpeechMetaData.java create mode 100644 src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java create mode 100644 src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/showSpeechesList.ftl diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java index b020bbf..6199798 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java @@ -1,14 +1,22 @@ package org.texttechnologylab.project.gruppe_05_1.database; +import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import org.bson.Document; +import org.texttechnologylab.project.gruppe_05_1.database.domainimp.speeches.Speech_MongoDB_Impl; 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.speaker.Membership; +import org.texttechnologylab.project.gruppe_05_1.domain.speech.SpeechMetaData; +import org.texttechnologylab.project.gruppe_05_1.util.GeneralUtils; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Speech_File_Impl; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; /** @@ -32,6 +40,8 @@ public class MongoPprUtils { private static MongoCollection speakerCollection = null; private static MongoCollection speechCollection = null; + private static MongoCollection sessionCollection = null; + private static MongoCollection agendaItemsCollection = null; private static MongoCollection picturesCollection = null; private static MongoCollection commentCollection = null; @@ -45,6 +55,15 @@ public class MongoPprUtils { return speechCollection; } + public static MongoCollection getSessionCollection() { + if (sessionCollection == null) sessionCollection = MongoDBHandler.getMongoDatabase().getCollection(SESSION_COLLECTION_NAME); + return sessionCollection; + } + + public static MongoCollection getAgendaItemsCollection() { + if (agendaItemsCollection == null) agendaItemsCollection = MongoDBHandler.getMongoDatabase().getCollection(AGENDA_ITEMS_COLLECTION_NAME); + return agendaItemsCollection; + } /** * Create the Speaker Collection and useful indices for it @@ -259,4 +278,114 @@ public class MongoPprUtils { } // TODO: kopiere die Speech-Sachen von Übung 4 hierher! + + /** + * Aufzählen, wie viele Reden eines bestimmten Redners gespeichert sind + * @param speakerId + * @return Anzahl Reden + */ + public static Long countSpeechesOfSpeaker(String speakerId) { + return getSpeechCollection().countDocuments(new Document("speakerId", Integer.parseInt(speakerId))); + } + + + /** + * Liefert alle Reden eines Redners zurück + * @param speakerId + * @return Alle Reden eines Redners + */ + public static List getSpeechesOfSpeaker(String speakerId) { + List speeches = new ArrayList<>(); + + Document filter = new Document("speakerId", Integer.parseInt(speakerId)); + List docs = getSpeechCollection().find(filter).into(new ArrayList<>()); + + for (Document doc : docs) { + speeches.add(new Speech_MongoDB_Impl(doc)); + } + + return speeches; + } + + /** + * Liefert Metadaten (aber keine Inhalte!) für alle Reden eines Redners zurück. + * Als Metadaten zählen das Datum, Agenda-ID etc. + * @param speakerId + * @return + */ + public static List getSpeechesMetadataForSeaker(String speakerId) { + + List speechMetaDataList = new ArrayList<>(); + List speeches = MongoPprUtils.getSpeechesOfSpeaker(speakerId); + for (Speech speech : speeches) { + SpeechMetaData md = new SpeechMetaData(); + + md.setSpeechKey(speech.getSpeechKey()); + md.setSpeechId(speech.getSpeechId()); + md.setSpeakerId(speech.getSpeakerId()); + int sessionId = speech.getSessionId(); + md.setSessionId(sessionId); + + + // aus "sessions" Collection + String dateTimeString = getSessionDateTime(sessionId); + if (dateTimeString != null) { + md.setDateTimeString(dateTimeString); + LocalDateTime tmp = GeneralUtils.parseDateTime(dateTimeString, "dd.MM.yyyy HH:mm"); + if (tmp == null) { + tmp = GeneralUtils.parseDateTime(dateTimeString, "dd.MM.yyyy H:mm"); + if (tmp == null) { + System.out.println(dateTimeString + " could not be parsed"); + } + } + md.setDateTime(tmp); + } + + // aus "agendaItems" Collection + int agendaItemId = speech.getAgendaItemId(); + String agendaTitel = getAgendaTitle(sessionId, agendaItemId); + md.setAgendaTitle(agendaTitel); + + speechMetaDataList.add(md); + + } + + // Sortiere nach Datum, absteigend + speechMetaDataList.sort((md1, md2) -> { + return md2.getDateTime().compareTo(md1.getDateTime()); + }); + + return speechMetaDataList; + } + + + /** + * Liefert das Datum und die Uhrzeit einer Sitzung zurück + * @param sessionId + * @return + */ + public static String getSessionDateTime(int sessionId) { + Document filter = new Document("sessionId", sessionId); + Object dateTime = getSessionCollection().find(filter).first().get("dateTime"); + if (dateTime == null) { + return null; + } else { + return (String) dateTime; + } + } + + /** + * Liefert den Agenda-Titel zurück + * @param sessionId + * @return + */ + public static String getAgendaTitle(int sessionId, int agendaItemId) { + Document filter = new Document("sessionId", sessionId).append("id", agendaItemId); + FindIterable iter = getAgendaItemsCollection().find(filter); + if ((iter == null || (iter.first() == null))) { + return "(kein Agendatitel)"; + } else { + return (String) iter.first().get("title"); + } + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/speech/SpeechMetaData.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/speech/SpeechMetaData.java new file mode 100644 index 0000000..bb9d55d --- /dev/null +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/speech/SpeechMetaData.java @@ -0,0 +1,104 @@ +package org.texttechnologylab.project.gruppe_05_1.domain.speech; + +import java.time.LocalDateTime; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * 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 speakerId; + int sessionId; // TODO: nötig? + + // aus "sessions" Collection + LocalDateTime dateTime; + String dateTimeString; + + // aus "agendaItems" Collection + String agendaTitle; + + public String getSpeechKey() { + return speechKey; + } + + public void setSpeechKey(String speechKey) { + this.speechKey = speechKey; + } + + public int getSpeechId() { + return speechId; + } + + public void setSpeechId(int speechId) { + this.speechId = speechId; + } + + public int getSpeakerId() { + return speakerId; + } + + public void setSpeakerId(int speakerId) { + this.speakerId = speakerId; + } + + public int getSessionId() { + return sessionId; + } + + public void setSessionId(int sessionId) { + this.sessionId = sessionId; + } + + public LocalDateTime getDateTime() { + return dateTime; + } + + public void setDateTime(LocalDateTime dateTime) { + this.dateTime = dateTime; + } + + public String getDateTimeString() { + return dateTimeString; + } + + public void setDateTimeString(String dateTimeString) { + this.dateTimeString = dateTimeString; + } + + public String getAgendaTitle() { + return agendaTitle; + } + + public void setAgendaTitle(String agendaTitle) { + this.agendaTitle = agendaTitle; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SpeechMetaData that)) return false; + return speechId == that.speechId && speakerId == that.speakerId && sessionId == that.sessionId && Objects.equals(speechKey, that.speechKey) && Objects.equals(dateTime, that.dateTime) && Objects.equals(dateTimeString, that.dateTimeString) && Objects.equals(agendaTitle, that.agendaTitle); + } + + @Override + public int hashCode() { + return Objects.hash(speechKey, speechId, speakerId, sessionId, dateTime, dateTimeString, agendaTitle); + } + + @Override + public String toString() { + return new StringJoiner(", ", SpeechMetaData.class.getSimpleName() + "[", "]") + .add("speechKey='" + speechKey + "'") + .add("speechId=" + speechId) + .add("speakerId=" + speakerId) + .add("sessionId=" + sessionId) + .add("dateTime=" + dateTime) + .add("dateTimeString='" + dateTimeString + "'") + .add("agendaTitle='" + agendaTitle + "'") + .toString(); + } +} diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/ParlamentarierController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/ParlamentarierController.java index aaed14d..6a63a9a 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/ParlamentarierController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/ParlamentarierController.java @@ -6,7 +6,9 @@ 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.database.MongoPprUtils; import org.texttechnologylab.project.gruppe_05_1.util.PPRUtils; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,6 +33,8 @@ public class ParlamentarierController { * @param ctx JavaLin-Context */ + private static List emptyList = new ArrayList<>(); // passed as an indicator if a certain list exists or not (in latter case: pass null) + @OpenApi( summary = "Get alle Parlamentarier. Man kann nach Vor-, Nachname oder Partei filtern.", description = "Listet alle Parlamentarier bzw. diejenige, welche den Filter entsprechen", @@ -88,7 +92,16 @@ public class ParlamentarierController { Map attributes = new HashMap<>(); attributes.put("p", pd); - attributes.put("speechesCount", pd.getReden() == null ? 0 : pd.getReden().size()); + Long speechCount = MongoPprUtils.countSpeechesOfSpeaker(pd.getId()); + attributes.put("speechesCount", speechCount); + if (speechCount == 0) { + attributes.put("speechesPlaceholder", null); + } else { + attributes.put("speechesPlaceholder", emptyList); + } + + + List speeches = MongoPprUtils.getSpeechesOfSpeaker(pd.getId()); ctx.render("parlamentarierDetails.ftl", attributes); } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java index 1f5561c..1eb08d6 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java @@ -57,17 +57,9 @@ public class RESTHandler { app.get("/portfolio/{id}", ParlamentarierController::getParlamentarierDetails); app.delete("/deleteParlamentarier", ParlamentarierController::deleteAllParlamentarier); - /* - TODO - // Fotos - app.get("/editFoto/{id}", FotosController::editFotos); - app.post("/editFoto/updateFotoUrl/{id}/{pictureId}", FotosController::updateFotoUrl); - app.post("/editFoto/defineFotoAsPrimary/{id}", FotosController::defineFotoAsPrimary); - // Reden - app.get("/reden/{id}", RedenController::listSpeeches); // zeige Reden eines Parlamentariers an - app.get("/reden/{id}/{redeId}", RedenController::showSpeech); // zeige eine bestimmte Rede des Parlamentariers an - app.post("/reden/updateComment/{id}/{speechId}/{commentId}", RedenController::updateComment); // aktualisiere Änderung an einer Kommentar + 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 - */ } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java new file mode 100644 index 0000000..999c258 --- /dev/null +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java @@ -0,0 +1,105 @@ +package org.texttechnologylab.project.gruppe_05_1.rest; + +import io.javalin.http.Context; +import io.javalin.openapi.*; +import org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils; +import org.texttechnologylab.project.gruppe_05_1.domain.html.ParlamentarierDetails; +import org.texttechnologylab.project.gruppe_05_1.domain.speech.Protocol; +import org.texttechnologylab.project.gruppe_05_1.domain.speech.SpeechMetaData; +import org.texttechnologylab.project.gruppe_05_1.util.GeneralUtils; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Comment; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SpeechController { + /** + * Liste alle Reden eines Parlamentariers an + * @param ctx Javalin Context + */ + @OpenApi( + summary = "Liste alle Reden eines Parlamentariers an", + description = "Liste alle Reden eines Parlamentariers an", + operationId = "listSpeeches", + path = "/reden/{id}", + methods = HttpMethod.GET, + tags = {"Rede"}, + pathParams = { + @OpenApiParam(name = "id", description = "id des Parlamentariers", required = true), + }, + responses = { + @OpenApiResponse(status = "200", content = {@OpenApiContent(from = Speech[].class)}) + }) + public static void listSpeeches(Context ctx) { + String parlamentarierId = ctx.pathParam("id"); + + ParlamentarierDetails p = MongoPprUtils.getParlamentarierDetailsByID(parlamentarierId); + List speechMetaDataList = MongoPprUtils.getSpeechesMetadataForSeaker(parlamentarierId); + + Map attributes = new HashMap<>(); + attributes.put("p", p); + attributes.put("speechesMetaDataList", speechMetaDataList); + ctx.render("showSpeechesList.ftl", attributes); + } + + /** + * Zeige eine bestimmte Rede des Parlamentariers an + * @param ctx Javalin Context + */ + @OpenApi( + summary = "Zeige eine bestimmte Rede des Parlamentariers an", + description = "Zeige eine bestimmte Rede des Parlamentariers an", + operationId = "showSpeech", + path = "/reden/{id}/{redeID}", + methods = HttpMethod.GET, + tags = {"Rede"}, + pathParams = { + @OpenApiParam(name = "id", description = "id des Parlamentariers", required = true), + @OpenApiParam(name = "redeId", description = "id der Rede", required = true), + }, + responses = { + @OpenApiResponse(status = "200", content = {@OpenApiContent(from = Speech.class)}) + }) + public static void showSpeech(Context ctx) { + String parlamentarierId = ctx.pathParam("id"); + String redeId = ctx.pathParam("redeId"); + + Map attributes = new HashMap<>(); + + /* + Speech rede = MongoPprUtils.getSpeechesById(redeId); + List comments = MongoPprUtils.getCommentsForSpeech(redeId); + ParlamentarierDetails p = MongoPprUtils.getParlamentarierDetailsByID(parlamentarierId); + + + attributes.put("p", p); + attributes.put("rede", rede); + attributes.put("comments", comments.size() > 0 ? comments : null); + Protocol protocol = rede.getProtocol(); + if (protocol == null) { + attributes.put("date", "(keine Angaben)"); + attributes.put("time", "(keine Angaben)"); + } else { + LocalDate date = protocol.getDate(); + LocalTime time = protocol.getStarttime(); + if (date == null) { + attributes.put("date", "(keine Angaben)"); + } else { + attributes.put("date", GeneralUtils.formatDate(date)); + } + if (time == null) { + attributes.put("time", "(keine Angaben)"); + } else { + attributes.put("time", GeneralUtils.formatTime(time)); + } + } + + */ + ctx.render("speechWithComments.ftl", attributes); + } + +} diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/GeneralUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/GeneralUtils.java index 0b013a3..d67d198 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/GeneralUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/GeneralUtils.java @@ -1,6 +1,7 @@ package org.texttechnologylab.project.gruppe_05_1.util; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -74,4 +75,11 @@ public abstract class GeneralUtils { return time.format(DateTimeFormatter.ofPattern("HH.mm")); } + public static LocalDateTime parseDateTime(String dateTime, String timeFormat) { + try { + return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern(timeFormat)); + } catch (DateTimeParseException ex) { + return null; + } + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/parlamentarierDetails.ftl b/src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/parlamentarierDetails.ftl index 0ad5435..732a4ef 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/parlamentarierDetails.ftl +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/parlamentarierDetails.ftl @@ -26,10 +26,10 @@

Reden

- <#if p.reden??> + <#if speechesPlaceholder??> ${speechesCount} Reden vorhanden <#else> - Keine Reden + Keine Reden vorhanden

diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/showSpeechesList.ftl b/src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/showSpeechesList.ftl new file mode 100644 index 0000000..fc8ba12 --- /dev/null +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/website/templates/showSpeechesList.ftl @@ -0,0 +1,43 @@ + + + + + + Reden von ${p.vorname} ${p.nachname} (${p.partei}) + + + +
+

Reden von ${p.vorname} ${p.nachname} (${p.partei})

+
+ +
+
+ + + + + + + + + + + <#list speechesMetaDataList as redeMd> + + + + + + + +
DatumSitzung / Agenda
${redeMd.dateTimeString}${redeMd.sessionId} / ${redeMd.agendaTitle}
+
+
+ \ No newline at end of file