s5260822 2025-03-10 18:39:06 +01:00
commit 8e8a12462d
21 changed files with 785 additions and 165 deletions

BIN
src/.DS_Store vendored

Binary file not shown.

BIN
src/main/.DS_Store vendored

Binary file not shown.

Binary file not shown.

View file

@ -1,26 +1,18 @@
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;
@ -54,13 +46,13 @@ 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
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 +71,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,22 +81,27 @@ 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);
// Upload der analysierten XMI dateien
// NLP-Verarbeitung - TODO
// NlpUtils.importXmiData();
//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();

View file

@ -3,21 +3,18 @@ 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;
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 +22,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 +45,8 @@ public class MongoDBHandler {
private static String collection;
private static String databaseName;
private MongoCollection<Document> speakerCollection;
private MongoCollection<Document> speechesCollection;
private MongoCollection<Document> sessionsCollection;
private MongoCollection<Document> agendaItemsCollection;
private MongoCollection<Document> historyCollection;
@ -71,27 +67,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 +115,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 +172,9 @@ public class MongoDBHandler {
*
* @return List<String> with the names of all collections
*/
static public Set<String> getCollectionNames() {
// return getMongoDatabase().listCollectionNames().into(new ArrayList<>());
return getMongoDatabase().listCollectionNames().into(new HashSet<>());
public Set<String> getCollectionNames() {
// return getDatabase().listCollectionNames().into(new ArrayList<>());
return getDatabase().listCollectionNames().into(new HashSet<>());
}
/**
@ -168,8 +182,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 +207,8 @@ public class MongoDBHandler {
}
}
static public void createCollectionIfNotExist(String collectionName) {
createCollectionIfNotExist(getMongoDatabase(), collectionName);
public void createCollectionIfNotExist(String collectionName) {
createCollectionIfNotExist(getDatabase(), collectionName);
}
@ -211,8 +225,8 @@ public class MongoDBHandler {
}
}
static public void createCollection(String collectionName) {
createCollection(getMongoDatabase(), collectionName);
public void createCollection(String collectionName) {
createCollection(getDatabase(), collectionName);
}
@ -261,8 +275,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,16 +677,30 @@ public class MongoDBHandler {
);
}
public void deleteAllDocuments() {
public void deleteSpeechRelatedDocuments() {
speechesCollection.deleteMany(new Document());
sessionsCollection.deleteMany(new Document());
agendaItemsCollection.deleteMany(new Document());
//historyCollection.deleteMany(new Document());
}
public void bulkUpdateDocuments(String collectionName, List<WriteModel<Document>> updates) {
BulkWriteOptions options = new BulkWriteOptions().ordered(false);
speechesCollection.bulkWrite(updates, options);
public void bulkWriteNlpData(List<WriteModel<Document>> 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() {

View file

@ -1,22 +1,28 @@
package org.texttechnologylab.project.gruppe_05_1.database;
import com.mongodb.client.FindIterable;
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.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.*;
/**
* 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,11 +31,17 @@ 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";
private static MongoCollection<Document> speakerCollection = null;
private static MongoCollection<Document> speechCollection = null;
private static MongoCollection<Document> sessionCollection = null;
private static MongoCollection<Document> agendaItemsCollection = null;
private static MongoCollection<Document> picturesCollection = null;
private static MongoCollection<Document> commentCollection = null;
@ -43,53 +55,35 @@ public class MongoPprUtils {
return speechCollection;
}
public static MongoCollection<Document> getPicturesCollection() {
if (picturesCollection == null) picturesCollection = MongoDBHandler.getMongoDatabase().getCollection(PICTURES_COLLECTION_NAME);
return picturesCollection;
public static MongoCollection<Document> getSessionCollection() {
if (sessionCollection == null) sessionCollection = MongoDBHandler.getMongoDatabase().getCollection(SESSION_COLLECTION_NAME);
return sessionCollection;
}
public static MongoCollection<Document> getCommentCollection() {
if (commentCollection == null) commentCollection = MongoDBHandler.getMongoDatabase().getCollection(COMMENT_COLLECTION_NAME);
return commentCollection;
public static MongoCollection<Document> getAgendaItemsCollection() {
if (agendaItemsCollection == null) agendaItemsCollection = MongoDBHandler.getMongoDatabase().getCollection(AGENDA_ITEMS_COLLECTION_NAME);
return agendaItemsCollection;
}
/**
* 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 +91,7 @@ public class MongoPprUtils {
public static void truncateSpeakerCollection() {
getSpeakerCollection().drop();
createSpeechCollection();
createIndexForSpeechCollection();
}
/*
@ -284,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<Speech> getSpeechesOfSpeaker(String speakerId) {
List<Speech> speeches = new ArrayList<>();
Document filter = new Document("speakerId", Integer.parseInt(speakerId));
List<Document> 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<SpeechMetaData> getSpeechesMetadataForSeaker(String speakerId) {
List<SpeechMetaData> speechMetaDataList = new ArrayList<>();
List<Speech> 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<Document> iter = getAgendaItemsCollection().find(filter);
if ((iter == null || (iter.first() == null))) {
return "(kein Agendatitel)";
} else {
return (String) iter.first().get("title");
}
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -1,8 +1,14 @@
package org.texttechnologylab.project.gruppe_05_1.nlp;
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.cas.CASException;
@ -10,13 +16,23 @@ import org.apache.uima.fit.factory.JCasFactory;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
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;
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;
@ -26,6 +42,10 @@ import java.net.URL;
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;
import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
@ -108,7 +128,7 @@ public class NlpUtils {
* Initialization of a sample CAS document
* @return JCas object
*/
public static JCas getCas() {
public static JCas getCas() {
// init a CAS with a static text.
JCas pCas;
try {
@ -133,7 +153,7 @@ public class NlpUtils {
}
public static void runDockerDriver() {
public static void runDockerDriver() {
// reset existing pipeline-components
pComposer.resetPipeline();
@ -194,7 +214,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<Sentence> sentences = JCasUtil.select(jcas, Sentence.class);
@ -215,8 +235,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());
}
}
@ -231,7 +250,6 @@ public class NlpUtils {
}
/**
* Execution of video processing via DUUI using the RemoteDriver
* @throws Exception in case of an error
@ -306,4 +324,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<Speech> 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<WriteModel<Document>> 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<Document> 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<String> sentences = JCasUtil.select(jCas, Sentence.class).stream()
.map(Sentence::getCoveredText)
.collect(Collectors.toList());
analysisResults.append("sentences", sentences);
// Dependencies
List<Document> 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<Document> 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<Document> 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<Document> 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;
}
}

View file

@ -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<WriteModel<Document>> 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<Document> 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<Document> 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<Document> 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.");

View file

@ -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<Integer> 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<String, Object> 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<Speech> speeches = MongoPprUtils.getSpeechesOfSpeaker(pd.getId());
ctx.render("parlamentarierDetails.ftl", attributes);
}

View file

@ -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
*/
}
}

View file

@ -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<SpeechMetaData> speechMetaDataList = MongoPprUtils.getSpeechesMetadataForSeaker(parlamentarierId);
Map<String, Object> 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<String, Object> attributes = new HashMap<>();
/*
Speech rede = MongoPprUtils.getSpeechesById(redeId);
List<Comment> 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);
}
}

View file

@ -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;
}
}
}

View file

@ -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<String> 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

View file

@ -26,10 +26,10 @@
<main>
<section>
<h2>Reden</h2>
<#if p.reden??>
<#if speechesPlaceholder??>
<a href="/reden/${p.id}">${speechesCount} Reden vorhanden</a>
<#else>
Keine Reden
Keine Reden vorhanden
</#if>
<br> <br>
</section>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reden von ${p.vorname} ${p.nachname} (${p.partei})</title>
<style type="text/css">
th, td {
padding: 12px;
text-align: center; /* Center-aligns both header and data cells */
border: 1px solid #ddd;
}
</style>
</head>
<body>
<header>
<h1>Reden von ${p.vorname} ${p.nachname} (${p.partei})</h1>
</header>
<main>
<section>
<table>
<thead>
<tr>
<th>Datum</th>
<th>Sitzung / Agenda</th>
</tr>
</thead>
<tbody>
<#list speechesMetaDataList as redeMd>
<tr>
<td>${redeMd.dateTimeString}</td>
<td><a href="/reden/${p.id}/${redeMd.speechKey}">${redeMd.sessionId} / ${redeMd.agendaTitle}</a></td>
</tr>
</#list>
</tbody>
</table>
</section>
</main>
<body>

View file

@ -1,5 +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;
@ -91,4 +94,14 @@ public class Speech_File_Impl implements Speech {
+ "</div>";
}
@Override
public String getFullText() {
return "";
}
@Override
public JCas toCas() throws UIMAException {
return null;
}
}

View file

@ -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;
}

Binary file not shown.