From eb3124e30dc21f90cd05e2c0cf95a0efadfa1859 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sat, 22 Mar 2025 18:51:43 +0100 Subject: [PATCH 01/26] added latex preamble --- src/main/resources/tex/preamble.tex | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/resources/tex/preamble.tex diff --git a/src/main/resources/tex/preamble.tex b/src/main/resources/tex/preamble.tex new file mode 100644 index 0000000..aa30691 --- /dev/null +++ b/src/main/resources/tex/preamble.tex @@ -0,0 +1,22 @@ +\documentclass[a4paper]{article} +\usepackage{graphicx} +\usepackage{fancyhdr} +\usepackage{geometry} +\usepackage{xcolor} +\usepackage[T1]{fontenc} + +\pagestyle{fancy} + +\geometry{ + top=2.5cm, % Top margin + bottom=3cm, % Bottom margin + left=2.5cm, % Left margin + right=2.5cm, % Right margin + headheight=25pt, % Header height + footskip=1.5cm, % Space from the bottom margin to the baseline of the footer + headsep=0.5cm, % Space from the top margin to the baseline of the header + %showframe, % Uncomment to show how the type block is set on the page +} + +\rhead{Multimodal Parliament Explorer} +\lhead{PDF Speech Export for $$EXPORTCATEGORY$$} From 359d057a9b4986688f326c3a0a081cdabc45f488 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sat, 22 Mar 2025 18:52:08 +0100 Subject: [PATCH 02/26] main latex export functionality --- .../project/gruppe_05_1/Main.java | 2 + .../gruppe_05_1/database/MongoPprUtils.java | 24 +++- .../domainimpl/mdb/Speaker_MongoDB_Impl.java | 91 +++++++++++++- .../domainimpl/mdb/Speech_MongoDB_Impl.java | 12 +- .../mdb/speechline/Comment_MongoDB_Impl.java | 4 + .../mdb/speechline/Line_MongoDB_Impl.java | 4 + .../mdb/speechline/Speaker_MongoDB_Impl.java | 4 + .../project/gruppe_05_1/export/TeXUtil.java | 119 ++++++++++++++++++ .../project/gruppe_05_1/rest/RESTHandler.java | 4 + .../gruppe_05_1/rest/SpeechController.java | 2 +- .../rest/SpeechesExportController.java | 44 +++++++ .../xml/speeches/Impls/Comment_File_Impl.java | 5 + .../xml/speeches/Impls/Line_File_Impl.java | 5 + .../xml/speeches/Impls/Speaker_File_Impl.java | 5 + .../xml/speeches/Impls/Speech_File_Impl.java | 18 +++ .../xml/speeches/Interfaces/Content.java | 7 ++ .../xml/speeches/Interfaces/Speech.java | 2 + 17 files changed, 345 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java create mode 100644 src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java 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 85aeddb..b022cc3 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 @@ -34,11 +34,13 @@ public class Main { private static final FileObjectFactory xmlFactory = FileObjectFactory.getFactory(); private static final MongoObjectFactory mongoFactory = MongoObjectFactory.getFactory(); + public static final String RESOURCES_DIR = "src/main/resources"; public static final String CONFIG_DIR = "src/main/resources/config"; public static final String JAVALIN_TEMPLATE_DIR = "src/main/resources/templates"; public static final String JAVALIN_STATIC_FILES_DIR = "src/main/resources/static"; public static final String JCAS_SPEECHES_TYPESYSTEM_DIR = "src/main/resources/speeches/TypeSystem"; public static final String MEMBER_IMAGES_DIR = "src/main/resources/membersOfParliamentImages/"; + public static final String TEMP_EXPORT_DIR = "src/main/resources/tempExport/"; public static void main(String[] args) throws Exception { UPLOAD_MEMBER_PHOTOS = Arrays.asList(args).contains("uploadMemberPhotos"); 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 73c6d90..d056d92 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 @@ -11,6 +11,7 @@ import com.mongodb.client.model.Projections; import io.javalin.http.Context; import org.bson.Document; import org.bson.conversions.Bson; +import org.texttechnologylab.project.gruppe_05_1.database.domainimpl.mdb.Speaker_MongoDB_Impl; import org.texttechnologylab.project.gruppe_05_1.database.domainimpl.mdb.Speech_MongoDB_Impl; import org.texttechnologylab.project.gruppe_05_1.domain.html.HtmlSpeech; import org.texttechnologylab.project.gruppe_05_1.domain.html.Parlamentarier; @@ -297,6 +298,15 @@ public class MongoPprUtils { return readParlamentarierDetailsFromSpeaker(doc); } + public static Speaker_MongoDB_Impl getSpeakerById(String id) { + Logger.debug("ID: " + id); + Document doc = MongoDBHandler.findFirstDocumentInCollection(getSpeakerCollection(), "_id", id); + Logger.debug("Speaker: " + doc); + Speaker_MongoDB_Impl speaker = new Speaker_MongoDB_Impl().createSpeakerMongoDBImpl(doc); + Logger.debug("Speaker parsed" + speaker); + return speaker; + } + /** * Holt die Details eines Parlamentariers @@ -623,7 +633,7 @@ public class MongoPprUtils { * @param key: Rede ID * @return */ - public static HtmlSpeech getSpeechByKey(String key) { + public static HtmlSpeech getHTMLSpeechByKey(String key) { Document filter = new Document("speechKey", key); Document speechDoc = getSpeechCollection().find(filter).first(); if (speechDoc == null) { @@ -634,6 +644,18 @@ public class MongoPprUtils { return new HtmlSpeech(speechDoc); } + public static Speech getSpeechByKey(String key) { + Document filter = new Document("speechKey", key); + Document speechDoc = getSpeechCollection().find(filter).first(); + + if (speechDoc == null) { + Logger.error("Rede " + key + " nicht gefunden"); + return null; + } + + return new Speech_MongoDB_Impl(speechDoc, true); + } + // getMemberPhoto /** diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java index 5c357e0..e2b625e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java @@ -5,15 +5,60 @@ import org.texttechnologylab.project.gruppe_05_1.database.MongoDBHandler; import org.texttechnologylab.project.gruppe_05_1.database.MongoOperations; import org.texttechnologylab.project.gruppe_05_1.domain.speaker.Membership; import org.texttechnologylab.project.gruppe_05_1.domain.speaker.Speaker; +import org.texttechnologylab.project.gruppe_05_1.util.Logger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.time.LocalDate; +import java.util.*; +import static org.texttechnologylab.project.gruppe_05_1.Main.TEMP_EXPORT_DIR; import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.getMemberPhoto; public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations { + public Speaker_MongoDB_Impl createSpeakerMongoDBImpl(Document mongoDocument) { + this.setId(mongoDocument.getString("_id")); + this.setName(mongoDocument.getString("name")); + this.setFirstName(mongoDocument.getString("firstName")); + this.setTitle(mongoDocument.getString("title")); + Logger.debug("First part parsed succesfully"); + this.setGeburtsdatum(parseTimestampSafely(mongoDocument.getDate("geburtsdatum"))); + this.setGeburtsort(mongoDocument.getString("geburtsort")); + this.setSterbedatum(parseTimestampSafely(mongoDocument.getDate("sterbedatum"))); + this.setGeschlecht(mongoDocument.getString("geschlecht")); + this.setBeruf(mongoDocument.getString("beruf")); + this.setAkademischertitel(mongoDocument.getString("akademischertitel")); + this.setFamilienstand(mongoDocument.getString("familienstand")); + this.setReligion(mongoDocument.getString("religion")); + this.setVita(mongoDocument.getString("vita")); + this.setParty(mongoDocument.getString("party")); + + List memberships = (List) mongoDocument.get("memberships"); + List membershipList = new ArrayList<>(); + for (Document membership : memberships) { + Membership membershipObj = new Membership(); + membershipObj.setRole(membership.getString("role")); + membershipObj.setMember(membership.getString("member")); + membershipObj.setBegin(parseTimestampSafely(membership.getDate("begin"))); + membershipObj.setEnd(parseTimestampSafely(membership.getDate("end"))); + membershipObj.setLabel(membership.getString("label")); + membershipObj.setWp(membership.getInteger("wp")); + membershipList.add(membershipObj); + } + this.setMemberships(membershipList); + + return this; + } + + public LocalDate parseTimestampSafely(Date timestamp) { + try { + Logger.debug("Parsing timestamp: " + timestamp); + return LocalDate.parse(timestamp.toString()); + } catch (Exception e) { + return null; + } + } @Override public Document createEntity(Speaker entity) { @@ -48,4 +93,42 @@ public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + // Delete file + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + // Delete the directory after its contents are deleted + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } +} 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 2d50db1..8ffa4e8 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 @@ -65,5 +65,9 @@ public class RESTHandler { app.get("/reden/{id}/{redeId}", SpeechController::showSpeech); // zeige eine bestimmte Rede des Parlamentariers an app.get("/reden", SpeechController::listAllSpeeches); // zeige alle Reden an (Filtern möglich) + + app.get("/export/speech/{id}", SpeechesExportController::exportSpeech); // exportiere eine Rede als PDF + //app.get("/portfolio/{id}/export", SpeechesExportController::exportSpeechesFromParlamentarier); // exportiere alle Reden eines Parlamentariers als PDF + //app.get("/topic/{topic}/export", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF } } 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 index 85e5d19..74e2dfe 100644 --- 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 @@ -72,7 +72,7 @@ public class SpeechController { Map attributes = new HashMap<>(); - HtmlSpeech speech = MongoPprUtils.getSpeechByKey(redeId); + HtmlSpeech speech = MongoPprUtils.getHTMLSpeechByKey(redeId); if (speech == null) { attributes.put("error", "Rede " + redeId + " nicht vorhanden"); ctx.render("speech.ftl", attributes); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java new file mode 100644 index 0000000..f56a12a --- /dev/null +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -0,0 +1,44 @@ +package org.texttechnologylab.project.gruppe_05_1.rest; + +import io.javalin.http.Context; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiResponse; +import org.texttechnologylab.project.gruppe_05_1.util.Logger; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Base64; + +import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.*; + +public class SpeechesExportController { + @OpenApi( + summary = "Get a speech as a PDF", + description = "Returns a LaTeX generated pdf of a selected speech", + operationId = "getSpeechExport", + path = "/export/speech/{id}", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "PDF"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeech(Context ctx) throws IOException { + byte[] pdfBytes = new byte[0]; + try { + pdfBytes = Base64.getDecoder().decode(getExportedSpeechBase64StringBySpeechId(ctx.pathParam("id"))); + } catch (Exception e) { + Logger.error("Failed to generate Export of Speech with ID " + ctx.pathParam("id")); + Logger.error(e.getMessage()); + } + + // Set the response content type to PDF + ctx.contentType("application/pdf"); + + // Send the PDF as a response + ctx.result(new ByteArrayInputStream(pdfBytes)); + + // delete the temporary folder + deleteTeXTempDirContents(); + } +} diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java index 036b204..96b802b 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java @@ -42,4 +42,9 @@ public class Comment_File_Impl implements Content, Comment { public MongoDBEntryType getType() { return MongoDBEntryType.SPEECH_COMMENT; } + + @Override + public String toTeX() { + return "\\textcolor{blue}{Kommentar}: " + this.getComment() + "\\\n"; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java index d230aaf..f9baea5 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java @@ -34,4 +34,9 @@ public class Line_File_Impl implements Content, Line { public MongoDBEntryType getType() { return MongoDBEntryType.SPEECH_LINE; } + + @Override + public String toTeX() { + return this.getContent() + "\\\n"; + } } \ No newline at end of file diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java index a71b8c1..4dfe625 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java @@ -49,4 +49,9 @@ public class Speaker_File_Impl implements Content, Speaker { public MongoDBEntryType getType() { return MongoDBEntryType.SPEECH_SPEAKER; } + + @Override + public String toTeX() { + return "\\textcolor{blue}{Redner/Rednerin}: " + this.getSpeakerName() + "\\\n"; + } } 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 fa765c5..2a3a412 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 @@ -103,4 +103,22 @@ public class Speech_File_Impl implements Speech { return null; } + @Override + public String toTeX() { + StringBuilder tex = new StringBuilder(); + + tex.append("\\NLP Metadata\\\n"); + + tex.append("[Graphs] //TODO: Implement\n"); + + tex.append("\\subsection*{Speech Content}\n"); + + // Add content block of speeches + for (Content content: this.getSpeechContents()) { + tex.append(content.toTeX()); + } + + + return tex.toString(); + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java index 1138cb7..5543428 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java @@ -24,4 +24,11 @@ public interface Content { * @return The speech ID. */ int getSpeechId(); + + /** + * Returns the content as LaTeX. + * + * @return The content. + */ + String toTeX(); } 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 642a24c..75032ab 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 @@ -85,4 +85,6 @@ public interface Speech { String getFullText(); JCas toCas() throws UIMAException; + + String toTeX(); } From f3bf22f197b45a3a7622ad32697c09c16f0b608b Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 19:25:41 +0100 Subject: [PATCH 03/26] fixed member image not being saved on first speech export --- .../project/gruppe_05_1/export/TeXUtil.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index f337905..5e35068 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -25,6 +25,7 @@ public class TeXUtil { private static String END_DOCUMENT = "\\end{document}"; public static String getSpeechToTexComponent(String speechId) { + createTempDir(); Speech speech = getSpeechByKey(speechId); Logger.debug("Speech ID: " + speechId); @@ -54,9 +55,7 @@ public class TeXUtil { public static String convertTexToBase64PDF(String tex) throws IOException, InterruptedException { // Create a temporary directory File tempDir = new File(TEMP_EXPORT_DIR); - if (!tempDir.exists()) { - tempDir.mkdir(); - } + createTempDir(); // Format tex string to UTF-8 tex = new String(tex.getBytes("UTF-8")); @@ -98,6 +97,13 @@ public class TeXUtil { return Base64.getEncoder().encodeToString(pdfBytes); } + public static void createTempDir() { + File tempDir = new File(TEMP_EXPORT_DIR); + if (!tempDir.exists()) { + tempDir.mkdirs(); + } + } + public static void deleteTeXTempDirContents() throws IOException { // Walk through the directory Files.walkFileTree(Path.of(TEMP_EXPORT_DIR), new SimpleFileVisitor() { From 41aab00db73e9f001865fd8ab1f79c40bd15470c Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 20:02:28 +0100 Subject: [PATCH 04/26] added section title to Speech export --- .../domainimpl/mdb/Speech_MongoDB_Impl.java | 17 +++++++++++++++++ .../project/gruppe_05_1/export/TeXUtil.java | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java index fafa227..54a6233 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java @@ -15,6 +15,9 @@ import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; import java.util.List; +import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.getAgendaTitle; +import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.getSessionDateTime; + public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech { public Speech_MongoDB_Impl(Document mongoDocument, boolean includeContent) { super( @@ -81,6 +84,20 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech { public String toTeX() { StringBuilder tex = new StringBuilder(); + tex.append("\\section*{Rede ") + .append(this.getSpeechKey()) + .append("/") + .append(getAgendaTitle(this.getSessionId(), this.getAgendaItemId())) + .append(" von ") + .append(this.getSpeakerName()) + .append(" (") + .append(this.getFraction()) + .append(") vom ") + .append(getSessionDateTime(this.getSessionId())) + .append("}\n"); + + tex.append("$$SPEAKERINFO$$\n"); + tex.append("\\subsection*{NLP Metadata}\n"); tex.append("[Graphs] //TODO: Implement\n"); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 5e35068..9fea175 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -37,13 +37,13 @@ public class TeXUtil { StringBuilder tex = new StringBuilder(); - tex.append(speaker.toTeX()); + //tex.append(speaker.toTeX()); tex.append(speech.toTeX()); Logger.debug("TeX: " + tex); - return tex.toString(); + return tex.toString().replace("$$SPEAKERINFO$$", speaker.toTeX()); } public static String getExportedSpeechBase64StringBySpeechId(String speechId) throws IOException, InterruptedException { From 28ae98bd869b47443a17a7b15548e5f05b1db490 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 20:02:41 +0100 Subject: [PATCH 05/26] changed color of speaker to green --- .../domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java | 2 +- src/main/resources/tex/preamble.tex | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java index 513e170..3d80009 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java @@ -15,6 +15,6 @@ public class Speaker_MongoDB_Impl extends Speaker_File_Impl implements Speaker { } public String toTeX() { - return "\\textcolor{blue}{Redner/Rednerin}: " + this.getSpeakerName() + "\\\\\n"; + return "\\textcolor{darkgreen}{Redner/Rednerin}: " + this.getSpeakerName() + "\\\\\n"; } } diff --git a/src/main/resources/tex/preamble.tex b/src/main/resources/tex/preamble.tex index aa30691..ec2bf02 100644 --- a/src/main/resources/tex/preamble.tex +++ b/src/main/resources/tex/preamble.tex @@ -7,6 +7,8 @@ \pagestyle{fancy} +\definecolor{darkgreen}{rgb}{0.0, 0.5, 0.0} + \geometry{ top=2.5cm, % Top margin bottom=3cm, % Bottom margin From 6d06aae46c93dcbb47b0d6068d4195b2683eb141 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 20:46:08 +0100 Subject: [PATCH 06/26] Fixed logger output --- .../project/gruppe_05_1/export/TeXUtil.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 9fea175..45b8b8b 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -37,12 +37,8 @@ public class TeXUtil { StringBuilder tex = new StringBuilder(); - //tex.append(speaker.toTeX()); - tex.append(speech.toTeX()); - Logger.debug("TeX: " + tex); - return tex.toString().replace("$$SPEAKERINFO$$", speaker.toTeX()); } @@ -75,7 +71,7 @@ public class TeXUtil { BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream())); - System.out.println("Standard Output:"); + Logger.debug("Standard Output:"); String s; while ((s = stdInput.readLine()) != null) { Logger.debug(s); From 417aee9cc12856a2fccf0e7a0e72fcbb54a098ac Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 20:46:42 +0100 Subject: [PATCH 07/26] added 500 code when pdf generation goes wrong --- .../rest/SpeechesExportController.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java index f56a12a..dc525e2 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -8,6 +8,7 @@ import org.texttechnologylab.project.gruppe_05_1.util.Logger; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.Arrays; import java.util.Base64; import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.*; @@ -23,22 +24,38 @@ public class SpeechesExportController { responses = { @OpenApiResponse(status = "200") }) - public static void exportSpeech(Context ctx) throws IOException { + public static void exportSpeech(Context ctx) { byte[] pdfBytes = new byte[0]; try { pdfBytes = Base64.getDecoder().decode(getExportedSpeechBase64StringBySpeechId(ctx.pathParam("id"))); } catch (Exception e) { Logger.error("Failed to generate Export of Speech with ID " + ctx.pathParam("id")); Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); } // Set the response content type to PDF ctx.contentType("application/pdf"); - // Send the PDF as a response - ctx.result(new ByteArrayInputStream(pdfBytes)); + ByteArrayInputStream stream = new ByteArrayInputStream(pdfBytes); - // delete the temporary folder - deleteTeXTempDirContents(); + Logger.pink(String.valueOf(stream.available())); + if (stream.available() == 0) { + Logger.error("PDF stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + // Send the PDF as a response + ctx.result(stream); + + try { + // delete the temporary folder + deleteTeXTempDirContents(); + } catch (IOException e) { + Logger.error("Failed to delete temporary folder."); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } } } From f2f941f4d613963ab206f3f05fb976027425792a Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 20:47:02 +0100 Subject: [PATCH 08/26] added check for no-image and add placeholder --- .../domainimpl/mdb/Speaker_MongoDB_Impl.java | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java index e2b625e..f53c4f8 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java @@ -22,7 +22,6 @@ public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations Date: Sat, 22 Mar 2025 21:18:30 +0100 Subject: [PATCH 09/26] fixed speaker title when not present --- .../database/domainimpl/mdb/Speaker_MongoDB_Impl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java index f53c4f8..5c087af 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java @@ -132,7 +132,11 @@ public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations Date: Sat, 22 Mar 2025 21:18:48 +0100 Subject: [PATCH 10/26] fixed religion --- .../database/domainimpl/mdb/Speaker_MongoDB_Impl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java index 5c087af..01f2494 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java @@ -139,7 +139,7 @@ public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations Date: Sat, 22 Mar 2025 21:18:56 +0100 Subject: [PATCH 11/26] removed unnecessary log message --- .../database/domainimpl/mdb/Speaker_MongoDB_Impl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java index 01f2494..dbfd06e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java @@ -123,7 +123,6 @@ public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations Date: Sat, 22 Mar 2025 21:19:08 +0100 Subject: [PATCH 12/26] fixed log --- .../database/domainimpl/mdb/Speaker_MongoDB_Impl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java index dbfd06e..7ff9a03 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java @@ -108,7 +108,7 @@ public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations Date: Sat, 22 Mar 2025 21:19:39 +0100 Subject: [PATCH 13/26] added placeholder for NLP data --- .../database/domainimpl/mdb/Speech_MongoDB_Impl.java | 2 +- .../gruppe_05_1/xml/speeches/Impls/Speech_File_Impl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java index 54a6233..544fd6f 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java @@ -100,7 +100,7 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech { tex.append("\\subsection*{NLP Metadata}\n"); - tex.append("[Graphs] //TODO: Implement\n"); + tex.append("$$NLPMETADATA$$\n"); tex.append("\\subsection*{Speech Content}\n"); 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 2a3a412..75eeeaa 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 @@ -109,7 +109,7 @@ public class Speech_File_Impl implements Speech { tex.append("\\NLP Metadata\\\n"); - tex.append("[Graphs] //TODO: Implement\n"); + tex.append("$$NLPMETADATA$$\n"); tex.append("\\subsection*{Speech Content}\n"); From 116a681ca905d7a78c97ac99f569d5e03cbdd102 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 21:19:52 +0100 Subject: [PATCH 14/26] removed unnecessary log message --- .../project/gruppe_05_1/rest/SpeechesExportController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java index dc525e2..7813d1c 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -38,8 +38,6 @@ public class SpeechesExportController { ctx.contentType("application/pdf"); ByteArrayInputStream stream = new ByteArrayInputStream(pdfBytes); - - Logger.pink(String.valueOf(stream.available())); if (stream.available() == 0) { Logger.error("PDF stream is empty."); ctx.result("Internal Server Error"); From 704d71dd750e0ba95a95e2b335d9ead86e4c5b04 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 21:20:20 +0100 Subject: [PATCH 15/26] added flag to pdflatex command to fix endless loading bug --- .../texttechnologylab/project/gruppe_05_1/export/TeXUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 45b8b8b..48d209a 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -66,7 +66,7 @@ public class TeXUtil { } // Run pdflatex to generate the .pdf file - String command = "pdflatex -output-directory=" + tempDir.getAbsolutePath() + " " + texFile.getAbsolutePath(); + String command = "pdflatex -interaction=nonstopmode -output-directory=" + tempDir.getAbsolutePath() + " " + texFile.getAbsolutePath(); Process process = Runtime.getRuntime().exec(command); From 8d00ef14d44a2eee6e423101f0618b0b9de47129 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:01:31 +0100 Subject: [PATCH 16/26] added support for bulk speech export from Speaker --- .../project/gruppe_05_1/export/TeXUtil.java | 40 +++++++++++++++-- .../project/gruppe_05_1/rest/RESTHandler.java | 2 +- .../rest/SpeechesExportController.java | 44 +++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 48d209a..383a8ab 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -15,14 +15,29 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Base64; +import java.util.List; import static org.texttechnologylab.project.gruppe_05_1.Main.RESOURCES_DIR; import static org.texttechnologylab.project.gruppe_05_1.Main.TEMP_EXPORT_DIR; import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.*; public class TeXUtil { - private static String BEGIN_DOCUMENT = "\\begin{document}"; - private static String END_DOCUMENT = "\\end{document}"; + private static final String PREAMBLE = readFileContentFromTeXDir(); + private static final String BEGIN_DOCUMENT = "\\begin{document}\n"; + private static final String END_DOCUMENT = "\\end{document}"; + private static final String TABLEOFCONTENTS = "\\tableofcontents\n\\newpage\n"; + private static final String NEWPAGE = "\\newpage\n"; + + private static String readFileContentFromTeXDir() { + try { + return Files.readString(new File(RESOURCES_DIR, "tex/preamble.tex").toPath()); + } catch (IOException e) { + Logger.error("Failed to read file content from tex directory."); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + return ""; + } + } public static String getSpeechToTexComponent(String speechId) { createTempDir(); @@ -44,8 +59,25 @@ public class TeXUtil { public static String getExportedSpeechBase64StringBySpeechId(String speechId) throws IOException, InterruptedException { // Read preamble from resources directory tex/preamble.tex - String preamble = Files.readString(new File(RESOURCES_DIR, "tex/preamble.tex").toPath()).replace("$$EXPORTCATEGORY$$", "Speech " + speechId); - return convertTexToBase64PDF(preamble + BEGIN_DOCUMENT + getSpeechToTexComponent(speechId) + END_DOCUMENT); + return convertTexToBase64PDF(PREAMBLE.replace("$$EXPORTCATEGORY$$", "Speech " + speechId) + BEGIN_DOCUMENT + getSpeechToTexComponent(speechId) + END_DOCUMENT); + } + + public static String getBulkExportedSpeechBase64StringFromSpeakerById(String speakerId) throws IOException, InterruptedException { + // Fetch all speechIDs from the speaker + List speechIds = getSpeechIdsBySpeakerId(speakerId); + + StringBuilder tex = new StringBuilder(); + + tex.append(PREAMBLE.replace("$$EXPORTCATEGORY$$", "Speaker ID" + speakerId)); + tex.append(BEGIN_DOCUMENT); + tex.append(TABLEOFCONTENTS); + for (String speechId : speechIds) { + tex.append(getSpeechToTexComponent(speechId)); + tex.append(NEWPAGE); + } + tex.append(END_DOCUMENT); + + return convertTexToBase64PDF(tex.toString()); } public static String convertTexToBase64PDF(String tex) throws IOException, InterruptedException { 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 8ffa4e8..d3d9691 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 @@ -67,7 +67,7 @@ public class RESTHandler { app.get("/reden", SpeechController::listAllSpeeches); // zeige alle Reden an (Filtern möglich) app.get("/export/speech/{id}", SpeechesExportController::exportSpeech); // exportiere eine Rede als PDF - //app.get("/portfolio/{id}/export", SpeechesExportController::exportSpeechesFromParlamentarier); // exportiere alle Reden eines Parlamentariers als PDF + app.get("/export/speaker/{id}", SpeechesExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF //app.get("/topic/{topic}/export", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java index 7813d1c..8a156b4 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -56,4 +56,48 @@ public class SpeechesExportController { Logger.debug(Arrays.toString(e.getStackTrace())); } } + + @OpenApi( + summary = "Get all speeches from a speaker as a PDF", + description = "Returns a LaTeX generated pdf of all speaches of a selected speech", + operationId = "getSpeechesFromSpeakerExport", + path = "/export/speaker/{id}", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "PDF"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeechesFromSpeaker(Context ctx) { + byte[] pdfBytes = new byte[0]; + try { + pdfBytes = Base64.getDecoder().decode(getBulkExportedSpeechBase64StringFromSpeakerById(ctx.pathParam("id"))); + } catch (Exception e) { + Logger.error("Failed to generate Export of Speeches from Speaker with ID " + ctx.pathParam("id")); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + + // Set the response content type to PDF + ctx.contentType("application/pdf"); + + ByteArrayInputStream stream = new ByteArrayInputStream(pdfBytes); + if (stream.available() == 0) { + Logger.error("PDF stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + // Send the PDF as a response + ctx.result(stream); + + try { + // delete the temporary folder + deleteTeXTempDirContents(); + Logger.debug("Temporary folder deleted."); + } catch (IOException e) { + Logger.error("Failed to delete temporary folder."); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + } } From 25fc8b5480f809216e964190b300af6480d813f3 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:01:47 +0100 Subject: [PATCH 17/26] fixed section in toc --- .../domainimpl/mdb/Speech_MongoDB_Impl.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java index 544fd6f..f77d55c 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java @@ -84,17 +84,19 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech { public String toTeX() { StringBuilder tex = new StringBuilder(); - tex.append("\\section*{Rede ") - .append(this.getSpeechKey()) - .append("/") - .append(getAgendaTitle(this.getSessionId(), this.getAgendaItemId())) - .append(" von ") - .append(this.getSpeakerName()) - .append(" (") - .append(this.getFraction()) - .append(") vom ") - .append(getSessionDateTime(this.getSessionId())) - .append("}\n"); + String speechTitle = "Rede " + + this.getSpeechKey() + + "/" + + getAgendaTitle(this.getSessionId(), this.getAgendaItemId()) + + " von " + + this.getSpeakerName() + + " (" + + this.getFraction() + + ") vom " + + getSessionDateTime(this.getSessionId()); + + tex.append("\\section*{").append(speechTitle).append("}\n"); + tex.append("\\addcontentsline{toc}{section}{").append(speechTitle).append("}\n"); tex.append("$$SPEAKERINFO$$\n"); From ea68b3204bf4be0f492b788748ab8cf980c94294 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:02:08 +0100 Subject: [PATCH 18/26] added method to get speechIDs from speaker --- .../project/gruppe_05_1/database/MongoPprUtils.java | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 d056d92..ce9e17e 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 @@ -730,4 +730,14 @@ public class MongoPprUtils { Logger.info("Updating Metadata Collection: end"); } + + public static List getSpeechIdsBySpeakerId(String speakerId) { + List speechIds = new ArrayList<>(); + Document filter = new Document("speakerId", Integer.parseInt(speakerId)); + List docs = getSpeechCollection().find(filter).into(new ArrayList<>()); + for (Document doc : docs) { + speechIds.add(doc.getString("speechKey")); + } + return speechIds; + } } From 483f168ae905880306458d8cc09821cc37ec5a14 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:02:38 +0100 Subject: [PATCH 19/26] moved to latexmk for proper toc generation --- .../texttechnologylab/project/gruppe_05_1/export/TeXUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 383a8ab..9a2043e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -98,7 +98,9 @@ public class TeXUtil { } // Run pdflatex to generate the .pdf file - String command = "pdflatex -interaction=nonstopmode -output-directory=" + tempDir.getAbsolutePath() + " " + texFile.getAbsolutePath(); + //String command = "pdflatex -interaction=nonstopmode -output-directory=" + tempDir.getAbsolutePath() + " " + texFile.getAbsolutePath(); + // using latexmk instead of pdflatex to fix TOC not generating properly + String command = "latexmk -pdf -interaction=nonstopmode -outdir=" + tempDir.getAbsolutePath() + " " + texFile.getAbsolutePath(); Process process = Runtime.getRuntime().exec(command); From 22ea6f047c143d216623ddeb9c3fa08126e93e61 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:02:59 +0100 Subject: [PATCH 20/26] removed unnecessary logs --- .../project/gruppe_05_1/export/TeXUtil.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 9a2043e..4b27306 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -43,13 +43,8 @@ public class TeXUtil { createTempDir(); Speech speech = getSpeechByKey(speechId); - Logger.debug("Speech ID: " + speechId); - Logger.debug("Speech: " + speech); - Speaker_MongoDB_Impl speaker = getSpeakerById(String.valueOf(speech.getSpeakerId())); - Logger.debug("Speaker: " + speaker); - StringBuilder tex = new StringBuilder(); tex.append(speech.toTeX()); From 320f4dbdc25f44852a773f0fba47dd82af5c350c Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:20:54 +0100 Subject: [PATCH 21/26] added request for all speeches exort and improved fetching speeds --- .../gruppe_05_1/database/MongoPprUtils.java | 16 +++++-- .../project/gruppe_05_1/export/TeXUtil.java | 35 ++++++++++++-- .../project/gruppe_05_1/rest/RESTHandler.java | 1 + .../rest/SpeechesExportController.java | 46 ++++++++++++++++++- 4 files changed, 91 insertions(+), 7 deletions(-) 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 ce9e17e..8e17b32 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 @@ -731,12 +731,22 @@ public class MongoPprUtils { Logger.info("Updating Metadata Collection: end"); } - public static List getSpeechIdsBySpeakerId(String speakerId) { - List speechIds = new ArrayList<>(); + public static List getSpeechesBySpeakerId(String speakerId) { + List speechIds = new ArrayList<>(); Document filter = new Document("speakerId", Integer.parseInt(speakerId)); List docs = getSpeechCollection().find(filter).into(new ArrayList<>()); for (Document doc : docs) { - speechIds.add(doc.getString("speechKey")); + speechIds.add(new Speech_MongoDB_Impl(doc, true)); + } + return speechIds; + } + + public static List getAllSpeeches() { + List speechIds = new ArrayList<>(); + Document filter = new Document(); + List docs = getSpeechCollection().find(filter).into(new ArrayList<>()); + for (Document doc : docs) { + speechIds.add(new Speech_MongoDB_Impl(doc, true)); } return speechIds; } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 4b27306..6f357c6 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -52,6 +52,17 @@ public class TeXUtil { return tex.toString().replace("$$SPEAKERINFO$$", speaker.toTeX()); } + public static String getSpeechToTexComponent(Speech speech) { + createTempDir(); + Speaker_MongoDB_Impl speaker = getSpeakerById(String.valueOf(speech.getSpeakerId())); + + StringBuilder tex = new StringBuilder(); + + tex.append(speech.toTeX()); + + return tex.toString().replace("$$SPEAKERINFO$$", speaker.toTeX()); + } + public static String getExportedSpeechBase64StringBySpeechId(String speechId) throws IOException, InterruptedException { // Read preamble from resources directory tex/preamble.tex return convertTexToBase64PDF(PREAMBLE.replace("$$EXPORTCATEGORY$$", "Speech " + speechId) + BEGIN_DOCUMENT + getSpeechToTexComponent(speechId) + END_DOCUMENT); @@ -59,15 +70,33 @@ public class TeXUtil { public static String getBulkExportedSpeechBase64StringFromSpeakerById(String speakerId) throws IOException, InterruptedException { // Fetch all speechIDs from the speaker - List speechIds = getSpeechIdsBySpeakerId(speakerId); + List speechIds = getSpeechesBySpeakerId(speakerId); StringBuilder tex = new StringBuilder(); tex.append(PREAMBLE.replace("$$EXPORTCATEGORY$$", "Speaker ID" + speakerId)); tex.append(BEGIN_DOCUMENT); tex.append(TABLEOFCONTENTS); - for (String speechId : speechIds) { - tex.append(getSpeechToTexComponent(speechId)); + for (Speech speech : speechIds) { + tex.append(getSpeechToTexComponent(speech)); + tex.append(NEWPAGE); + } + tex.append(END_DOCUMENT); + + return convertTexToBase64PDF(tex.toString()); + } + + public static String getBulkExportedAllSpeechBase64String() throws IOException, InterruptedException { + // Fetch all speechIDs from the speaker + List speechIds = getAllSpeeches(); + + StringBuilder tex = new StringBuilder(); + + tex.append(PREAMBLE.replace("$$EXPORTCATEGORY$$", "all speeches")); + tex.append(BEGIN_DOCUMENT); + tex.append(TABLEOFCONTENTS); + for (Speech speech : speechIds) { + tex.append(getSpeechToTexComponent(speech)); tex.append(NEWPAGE); } tex.append(END_DOCUMENT); 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 d3d9691..11c3b3a 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 @@ -69,5 +69,6 @@ public class RESTHandler { app.get("/export/speech/{id}", SpeechesExportController::exportSpeech); // exportiere eine Rede als PDF app.get("/export/speaker/{id}", SpeechesExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF //app.get("/topic/{topic}/export", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF + app.get("/export/all", SpeechesExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java index 8a156b4..79ba6a0 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -59,7 +59,7 @@ public class SpeechesExportController { @OpenApi( summary = "Get all speeches from a speaker as a PDF", - description = "Returns a LaTeX generated pdf of all speaches of a selected speech", + description = "Returns a LaTeX generated pdf of all speeches of a selected speech", operationId = "getSpeechesFromSpeakerExport", path = "/export/speaker/{id}", methods = HttpMethod.GET, @@ -100,4 +100,48 @@ public class SpeechesExportController { Logger.debug(Arrays.toString(e.getStackTrace())); } } + + @OpenApi( + summary = "Get all speeches as a PDF", + description = "Returns a LaTeX generated pdf of all speeches", + operationId = "getAllSpeeches", + path = "/export/all", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "PDF"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportAllSpeeches(Context ctx) { + byte[] pdfBytes = new byte[0]; + try { + pdfBytes = Base64.getDecoder().decode(getBulkExportedAllSpeechBase64String()); + } catch (Exception e) { + Logger.error("Failed to generate Export of all Speeches"); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + + // Set the response content type to PDF + ctx.contentType("application/pdf"); + + ByteArrayInputStream stream = new ByteArrayInputStream(pdfBytes); + if (stream.available() == 0) { + Logger.error("PDF stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + // Send the PDF as a response + ctx.result(stream); + + try { + // delete the temporary folder + deleteTeXTempDirContents(); + Logger.debug("Temporary folder deleted."); + } catch (IOException e) { + Logger.error("Failed to delete temporary folder."); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + } } From dabac9e316eba28ad2fcd9c474c82cbda3a6ca4d Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:33:27 +0100 Subject: [PATCH 22/26] added export based on Topic --- .../gruppe_05_1/database/MongoPprUtils.java | 10 ++++ .../project/gruppe_05_1/export/TeXUtil.java | 20 +++++++- .../project/gruppe_05_1/rest/RESTHandler.java | 2 +- .../rest/SpeechesExportController.java | 46 ++++++++++++++++++- 4 files changed, 75 insertions(+), 3 deletions(-) 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 8e17b32..c513548 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 @@ -750,4 +750,14 @@ public class MongoPprUtils { } return speechIds; } + + public static List getAllSpeechesWithTopic(String topic) { + List speechIds = new ArrayList<>(); + Document filter = new Document("analysisResults.topics.topic", topic); + List docs = getSpeechCollection().find(filter).into(new ArrayList<>()); + for (Document doc : docs) { + speechIds.add(new Speech_MongoDB_Impl(doc, true)); + } + return speechIds; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 6f357c6..3e4318b 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -86,7 +86,7 @@ public class TeXUtil { return convertTexToBase64PDF(tex.toString()); } - public static String getBulkExportedAllSpeechBase64String() throws IOException, InterruptedException { + public static String getBulkExportedAllSpeechesBase64String() throws IOException, InterruptedException { // Fetch all speechIDs from the speaker List speechIds = getAllSpeeches(); @@ -104,6 +104,24 @@ public class TeXUtil { return convertTexToBase64PDF(tex.toString()); } + public static String getBulkExportedAllSpeechesWithTopicBase64String(String topic) throws IOException, InterruptedException { + // Fetch all speechIDs from the speaker + List speechIds = getAllSpeechesWithTopic(topic); + + StringBuilder tex = new StringBuilder(); + + tex.append(PREAMBLE.replace("$$EXPORTCATEGORY$$", "Speeches with topic " + topic)); + tex.append(BEGIN_DOCUMENT); + tex.append(TABLEOFCONTENTS); + for (Speech speech : speechIds) { + tex.append(getSpeechToTexComponent(speech)); + tex.append(NEWPAGE); + } + tex.append(END_DOCUMENT); + + return convertTexToBase64PDF(tex.toString()); + } + public static String convertTexToBase64PDF(String tex) throws IOException, InterruptedException { // Create a temporary directory File tempDir = new File(TEMP_EXPORT_DIR); 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 11c3b3a..f30d669 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 @@ -68,7 +68,7 @@ public class RESTHandler { app.get("/export/speech/{id}", SpeechesExportController::exportSpeech); // exportiere eine Rede als PDF app.get("/export/speaker/{id}", SpeechesExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF - //app.get("/topic/{topic}/export", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF + app.get("/export/topic/{topic}", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF app.get("/export/all", SpeechesExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java index 79ba6a0..2930fc7 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -114,7 +114,7 @@ public class SpeechesExportController { public static void exportAllSpeeches(Context ctx) { byte[] pdfBytes = new byte[0]; try { - pdfBytes = Base64.getDecoder().decode(getBulkExportedAllSpeechBase64String()); + pdfBytes = Base64.getDecoder().decode(getBulkExportedAllSpeechesBase64String()); } catch (Exception e) { Logger.error("Failed to generate Export of all Speeches"); Logger.error(e.getMessage()); @@ -144,4 +144,48 @@ public class SpeechesExportController { Logger.debug(Arrays.toString(e.getStackTrace())); } } + + @OpenApi( + summary = "Get all speeches with specific topic as a PDF", + description = "Returns a LaTeX generated pdf of all speeches with specific topic", + operationId = "getAllSpeechesWithTopic", + path = "/export/topic/{topic}", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "PDF"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeechesWithTopic(Context ctx) { + byte[] pdfBytes = new byte[0]; + try { + pdfBytes = Base64.getDecoder().decode(getBulkExportedAllSpeechesWithTopicBase64String(ctx.pathParam("topic"))); + } catch (Exception e) { + Logger.error("Failed to generate Export of all Speeches with Topic " + ctx.pathParam("topic")); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + + // Set the response content type to PDF + ctx.contentType("application/pdf"); + + ByteArrayInputStream stream = new ByteArrayInputStream(pdfBytes); + if (stream.available() == 0) { + Logger.error("PDF stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + // Send the PDF as a response + ctx.result(stream); + + try { + // delete the temporary folder + deleteTeXTempDirContents(); + Logger.debug("Temporary folder deleted."); + } catch (IOException e) { + Logger.error("Failed to delete temporary folder."); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + } } From edb91b7b723cd7edf2a42e9126099e561efd41fd Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:48:14 +0100 Subject: [PATCH 23/26] added export for list of speeches --- .../project/gruppe_05_1/export/TeXUtil.java | 15 ++++++ .../project/gruppe_05_1/rest/RESTHandler.java | 1 + .../rest/SpeechesExportController.java | 52 +++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 3e4318b..c02aa14 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -122,6 +122,21 @@ public class TeXUtil { return convertTexToBase64PDF(tex.toString()); } + public static String getBulkExportedSpeechesBase64String(List speechIds) throws IOException, InterruptedException { + StringBuilder tex = new StringBuilder(); + + tex.append(PREAMBLE.replace("$$EXPORTCATEGORY$$", "selected speeches")); + tex.append(BEGIN_DOCUMENT); + tex.append(TABLEOFCONTENTS); + for (String speechId : speechIds) { + tex.append(getSpeechToTexComponent(speechId)); + tex.append(NEWPAGE); + } + tex.append(END_DOCUMENT); + + return convertTexToBase64PDF(tex.toString()); + } + public static String convertTexToBase64PDF(String tex) throws IOException, InterruptedException { // Create a temporary directory File tempDir = new File(TEMP_EXPORT_DIR); 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 f30d669..7db4d8d 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 @@ -70,5 +70,6 @@ public class RESTHandler { app.get("/export/speaker/{id}", SpeechesExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF app.get("/export/topic/{topic}", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF app.get("/export/all", SpeechesExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise + app.get("/export/speeches/{speechIds}", SpeechesExportController::exportSpeeches); // exportiere eine Liste von Reden als PDF } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java index 2930fc7..d053b38 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -10,6 +10,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Arrays; import java.util.Base64; +import java.util.List; import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.*; @@ -188,4 +189,55 @@ public class SpeechesExportController { Logger.debug(Arrays.toString(e.getStackTrace())); } } + + @OpenApi( + summary = "Get speeches by IDs as a PDF", + description = "Returns a LaTeX-generated PDF of the speeches specified by their IDs", + operationId = "getSpeechesByIds", + path = "/export/speeches/{speechIds}", // Comma-separated IDs + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "PDF"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeeches(Context ctx) { + byte[] pdfBytes = new byte[0]; + + try { + // Extract speech IDs from the path + String speechIdsParam = ctx.pathParam("speechIds"); + List speechIds = Arrays.asList(speechIdsParam.split(",")); + + // Generate PDF for given speech IDs + pdfBytes = Base64.getDecoder().decode(getBulkExportedSpeechesBase64String(speechIds)); + } catch (Exception e) { + Logger.error("Failed to generate export for speeches: " + ctx.pathParam("speechIds")); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + + // Set response content type + ctx.contentType("application/pdf"); + + ByteArrayInputStream stream = new ByteArrayInputStream(pdfBytes); + if (stream.available() == 0) { + Logger.error("PDF stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + + // Send the PDF as response + ctx.result(stream); + + try { + // Clean up temporary files + deleteTeXTempDirContents(); + Logger.debug("Temporary folder deleted."); + } catch (IOException e) { + Logger.error("Failed to delete temporary folder."); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + } } From 76951476ef76cb2621c10029af136c2f3f417b83 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 22:55:28 +0100 Subject: [PATCH 24/26] added warning in console if TeX sdk not installed --- .../project/gruppe_05_1/Main.java | 7 +++++++ .../project/gruppe_05_1/export/TeXUtil.java | 14 ++++++++++++++ .../project/gruppe_05_1/util/Logger.java | 4 ++++ 3 files changed, 25 insertions(+) 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 b022cc3..21f649e 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 @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; +import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.isTeXSdkInstalled; import static org.texttechnologylab.project.gruppe_05_1.util.PPRUtils.checkAndProcessNewProtocols; public class Main { @@ -61,6 +62,12 @@ public class Main { System.out.println(" - Debug Logging: " + DEBUG_LOGGING); System.out.println("--------------------------------------------o"); + if (!isTeXSdkInstalled()) { + Logger.orange("-------------------------------------------------o"); + Logger.orange("TeX SDK not installed. PDF export will not work."); + Logger.orange("-------------------------------------------------o"); + } + if (ONLY_RUN_WEB) { Logger.info("Starting Web Service..."); RESTHandler restHandler = new RESTHandler(); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index c02aa14..16cbe83 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -209,4 +209,18 @@ public class TeXUtil { } }); } + + public static boolean isTeXSdkInstalled() { + try { + Process process = Runtime.getRuntime().exec("pdflatex --version"); + BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream())); + String s; + while ((s = stdInput.readLine()) != null) { + if (s.contains("pdfTeX")) { + return true; + } + } + } catch (IOException ignored) {} + return false; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/Logger.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/Logger.java index 6dbfd8f..796498b 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/Logger.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/util/Logger.java @@ -28,4 +28,8 @@ public class Logger { public static void pink(String message) { System.out.println("\u001B[35m" + java.time.LocalTime.now() + " PINK: " + message + "\u001B[0m"); } + + public static void orange(String message) { + System.out.println("\u001B[38;5;214m" + message + "\u001B[0m"); + } } From 85ea3dd5f55d51e90f0e036dfa70df6d4a6dd959 Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sat, 22 Mar 2025 23:01:39 +0100 Subject: [PATCH 25/26] moved tex export request to /pdf sub path --- .../project/gruppe_05_1/rest/RESTHandler.java | 10 +++++----- .../gruppe_05_1/rest/SpeechesExportController.java | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) 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 7db4d8d..7226b07 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 @@ -66,10 +66,10 @@ public class RESTHandler { app.get("/reden", SpeechController::listAllSpeeches); // zeige alle Reden an (Filtern möglich) - app.get("/export/speech/{id}", SpeechesExportController::exportSpeech); // exportiere eine Rede als PDF - app.get("/export/speaker/{id}", SpeechesExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF - app.get("/export/topic/{topic}", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF - app.get("/export/all", SpeechesExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise - app.get("/export/speeches/{speechIds}", SpeechesExportController::exportSpeeches); // exportiere eine Liste von Reden als PDF + app.get("/export/pdf/speech/{id}", SpeechesExportController::exportSpeech); // exportiere eine Rede als PDF + app.get("/export/pdf/speaker/{id}", SpeechesExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF + app.get("/export/pdf/topic/{topic}", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF + app.get("/export/pdf/all", SpeechesExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise + app.get("/export/pdf/speeches/{speechIds}", SpeechesExportController::exportSpeeches); // exportiere eine Liste von Reden als PDF } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java index d053b38..c6ecf99 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java @@ -19,7 +19,7 @@ public class SpeechesExportController { summary = "Get a speech as a PDF", description = "Returns a LaTeX generated pdf of a selected speech", operationId = "getSpeechExport", - path = "/export/speech/{id}", + path = "/export/pdf/speech/{id}", methods = HttpMethod.GET, tags = {"Export", "Speeches", "PDF"}, responses = { @@ -62,7 +62,7 @@ public class SpeechesExportController { summary = "Get all speeches from a speaker as a PDF", description = "Returns a LaTeX generated pdf of all speeches of a selected speech", operationId = "getSpeechesFromSpeakerExport", - path = "/export/speaker/{id}", + path = "/export/pdf/speaker/{id}", methods = HttpMethod.GET, tags = {"Export", "Speeches", "PDF"}, responses = { @@ -106,7 +106,7 @@ public class SpeechesExportController { summary = "Get all speeches as a PDF", description = "Returns a LaTeX generated pdf of all speeches", operationId = "getAllSpeeches", - path = "/export/all", + path = "/export/pdf/all", methods = HttpMethod.GET, tags = {"Export", "Speeches", "PDF"}, responses = { @@ -150,7 +150,7 @@ public class SpeechesExportController { summary = "Get all speeches with specific topic as a PDF", description = "Returns a LaTeX generated pdf of all speeches with specific topic", operationId = "getAllSpeechesWithTopic", - path = "/export/topic/{topic}", + path = "/export/pdf/topic/{topic}", methods = HttpMethod.GET, tags = {"Export", "Speeches", "PDF"}, responses = { @@ -194,7 +194,7 @@ public class SpeechesExportController { summary = "Get speeches by IDs as a PDF", description = "Returns a LaTeX-generated PDF of the speeches specified by their IDs", operationId = "getSpeechesByIds", - path = "/export/speeches/{speechIds}", // Comma-separated IDs + path = "/export/pdf/speeches/{speechIds}", // Comma-separated IDs methods = HttpMethod.GET, tags = {"Export", "Speeches", "PDF"}, responses = { From ab37c00ea9c522d961a4dcbf9543774435c1693c Mon Sep 17 00:00:00 2001 From: s5260822 Date: Sun, 23 Mar 2025 00:57:29 +0100 Subject: [PATCH 26/26] added XML exports --- .../domainimpl/mdb/Speaker_MongoDB_Impl.java | 33 ++++ .../domainimpl/mdb/Speech_MongoDB_Impl.java | 17 ++ .../mdb/speechline/Comment_MongoDB_Impl.java | 10 + .../mdb/speechline/Line_MongoDB_Impl.java | 9 + .../mdb/speechline/Speaker_MongoDB_Impl.java | 11 ++ .../project/gruppe_05_1/export/XMLUtil.java | 137 +++++++++++++ .../project/gruppe_05_1/rest/RESTHandler.java | 16 +- ...ava => SpeechesLatexExportController.java} | 2 +- .../rest/SpeechesXMLExportController.java | 181 ++++++++++++++++++ .../xml/speeches/Impls/Comment_File_Impl.java | 12 ++ .../xml/speeches/Impls/Line_File_Impl.java | 11 ++ .../xml/speeches/Impls/Speaker_File_Impl.java | 13 ++ .../xml/speeches/Impls/Speech_File_Impl.java | 20 ++ .../xml/speeches/Interfaces/Content.java | 9 + .../xml/speeches/Interfaces/Speech.java | 4 + 15 files changed, 479 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java rename src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/{SpeechesExportController.java => SpeechesLatexExportController.java} (99%) create mode 100644 src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesXMLExportController.java diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java index 7ff9a03..f3d5133 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speaker_MongoDB_Impl.java @@ -6,6 +6,7 @@ import org.texttechnologylab.project.gruppe_05_1.database.MongoOperations; import org.texttechnologylab.project.gruppe_05_1.domain.speaker.Membership; import org.texttechnologylab.project.gruppe_05_1.domain.speaker.Speaker; import org.texttechnologylab.project.gruppe_05_1.util.Logger; +import org.w3c.dom.Element; import java.io.File; import java.io.FileOutputStream; @@ -151,4 +152,36 @@ public class Speaker_MongoDB_Impl extends Speaker implements MongoOperations memberships = this.getMemberships(); + for (Membership membership : memberships) { + Element membershipElement = doc.createElement("membership"); + membershipElement.setAttribute("role", membership.getRole()); + membershipElement.setAttribute("member", membership.getMember()); + membershipElement.setAttribute("begin", membership.getBegin() != null ? membership.getBegin().toString() : ""); + membershipElement.setAttribute("end", membership.getEnd() != null ? membership.getEnd().toString() : ""); + membershipElement.setAttribute("label", membership.getLabel()); + membershipElement.setAttribute("wp", String.valueOf(membership.getWp())); + speakerElement.appendChild(membershipElement); + } + + return speakerElement; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java index f77d55c..326da2e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/Speech_MongoDB_Impl.java @@ -11,6 +11,7 @@ import org.texttechnologylab.project.gruppe_05_1.database.domainimpl.mdb.speechl 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; +import org.w3c.dom.Element; import java.util.List; @@ -115,4 +116,20 @@ public class Speech_MongoDB_Impl extends Speech_File_Impl implements Speech { return tex.toString(); } + public Element toXML(org.w3c.dom.Document doc) { + Element speech = doc.createElement("speech"); + speech.setAttribute("sessionId", String.valueOf(this.getSessionId())); + speech.setAttribute("agendaItemId", String.valueOf(this.getAgendaItemId())); + speech.setAttribute("speechId", String.valueOf(this.getSpeechId())); + speech.setAttribute("speakerId", String.valueOf(this.getSpeakerId())); + speech.setAttribute("speakerName", this.getSpeakerName()); + speech.setAttribute("fraction", this.getFraction()); + speech.setAttribute("speechKey", this.getSpeechKey()); + + for (Content content: this.getSpeechContents()) { + speech.appendChild(content.toXML(doc)); + } + + return speech; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Comment_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Comment_MongoDB_Impl.java index 1ddd2ae..d2ca74d 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Comment_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Comment_MongoDB_Impl.java @@ -3,6 +3,7 @@ package org.texttechnologylab.project.gruppe_05_1.database.domainimpl.mdb.speech import org.bson.Document; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Comment_File_Impl; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Comment; +import org.w3c.dom.Element; public class Comment_MongoDB_Impl extends Comment_File_Impl implements Comment { @@ -18,4 +19,13 @@ public class Comment_MongoDB_Impl extends Comment_File_Impl implements Comment { public String toTeX() { return "\\textcolor{blue}{Kommentar}: " + this.getComment() + "\\\\\n"; } + + public Element toXML(org.w3c.dom.Document doc) { + Element comment = doc.createElement("comment"); + comment.setAttribute("contentId", String.valueOf(this.getContentId())); + comment.setAttribute("speechId", String.valueOf(this.getSpeechId())); + comment.setAttribute("commentatorName", this.getCommentatorName()); + comment.setTextContent(this.getComment()); + return comment; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Line_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Line_MongoDB_Impl.java index 74bd3c1..d2d81f4 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Line_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Line_MongoDB_Impl.java @@ -3,6 +3,7 @@ package org.texttechnologylab.project.gruppe_05_1.database.domainimpl.mdb.speech import org.bson.Document; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Line_File_Impl; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Line; +import org.w3c.dom.Element; public class Line_MongoDB_Impl extends Line_File_Impl implements Line { @@ -16,4 +17,12 @@ public class Line_MongoDB_Impl extends Line_File_Impl implements Line { public String toTeX() { return this.getContent() + "\\\\\n"; } + + public Element toXML(org.w3c.dom.Document doc) { + Element line = doc.createElement("line"); + line.setAttribute("contentId", String.valueOf(this.getContentId())); + line.setAttribute("speechId", String.valueOf(this.getSpeechId())); + line.setTextContent(this.getContent()); + return line; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java index 3d80009..4c6ffff 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/domainimpl/mdb/speechline/Speaker_MongoDB_Impl.java @@ -3,6 +3,7 @@ package org.texttechnologylab.project.gruppe_05_1.database.domainimpl.mdb.speech import org.bson.Document; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls.Speaker_File_Impl; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speaker; +import org.w3c.dom.Element; public class Speaker_MongoDB_Impl extends Speaker_File_Impl implements Speaker { public Speaker_MongoDB_Impl(Document mongoDocument) { @@ -17,4 +18,14 @@ public class Speaker_MongoDB_Impl extends Speaker_File_Impl implements Speaker { public String toTeX() { return "\\textcolor{darkgreen}{Redner/Rednerin}: " + this.getSpeakerName() + "\\\\\n"; } + + public Element toXML(org.w3c.dom.Document doc) { + Element speaker = doc.createElement("speaker"); + speaker.setAttribute("contentId", String.valueOf(this.getContentId())); + speaker.setAttribute("speechId", String.valueOf(this.getSpeechId())); + speaker.setAttribute("speakerId", String.valueOf(this.getSpeakerId())); + speaker.setAttribute("speakerName", this.getSpeakerName()); + speaker.setAttribute("fraction", this.getFraction()); + return speaker; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java new file mode 100644 index 0000000..4011614 --- /dev/null +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java @@ -0,0 +1,137 @@ +package org.texttechnologylab.project.gruppe_05_1.export; + +import org.eclipse.jetty.xml.XmlParser; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Node; +import org.texttechnologylab.project.gruppe_05_1.database.domainimpl.mdb.Speaker_MongoDB_Impl; +import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import static org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils.*; + +public class XMLUtil { + public static String documentToString(Document doc) { + try { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + + // Writer to store the XML string + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + + // Perform transformation + transformer.transform(source, result); + + return writer.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static Document createXmlDocument() throws ParserConfigurationException { + // create new doc + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + Document doc = factory.newDocumentBuilder().newDocument(); + + Element speechesElement = doc.createElement("speeches"); + doc.appendChild(speechesElement); + + return doc; + } + + public static void addSpeechById(Document doc, String speechId) { + // get speeches element + Element speechesElement = (Element) doc.getElementsByTagName("speeches").item(0); + + // create new speech element + Element speechElement = doc.createElement("speech"); + speechesElement.appendChild(speechElement); + + Speech speech = getSpeechByKey(speechId); + Speaker_MongoDB_Impl speaker = getSpeakerById(String.valueOf(speech.getSpeakerId())); + + speechElement.appendChild(speaker.toXML(doc)); + speechElement.appendChild(speech.toXML(doc)); + } + + public static void addSpeechBySpeech(Document doc, Speech speech) { + // get speeches element + Element speechesElement = (Element) doc.getElementsByTagName("speeches").item(0); + + // create new speech element + Element speechElement = doc.createElement("speech"); + speechesElement.appendChild(speechElement); + + Speaker_MongoDB_Impl speaker = getSpeakerById(String.valueOf(speech.getSpeakerId())); + + speechElement.appendChild(speaker.toXML(doc)); + speechElement.appendChild(speech.toXML(doc)); + } + + public static String getExportedSpeechById(String speechId) throws ParserConfigurationException { + Document doc = createXmlDocument(); + + addSpeechById(doc, speechId); + + return documentToString(doc); + } + + public static String getExportedSpeechesFromSpeakerById(String speakerId) throws ParserConfigurationException { + Document doc = createXmlDocument(); + + List speeches = getSpeechesBySpeakerId(speakerId); + + for (Speech speech : speeches) { + addSpeechBySpeech(doc, speech); + } + + return documentToString(doc); + } + + public static String getExportedAllSpeeches() throws ParserConfigurationException { + Document doc = createXmlDocument(); + + List speeches = getAllSpeeches(); + + for (Speech speech : speeches) { + addSpeechBySpeech(doc, speech); + } + + return documentToString(doc); + } + + public static String getExportedSpeechesWhithTopic(String topic) throws ParserConfigurationException { + Document doc = createXmlDocument(); + + List speeches = getAllSpeechesWithTopic(topic); + + for (Speech speech : speeches) { + addSpeechBySpeech(doc, speech); + } + + return documentToString(doc); + } + + public static String getExportedSpeechesbyIds(List speechIds) throws ParserConfigurationException { + Document doc = createXmlDocument(); + + for (String speechId : speechIds) { + addSpeechById(doc, speechId); + } + + return documentToString(doc); + } +} 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 7226b07..f45ab21 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 @@ -66,10 +66,16 @@ public class RESTHandler { app.get("/reden", SpeechController::listAllSpeeches); // zeige alle Reden an (Filtern möglich) - app.get("/export/pdf/speech/{id}", SpeechesExportController::exportSpeech); // exportiere eine Rede als PDF - app.get("/export/pdf/speaker/{id}", SpeechesExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF - app.get("/export/pdf/topic/{topic}", SpeechesExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF - app.get("/export/pdf/all", SpeechesExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise - app.get("/export/pdf/speeches/{speechIds}", SpeechesExportController::exportSpeeches); // exportiere eine Liste von Reden als PDF + app.get("/export/pdf/speech/{id}", SpeechesLatexExportController::exportSpeech); // exportiere eine Rede als PDF + app.get("/export/pdf/speaker/{id}", SpeechesLatexExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF + app.get("/export/pdf/topic/{topic}", SpeechesLatexExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF + app.get("/export/pdf/all", SpeechesLatexExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise + app.get("/export/pdf/speeches/{speechIds}", SpeechesLatexExportController::exportSpeeches); // exportiere eine Liste von Reden als PDF + + app.get("/export/xml/speech/{id}", SpeechesXMLExportController::exportSpeech); // exportiere eine Rede als XML + app.get("/export/xml/speaker/{id}", SpeechesXMLExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als XML + app.get("/export/xml/topic/{topic}", SpeechesXMLExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als XML + app.get("/export/xml/all", SpeechesXMLExportController::exportAllSpeeches); // exportiere alle Reden als XML + app.get("/export/xml/speeches/{speechIds}", SpeechesXMLExportController::exportSpeeches); // exportiere eine Liste von Reden als XML } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesLatexExportController.java similarity index 99% rename from src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java rename to src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesLatexExportController.java index c6ecf99..f3b6205 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesLatexExportController.java @@ -14,7 +14,7 @@ import java.util.List; import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.*; -public class SpeechesExportController { +public class SpeechesLatexExportController { @OpenApi( summary = "Get a speech as a PDF", description = "Returns a LaTeX generated pdf of a selected speech", diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesXMLExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesXMLExportController.java new file mode 100644 index 0000000..2b73910 --- /dev/null +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesXMLExportController.java @@ -0,0 +1,181 @@ +package org.texttechnologylab.project.gruppe_05_1.rest; + +import io.javalin.http.Context; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiResponse; +import org.texttechnologylab.project.gruppe_05_1.util.Logger; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + +import static org.texttechnologylab.project.gruppe_05_1.export.XMLUtil.*; +import static org.texttechnologylab.project.gruppe_05_1.export.TeXUtil.*; + +public class SpeechesXMLExportController { + @OpenApi( + summary = "Get a speech as XML", + description = "Returns an XML file of a selected speech", + operationId = "getSpeechExport", + path = "/export/xml/speech/{id}", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "XML"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeech(Context ctx) { + String xmlContent; + try { + xmlContent = getExportedSpeechById(ctx.pathParam("id")); + ByteArrayInputStream stream = new ByteArrayInputStream(xmlContent.getBytes()); + if (stream.available() == 0) { + Logger.error("XML stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + ctx.contentType("application/xml"); + ctx.result(stream); + } catch (Exception e) { + Logger.error("Failed to generate Export of Speech with ID " + ctx.pathParam("id")); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + ctx.result("Internal Server Error"); + ctx.status(500); + } + } + + @OpenApi( + summary = "Get all speeches from a speaker as XML", + description = "Returns an XML file of all speeches of a selected speech", + operationId = "getSpeechesFromSpeakerExport", + path = "/export/xml/speaker/{id}", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "XML"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeechesFromSpeaker(Context ctx) { + String xmlContent; + try { + xmlContent = getExportedSpeechesFromSpeakerById(ctx.pathParam("id")); + ByteArrayInputStream stream = new ByteArrayInputStream(xmlContent.getBytes()); + if (stream.available() == 0) { + Logger.error("XML stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + ctx.contentType("application/xml"); + ctx.result(stream); + } catch (Exception e) { + Logger.error("Failed to generate Export of Speeches from Speaker with ID " + ctx.pathParam("id")); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + ctx.result("Internal Server Error"); + ctx.status(500); + } + } + + @OpenApi( + summary = "Get all speeches as XML", + description = "Returns an XML file of all speeches", + operationId = "getAllSpeeches", + path = "/export/xml/all", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "XML"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportAllSpeeches(Context ctx) { + String xmlContent; + try { + xmlContent = getExportedAllSpeeches(); + ByteArrayInputStream stream = new ByteArrayInputStream(xmlContent.getBytes()); + if (stream.available() == 0) { + Logger.error("XML stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + ctx.contentType("application/xml"); + ctx.result(stream); + } catch (Exception e) { + Logger.error("Failed to generate Export of all Speeches"); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + ctx.result("Internal Server Error"); + ctx.status(500); + } + } + + @OpenApi( + summary = "Get all speeches with specific topic as XML", + description = "Returns an XML file of all speeches with specific topic", + operationId = "getAllSpeechesWithTopic", + path = "/export/xml/topic/{topic}", + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "XML"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeechesWithTopic(Context ctx) { + String xmlContent; + try { + xmlContent = getExportedSpeechesWhithTopic(ctx.pathParam("topic")); + ByteArrayInputStream stream = new ByteArrayInputStream(xmlContent.getBytes()); + if (stream.available() == 0) { + Logger.error("XML stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + ctx.contentType("application/xml"); + ctx.result(stream); + } catch (Exception e) { + Logger.error("Failed to generate Export of all Speeches"); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + ctx.result("Internal Server Error"); + ctx.status(500); + } + } + + @OpenApi( + summary = "Get speeches by IDs as XML", + description = "Returns an XML file of the speeches specified by their IDs", + operationId = "getSpeechesByIds", + path = "/export/xml/speeches/{speechIds}", // Comma-separated IDs + methods = HttpMethod.GET, + tags = {"Export", "Speeches", "XML"}, + responses = { + @OpenApiResponse(status = "200") + }) + public static void exportSpeeches(Context ctx) { + String xmlContent; + try { + String speechIdsParam = ctx.pathParam("speechIds"); + List speechIds = Arrays.asList(speechIdsParam.split(",")); + xmlContent = getExportedSpeechesbyIds(speechIds); + ByteArrayInputStream stream = new ByteArrayInputStream(xmlContent.getBytes()); + if (stream.available() == 0) { + Logger.error("XML stream is empty."); + ctx.result("Internal Server Error"); + ctx.status(500); + return; + } + ctx.contentType("application/xml"); + ctx.result(stream); + } catch (Exception e) { + Logger.error("Failed to generate Export of all Speeches"); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + ctx.result("Internal Server Error"); + ctx.status(500); + } + } +} diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java index 96b802b..4a824b1 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Comment_File_Impl.java @@ -3,6 +3,8 @@ package org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Comment; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Content; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.enums.MongoDBEntryType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; public class Comment_File_Impl implements Content, Comment { @@ -47,4 +49,14 @@ public class Comment_File_Impl implements Content, Comment { public String toTeX() { return "\\textcolor{blue}{Kommentar}: " + this.getComment() + "\\\n"; } + + @Override + public Element toXML(Document doc) { + Element comment = doc.createElement("comment"); + comment.setAttribute("contentId", String.valueOf(this.getContentId())); + comment.setAttribute("speechId", String.valueOf(this.getSpeechId())); + comment.setAttribute("commentatorName", this.getCommentatorName()); + comment.setTextContent(this.getComment()); + return comment; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java index f9baea5..72149fc 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Line_File_Impl.java @@ -3,6 +3,8 @@ package org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Content; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Line; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.enums.MongoDBEntryType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; public class Line_File_Impl implements Content, Line { private final int contentId; @@ -39,4 +41,13 @@ public class Line_File_Impl implements Content, Line { public String toTeX() { return this.getContent() + "\\\n"; } + + @Override + public Element toXML(Document doc) { + Element line = doc.createElement("line"); + line.setAttribute("contentId", String.valueOf(this.getContentId())); + line.setAttribute("speechId", String.valueOf(this.getSpeechId())); + line.setTextContent(this.getContent()); + return line; + } } \ No newline at end of file diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java index 4dfe625..8959244 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Impls/Speaker_File_Impl.java @@ -3,6 +3,8 @@ package org.texttechnologylab.project.gruppe_05_1.xml.speeches.Impls; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Content; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speaker; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.enums.MongoDBEntryType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; public class Speaker_File_Impl implements Content, Speaker { @@ -54,4 +56,15 @@ public class Speaker_File_Impl implements Content, Speaker { public String toTeX() { return "\\textcolor{blue}{Redner/Rednerin}: " + this.getSpeakerName() + "\\\n"; } + + @Override + public Element toXML(Document doc) { + Element speaker = doc.createElement("speaker"); + speaker.setAttribute("contentId", String.valueOf(this.getContentId())); + speaker.setAttribute("speechId", String.valueOf(this.getSpeechId())); + speaker.setAttribute("speakerId", String.valueOf(this.getSpeakerId())); + speaker.setAttribute("speakerName", this.getSpeakerName()); + speaker.setAttribute("fraction", this.getFraction()); + return speaker; + } } 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 75eeeaa..aa62491 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 @@ -5,6 +5,8 @@ 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; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import java.util.ArrayList; @@ -121,4 +123,22 @@ public class Speech_File_Impl implements Speech { return tex.toString(); } + + @Override + public Element toXML(Document doc) { + Element speech = doc.createElement("speech"); + speech.setAttribute("sessionId", String.valueOf(this.getSessionId())); + speech.setAttribute("agendaItemId", String.valueOf(this.getAgendaItemId())); + speech.setAttribute("speechId", String.valueOf(this.getSpeechId())); + speech.setAttribute("speakerId", String.valueOf(this.getSpeakerId())); + speech.setAttribute("speakerName", this.getSpeakerName()); + speech.setAttribute("fraction", this.getFraction()); + speech.setAttribute("speechKey", this.getSpeechKey()); + + for (Content content: this.getSpeechContents()) { + speech.appendChild(content.toXML(doc)); + } + + return speech; + } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java index 5543428..da5955e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/xml/speeches/Interfaces/Content.java @@ -1,6 +1,7 @@ package org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces; import org.texttechnologylab.project.gruppe_05_1.xml.speeches.enums.MongoDBEntryType; +import org.w3c.dom.Element; public interface Content { /** @@ -31,4 +32,12 @@ public interface Content { * @return The content. */ String toTeX(); + + /** + * Returns the content as XML. + * + * @param doc The XML document. + * @return The content. + */ + Element toXML(org.w3c.dom.Document doc); } 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 75032ab..2152a6a 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 @@ -3,6 +3,8 @@ 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 org.w3c.dom.Document; +import org.w3c.dom.Element; import java.util.List; @@ -87,4 +89,6 @@ public interface Speech { JCas toCas() throws UIMAException; String toTeX(); + + Element toXML(Document doc); }