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