mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Merged feature/dk-misc-20250327 into dev
This commit is contained in:
@ -151,16 +151,21 @@
|
|||||||
<version>2.3</version>
|
<version>2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- the next 2 deps are for html to pdf - per https://www.baeldung.com/java-html-to-pdf -->
|
<!-- the next 3 deps are for html to pdf -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jsoup</groupId>
|
<groupId>org.jsoup</groupId>
|
||||||
<artifactId>jsoup</artifactId>
|
<artifactId>jsoup</artifactId>
|
||||||
<version>1.15.3</version>
|
<version>1.15.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.xhtmlrenderer</groupId>
|
<groupId>com.openhtmltopdf</groupId>
|
||||||
<artifactId>flying-saucer-pdf-openpdf</artifactId>
|
<artifactId>openhtmltopdf-core</artifactId>
|
||||||
<version>9.1.22</version>
|
<version>1.0.10</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.openhtmltopdf</groupId>
|
||||||
|
<artifactId>openhtmltopdf-pdfbox</artifactId>
|
||||||
|
<version>1.0.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- the next 3 deps are being added for google drive support -->
|
<!-- the next 3 deps are being added for google drive support -->
|
||||||
|
@ -26,22 +26,31 @@ import java.nio.file.Path;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction;
|
import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
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.ConvertHtmlToPdfInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfOutput;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
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.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
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!
|
** Action to convert a string of HTML to a PDF!
|
||||||
**
|
**
|
||||||
** Much credit to https://www.baeldung.com/java-html-to-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<ConvertHtmlToPdfInput, ConvertHtmlToPdfOutput>
|
public class ConvertHtmlToPdfAction extends AbstractQActionFunction<ConvertHtmlToPdfInput, ConvertHtmlToPdfOutput>
|
||||||
{
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(ConvertHtmlToPdfAction.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
@ -62,31 +71,32 @@ public class ConvertHtmlToPdfAction extends AbstractQActionFunction<ConvertHtmlT
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// convert the XHTML to PDF //
|
// convert the XHTML to PDF //
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
ITextRenderer renderer = new ITextRenderer();
|
PdfRendererBuilder builder = new PdfRendererBuilder();
|
||||||
SharedContext sharedContext = renderer.getSharedContext();
|
builder.toStream(input.getOutputStream());
|
||||||
sharedContext.setPrint(true);
|
builder.useFastMode();
|
||||||
sharedContext.setInteractive(false);
|
builder.withHtmlContent(document.html(), input.getBasePath() == null ? "./" : input.getBasePath().toUri().toString());
|
||||||
|
|
||||||
if(input.getBasePath() != null)
|
try(PdfBoxRenderer pdfBoxRenderer = builder.buildPdfRenderer())
|
||||||
{
|
{
|
||||||
String baseUrl = input.getBasePath().toUri().toURL().toString();
|
pdfBoxRenderer.layout();
|
||||||
renderer.setDocumentFromString(document.html(), baseUrl);
|
pdfBoxRenderer.getSharedContext().setPrint(true);
|
||||||
}
|
pdfBoxRenderer.getSharedContext().setInteractive(false);
|
||||||
else
|
|
||||||
{
|
|
||||||
renderer.setDocumentFromString(document.html());
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
for(Map.Entry<String, Path> entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet())
|
||||||
// register any custom fonts the input supplied //
|
{
|
||||||
//////////////////////////////////////////////////
|
LOG.warn("Note: Custom fonts appear to not be working in this class at this time...");
|
||||||
for(Map.Entry<String, Path> entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet())
|
pdfBoxRenderer.getFontResolver().addFont(
|
||||||
{
|
entry.getValue().toAbsolutePath().toFile(), // Path to the TrueType font file
|
||||||
renderer.getFontResolver().addFont(entry.getValue().toAbsolutePath().toString(), entry.getKey(), "UTF-8", true, null);
|
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();
|
pdfBoxRenderer.createPDF();
|
||||||
renderer.createPDF(input.getOutputStream());
|
}
|
||||||
|
|
||||||
return (output);
|
return (output);
|
||||||
}
|
}
|
||||||
|
@ -468,7 +468,7 @@ public class QRecord implements Serializable
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public String getValueString(String fieldName)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
public Instant getValueInstant(String fieldName)
|
||||||
{
|
{
|
||||||
return (ValueUtils.getValueAsInstant(values.get(fieldName)));
|
return (ValueUtils.getValueAsInstant(getValue(fieldName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.data;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
@ -198,4 +199,62 @@ public class QRecordWithJoinedRecords extends QRecord
|
|||||||
return (rs);
|
return (rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
@Override
|
||||||
|
public Map<String, List<QRecord>> getAssociatedRecords()
|
||||||
|
{
|
||||||
|
return mainRecord.getAssociatedRecords();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QRecord withAssociatedRecord(String name, QRecord associatedRecord)
|
||||||
|
{
|
||||||
|
mainRecord.withAssociatedRecord(name, associatedRecord);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QRecord withAssociatedRecords(Map<String, List<QRecord>> associatedRecords)
|
||||||
|
{
|
||||||
|
mainRecord.withAssociatedRecords(associatedRecords);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void setAssociatedRecords(Map<String, List<QRecord>> associatedRecords)
|
||||||
|
{
|
||||||
|
mainRecord.setAssociatedRecords(associatedRecords);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QRecord withAssociatedRecords(String name, List<QRecord> associatedRecords)
|
||||||
|
{
|
||||||
|
mainRecord.withAssociatedRecords(name, associatedRecords);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user