com.github.ukase.bulk.BulkRenderTask.java Source code

Java tutorial

Introduction

Here is the source code for com.github.ukase.bulk.BulkRenderTask.java

Source

/*
 * Copyright (c) 2016 Konstantin Lepa <konstantin+ukase@lepabox.net>
 *
 * This file is part of Ukase.
 *
 *  Ukase is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package com.github.ukase.bulk;

import com.github.ukase.toolkit.RenderTask;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.log4j.Log4j;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Log4j
public class BulkRenderTask {
    private final String id;
    private final List<SingleRenderTask> subTasks;
    private final CountDownLatch latch;
    private final Consumer<String> errorConsumer;
    private final BiConsumer<String, byte[]> dataConsumer;
    private byte[] pdf;

    public BulkRenderTask(List<RenderTask> payloads, BiConsumer<String, byte[]> dataConsumer,
            Consumer<String> errorConsumer) {
        this.dataConsumer = dataConsumer;
        this.errorConsumer = errorConsumer;
        this.id = UUID.randomUUID().toString();
        subTasks = payloads.stream().map(this::createSubTask).collect(Collectors.toList());
        latch = new CountDownLatch(subTasks.size() + 1);
    }

    public String getId() {
        return id;
    }

    public List<RenderTask> getSubTasks() {
        return Collections.unmodifiableList(subTasks);
    }

    public byte[] getResult() throws InterruptedException, IOException {
        latch.await();
        if (pdf == null) {
            throw new IOException("Bulk were failed to be rendered");
        }
        return pdf;
    }

    void childProcessed() {
        latch.countDown();
        if (latch.getCount() == 1) {
            mergeSubTasksPdfs();
        }
    }

    private void mergeSubTasksPdfs() {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            Document document = new Document(PageSize.A4);
            PdfWriter writer = PdfWriter.getInstance(document, baos);
            document.open();
            PdfContentByte cb = writer.getDirectContent();

            appendPdfs(document, writer, cb);

            document.close();
            pdf = baos.toByteArray();
        } catch (IOException | DocumentException e) {
            log.warn("Cannot bulk pdfs", e);
        } finally {
            registerResult();
        }
    }

    private void registerResult() {
        if (pdf != null) {
            dataConsumer.accept(id, pdf);
        } else {
            errorConsumer.accept(id);
        }
        latch.countDown();
    }

    private void appendPdfs(Document document, PdfWriter writer, PdfContentByte cb) throws IOException {
        for (SingleRenderTask task : subTasks) {
            if (task.getPdf() == null) {
                throw new IOException("Some of pdf were failed: " + task.getTemplateName());
            }
            appendPdf(document, writer, cb, task.getPdf());
        }
    }

    private void appendPdf(Document document, PdfWriter writer, PdfContentByte cb, byte[] pdf) throws IOException {
        PdfReader reader = new PdfReader(pdf);
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            PdfImportedPage page = writer.getImportedPage(reader, i);
            document.newPage();
            cb.addTemplate(page, 0, 0);
        }
    }

    private SingleRenderTask createSubTask(RenderTask task) {
        return new SingleRenderTask(task, this);
    }
}