diff --git a/qqq-backend-core/pom.xml b/qqq-backend-core/pom.xml index 21723b83..63a24365 100644 --- a/qqq-backend-core/pom.xml +++ b/qqq-backend-core/pom.xml @@ -151,16 +151,21 @@ 2.3 - + org.jsoup jsoup 1.15.3 - org.xhtmlrenderer - flying-saucer-pdf-openpdf - 9.1.22 + com.openhtmltopdf + openhtmltopdf-core + 1.0.10 + + + com.openhtmltopdf + openhtmltopdf-pdfbox + 1.0.10 diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java index a7f9096f..d2dbdac1 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java @@ -26,22 +26,31 @@ import java.nio.file.Path; import java.util.Map; import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction; import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfInput; import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfOutput; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; +import com.openhtmltopdf.css.constants.IdentValue; +import com.openhtmltopdf.pdfboxout.PdfBoxFontResolver; +import com.openhtmltopdf.pdfboxout.PdfBoxRenderer; +import com.openhtmltopdf.pdfboxout.PdfRendererBuilder; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; -import org.xhtmlrenderer.layout.SharedContext; -import org.xhtmlrenderer.pdf.ITextRenderer; /******************************************************************************* ** Action to convert a string of HTML to a PDF! ** ** Much credit to https://www.baeldung.com/java-html-to-pdf - *******************************************************************************/ + ** + ** Updated in March 2025 to go from flying-saucer-pdf-openpdf lib to openhtmltopdf, + ** mostly to get support for max-height on images... + ********************************************************************************/ public class ConvertHtmlToPdfAction extends AbstractQActionFunction { + private static final QLogger LOG = QLogger.getLogger(ConvertHtmlToPdfAction.class); + + /******************************************************************************* ** @@ -62,31 +71,32 @@ public class ConvertHtmlToPdfAction extends AbstractQActionFunction entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet()) - { - renderer.getFontResolver().addFont(entry.getValue().toAbsolutePath().toString(), entry.getKey(), "UTF-8", true, null); - } + for(Map.Entry entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet()) + { + LOG.warn("Note: Custom fonts appear to not be working in this class at this time..."); + pdfBoxRenderer.getFontResolver().addFont( + entry.getValue().toAbsolutePath().toFile(), // Path to the TrueType font file + entry.getKey(), // Font family name to use in CSS + 400, // Font weight (e.g., 400 for normal, 700 for bold) + IdentValue.NORMAL, // Font style (e.g., NORMAL, ITALIC) + true, // Whether to subset the font + PdfBoxFontResolver.FontGroup.MAIN // ?? + ); + } - renderer.layout(); - renderer.createPDF(input.getOutputStream()); + pdfBoxRenderer.createPDF(); + } return (output); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java index cc3b0f6c..194e59da 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java @@ -468,7 +468,7 @@ public class QRecord implements Serializable *******************************************************************************/ public String getValueString(String fieldName) { - return (ValueUtils.getValueAsString(values.get(fieldName))); + return (ValueUtils.getValueAsString(getValue(fieldName))); } @@ -479,7 +479,7 @@ public class QRecord implements Serializable *******************************************************************************/ public Integer getValueInteger(String fieldName) { - return (ValueUtils.getValueAsInteger(values.get(fieldName))); + return (ValueUtils.getValueAsInteger(getValue(fieldName))); } @@ -490,7 +490,7 @@ public class QRecord implements Serializable *******************************************************************************/ public Long getValueLong(String fieldName) { - return (ValueUtils.getValueAsLong(values.get(fieldName))); + return (ValueUtils.getValueAsLong(getValue(fieldName))); } @@ -500,7 +500,7 @@ public class QRecord implements Serializable *******************************************************************************/ public BigDecimal getValueBigDecimal(String fieldName) { - return (ValueUtils.getValueAsBigDecimal(values.get(fieldName))); + return (ValueUtils.getValueAsBigDecimal(getValue(fieldName))); } @@ -510,7 +510,7 @@ public class QRecord implements Serializable *******************************************************************************/ public Boolean getValueBoolean(String fieldName) { - return (ValueUtils.getValueAsBoolean(values.get(fieldName))); + return (ValueUtils.getValueAsBoolean(getValue(fieldName))); } @@ -520,7 +520,7 @@ public class QRecord implements Serializable *******************************************************************************/ public LocalTime getValueLocalTime(String fieldName) { - return (ValueUtils.getValueAsLocalTime(values.get(fieldName))); + return (ValueUtils.getValueAsLocalTime(getValue(fieldName))); } @@ -530,7 +530,7 @@ public class QRecord implements Serializable *******************************************************************************/ public LocalDate getValueLocalDate(String fieldName) { - return (ValueUtils.getValueAsLocalDate(values.get(fieldName))); + return (ValueUtils.getValueAsLocalDate(getValue(fieldName))); } @@ -540,7 +540,7 @@ public class QRecord implements Serializable *******************************************************************************/ public byte[] getValueByteArray(String fieldName) { - return (ValueUtils.getValueAsByteArray(values.get(fieldName))); + return (ValueUtils.getValueAsByteArray(getValue(fieldName))); } @@ -550,7 +550,7 @@ public class QRecord implements Serializable *******************************************************************************/ public Instant getValueInstant(String fieldName) { - return (ValueUtils.getValueAsInstant(values.get(fieldName))); + return (ValueUtils.getValueAsInstant(getValue(fieldName))); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java index aa773687..70796b49 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java @@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.data; import java.io.Serializable; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.function.BiFunction; @@ -198,4 +199,62 @@ public class QRecordWithJoinedRecords extends QRecord return (rs); } + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public Map> getAssociatedRecords() + { + return mainRecord.getAssociatedRecords(); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public QRecord withAssociatedRecord(String name, QRecord associatedRecord) + { + mainRecord.withAssociatedRecord(name, associatedRecord); + return (this); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public QRecord withAssociatedRecords(Map> associatedRecords) + { + mainRecord.withAssociatedRecords(associatedRecords); + return (this); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public void setAssociatedRecords(Map> associatedRecords) + { + mainRecord.setAssociatedRecords(associatedRecords); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public QRecord withAssociatedRecords(String name, List associatedRecords) + { + mainRecord.withAssociatedRecords(name, associatedRecords); + return (this); + } + }