OpenPdfRenderer.java

package org.europa.together.application;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.europa.together.application.internal.PdfDocument;
import org.europa.together.application.internal.PdfReplacedElementFactory;
import org.europa.together.business.Logger;
import org.europa.together.business.PdfRenderer;
import org.europa.together.domain.LogLevel;
import org.europa.together.utils.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openpdf.text.pdf.PdfStamper;
import org.springframework.stereotype.Repository;
import org.xhtmlrenderer.layout.SharedContext;
import org.xhtmlrenderer.pdf.ITextRenderer;

/**
 * Implementation of a simple PDF Renderer.
 * <br>
 * https://knpcode.com/java-programs/generating-pdf-java-using-openpdf-tutorial/#HelloWorldOpenPDF
 */
@Repository
public class OpenPdfRenderer implements PdfRenderer {

    private static final long serialVersionUID = 11L;
    private static final Logger LOGGER = new LogbackLogger(OpenPdfRenderer.class);

    //A4
    private String format = "size: 21cm 29.7cm; margin: 20mm 20mm;";

    private String title = "";
    private String subject = "";
    private String author = "";
    private String keywords = "";

    @Override
    public PdfDocument loadDocument(final File pdfDocument)
            throws IOException {
        if (!pdfDocument.exists()) {
            throw new FileNotFoundException();
        }
        return new PdfDocument(pdfDocument.getAbsolutePath());
    }

    @Override
    public void writeDocument(final PdfDocument pdf, final String destination)
            throws IOException, FileNotFoundException {
        PdfStamper pdfStamper = new PdfStamper(pdf, new FileOutputStream(destination));
        pdfStamper.close();
    }

    @Override
    public PdfDocument removePage(final PdfDocument pdf, final int... pages)
            throws IOException {
        PdfDocument newPDF = new PdfDocument(pdf);
        int pagesTotal = newPDF.getNumberOfPages();
        List<Integer> allPages = new ArrayList<>(pagesTotal);
        for (int i = 1; i <= pagesTotal; i++) {
            allPages.add(i);
        }
        for (Integer page : pages) {
            allPages.remove(page);
        }
        newPDF.selectPages(allPages);
        LOGGER.log("Document contains " + newPDF.getNumberOfPages() + " Pages",
                LogLevel.DEBUG);
        return newPDF;
    }

    @Override
    public void renderDocumentFromHtml(final String file, final String template)
            throws FileNotFoundException, IOException {
        StringBuilder html = new StringBuilder();
        html.append("<html>")
                .append("<head>")
                .append("<meta charset=\"UTF-8\" />")
                .append("<title>").append(
                StringUtils.escapeXmlCharacters(getTitle())).append("</title>")
                .append("<meta name=\"author\" content=\"").append(
                StringUtils.escapeXmlCharacters(getAuthor())).append("\" />")
                .append("<meta name=\"subject\" content=\"").append(
                StringUtils.escapeXmlCharacters(getSubject())).append("\" />")
                .append("<meta name=\"keywords\" content=\"").append(
                StringUtils.escapeXmlCharacters(getKeywords())).append("\" />")
                .append("<style>")
                .append("@page {").append(format).append("}")
                .append("</style>")
                .append("</head>")
                .append("<body>")
                .append(template)
                .append("</body></html>");

        Document document = Jsoup.parse(html.toString(), "UTF-8");
        document.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
        LOGGER.log("test", LogLevel.DEBUG);
        try (OutputStream os = new FileOutputStream(file)) {
            ITextRenderer renderer = new ITextRenderer();
            SharedContext sharedContext = renderer.getSharedContext();
            sharedContext.setPrint(true);
            sharedContext.setInteractive(false);
            //IMAGE
            sharedContext.setReplacedElementFactory(new PdfReplacedElementFactory());
            sharedContext.getTextRenderer().setSmoothingThreshold(0);

            renderer.setDocumentFromString(createWellFormedHtml(html.toString()));
            renderer.layout();
            renderer.createPDF(os);
        }
    }

    //<editor-fold defaultstate="collapsed" desc="Getter / Setter">
    @Override
    public void setAuthor(final String author) {
        this.author = author;
    }

    @Override
    public void setKeywords(final String keywords) {
        this.keywords = keywords;
    }

    @Override
    public void setSubject(final String subject) {
        this.subject = subject;
    }

    @Override
    public void setTitle(final String title) {
        this.title = title;
    }

    @Override
    public void setFormat(final String format) {
        this.format = format;
    }

    @Override
    public String getAuthor() {
        return author;
    }

    @Override
    public String getKeywords() {
        return keywords;
    }

    @Override
    public String getSubject() {
        return subject;
    }

    @Override
    public String getTitle() {
        return title;
    }

    @Override
    public String getFormat() {
        return format;
    }
    //</editor-fold>

    private String createWellFormedHtml(final String html) {
        Document content = Jsoup.parse(html, "UTF-8");
        content.outputSettings().syntax(
                Document.OutputSettings.Syntax.xml);
        return content.html();
    }

}