com.docdoku.server.extras.TitleBlockGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.docdoku.server.extras.TitleBlockGenerator.java

Source

/*
 * DocDoku, Professional Open Source
 * Copyright 2006 - 2015 DocDoku SARL
 *
 * This file is part of DocDokuPLM.
 *
 * DocDokuPLM 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.
 *
 * DocDokuPLM 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 DocDokuPLM.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.docdoku.server.extras;

import com.docdoku.core.document.DocumentIteration;
import com.docdoku.core.meta.InstanceAttribute;
import com.docdoku.core.product.PartIteration;
import com.docdoku.core.workflow.Activity;
import com.docdoku.core.workflow.Task;
import com.docdoku.core.workflow.Workflow;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.draw.LineSeparator;

import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Morgan Guimard
 *
 * This class define the default pdf generation for both part and document.
 * This behaviour can be overridden:
 * @see com.docdoku.server.extras.PartTitleBlockGenerator
 * @see com.docdoku.server.extras.DocumentTitleBlockGenerator
 */
public abstract class TitleBlockGenerator {

    private static Font NORMAL_12;
    private static Font BOLD_12;
    private static Font BOLD_18;

    protected static final float TABLE_PERCENT_WIDTH = 100f;
    protected static final float SIGNATURE_SIZE_W = 80f;
    protected static final float SIGNATURE_SIZE_H = 60f;

    protected static final String TEMP_FILE_NAME = "output.pdf";

    protected static final String BASE_NAME = "com.docdoku.server.viewers.localization.TitleBlockGenerator";

    protected static final Logger LOGGER = Logger.getLogger(TitleBlockGenerator.class.getName());
    static {
        try {
            BaseFont normal = BaseFont.createFont("com/docdoku/server/viewers/fonts/DejaVuSans.ttf",
                    BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            BaseFont bold = BaseFont.createFont("com/docdoku/server/viewers/fonts/DejaVuSans-Bold.ttf",
                    BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            NORMAL_12 = new Font(normal, 12, Font.NORMAL);
            BOLD_12 = new Font(bold, 12, Font.BOLD);
            BOLD_18 = new Font(bold, 18, Font.BOLD);
        } catch (DocumentException | IOException e) {
            LOGGER.log(Level.SEVERE, null, e);
        }
    }

    protected String title;
    protected String subject;
    protected String authorName;
    protected String version;

    protected String creationDate;
    protected String iterationDate;
    protected String keywords;
    protected String description;
    protected java.util.List<InstanceAttribute> instanceAttributes;
    protected String currentIteration;
    protected Workflow workflow;
    protected Locale pLocale;
    protected String revisionNote;
    protected String lifeCycleState;

    protected void generateHeader(Paragraph preface, ResourceBundle bundle) {
        // Title + description
        preface.add(new Paragraph(title, BOLD_18));
        addEmptyLine(preface, 1);

        if (!description.isEmpty()) {
            preface.add(new Paragraph(description, NORMAL_12));
        }

        // Separator
        LineSeparator separator = new LineSeparator();
        preface.add(separator);
        addEmptyLine(preface, 1);

    }

    protected void generateTable(Paragraph preface, ResourceBundle bundle) {
        // Author + date
        PdfPTable table = new PdfPTable(2);
        table.setWidthPercentage(TABLE_PERCENT_WIDTH);

        PdfPCell cell;

        cell = new PdfPCell(new Phrase(authorName, NORMAL_12));
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        table.addCell(cell);

        cell = new PdfPCell(new Phrase(creationDate, NORMAL_12));
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
        table.addCell(cell);

        preface.add(table);

        addEmptyLine(preface, 1);

        preface.add(new Paragraph(bundle.getString("iteration"), BOLD_12));
        addEmptyLine(preface, 1);

        PdfPTable iterationTable = new PdfPTable(5);
        iterationTable.setWidthPercentage(TABLE_PERCENT_WIDTH);

        // Table header
        cell = new PdfPCell(new Phrase(bundle.getString("iteration.version"), BOLD_12));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(bundle.getString("iteration.iteration"), BOLD_12));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(bundle.getString("iteration.date"), BOLD_12));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(bundle.getString("iteration.author"), BOLD_12));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(bundle.getString("iteration.Notes"), BOLD_12));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        iterationTable.addCell(cell);

        // Table body
        cell = new PdfPCell(new Phrase(version, NORMAL_12));
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(currentIteration, NORMAL_12));
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(iterationDate, NORMAL_12));
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(authorName, NORMAL_12));
        iterationTable.addCell(cell);
        cell = new PdfPCell(new Phrase(revisionNote, NORMAL_12));
        iterationTable.addCell(cell);

        preface.add(iterationTable);
    }

    public void generateAttribute(Paragraph preface, ResourceBundle bundle) {

        // Table title
        preface.add(new Paragraph(bundle.getString("attributes"), BOLD_12));
        addEmptyLine(preface, 1);

        PdfPTable attributesTable = new PdfPTable(2);
        attributesTable.setWidthPercentage(100f);

        // Table head
        PdfPCell cell = new PdfPCell(new Phrase(bundle.getString("attributes.name"), BOLD_12));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        attributesTable.addCell(cell);
        cell = new PdfPCell(new Phrase(bundle.getString("attributes.value"), BOLD_12));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        attributesTable.addCell(cell);

        // Table body

        for (InstanceAttribute attr : instanceAttributes) {
            cell = new PdfPCell(new Phrase(attr.getName(), NORMAL_12));
            attributesTable.addCell(cell);
            Object value = attr.getValue();
            cell = new PdfPCell(new Phrase(value != null ? String.valueOf(value) : "", NORMAL_12));
            attributesTable.addCell(cell);
        }

        preface.add(attributesTable);

    }

    private void generateLyfeCycleState(Paragraph preface, ResourceBundle bundle) {
        // Table title
        preface.add(new Paragraph(bundle.getString("lifecycle") + " : " + lifeCycleState, BOLD_12));
        addEmptyLine(preface, 1);

        PdfPTable lifeCycleTable = new PdfPTable(5);
        lifeCycleTable.setWidthPercentage(100f);
        PdfPCell cell;
        for (Activity activity : workflow.getActivities()) {

            boolean headerRendered = false;

            for (Task task : activity.getTasks()) {

                if (task.isApproved() || task.isRejected()) {

                    if (!headerRendered) {
                        // Table head
                        cell = new PdfPCell(new Phrase(activity.getLifeCycleState(), BOLD_12));
                        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                        cell.setColspan(5);
                        lifeCycleTable.addCell(cell);

                        cell = new PdfPCell(new Phrase(bundle.getString("lifecycle.task"), BOLD_12));
                        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                        lifeCycleTable.addCell(cell);

                        cell = new PdfPCell(new Phrase(bundle.getString("lifecycle.date"), BOLD_12));
                        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                        lifeCycleTable.addCell(cell);

                        cell = new PdfPCell(new Phrase(bundle.getString("lifecycle.author"), BOLD_12));
                        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                        lifeCycleTable.addCell(cell);

                        cell = new PdfPCell(new Phrase(bundle.getString("lifecycle.comments"), BOLD_12));
                        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                        lifeCycleTable.addCell(cell);

                        cell = new PdfPCell(new Phrase(bundle.getString("lifecycle.signature"), BOLD_12));
                        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                        lifeCycleTable.addCell(cell);

                        headerRendered = true;
                    }

                    // Table body
                    cell = new PdfPCell(new Phrase(task.getTitle(), NORMAL_12));
                    lifeCycleTable.addCell(cell);

                    SimpleDateFormat simpleFormat = new SimpleDateFormat(bundle.getString("date.format"));
                    cell = new PdfPCell(new Phrase(simpleFormat.format(task.getClosureDate()), NORMAL_12));
                    lifeCycleTable.addCell(cell);

                    cell = new PdfPCell(new Phrase(task.getWorker().getName(), NORMAL_12));
                    lifeCycleTable.addCell(cell);

                    cell = new PdfPCell(new Phrase(task.getClosureComment(), NORMAL_12));
                    lifeCycleTable.addCell(cell);

                    if (task.getSignature() != null) {
                        try {
                            byte[] imageByte;
                            int indexOfFirstComma = task.getSignature().indexOf(",");
                            String base64 = task.getSignature().substring(indexOfFirstComma + 1,
                                    task.getSignature().length());
                            imageByte = DatatypeConverter.parseBase64Binary(base64);
                            Image image = Image.getInstance(imageByte);
                            image.setCompressionLevel(Image.ORIGINAL_NONE);
                            image.scaleToFit(SIGNATURE_SIZE_W, SIGNATURE_SIZE_H);
                            cell = new PdfPCell(image);
                            lifeCycleTable.addCell(cell);
                        } catch (Exception e) {
                            cell = new PdfPCell(new Phrase(bundle.getString("signature.error"), NORMAL_12));
                            lifeCycleTable.addCell(cell);
                        }

                    } else {
                        cell = new PdfPCell(new Phrase(""));
                        lifeCycleTable.addCell(cell);
                    }

                }
            }

        }

        preface.add(lifeCycleTable);
    }

    /*
    * Generate a block title pdf page and add it to the pdf given in the input stream
    * */
    public InputStream generateBlockTitleToPDF(InputStream inputStream) throws IOException, DocumentException {

        File tmpDir = com.google.common.io.Files.createTempDir();
        File blockTitleFile = new File(tmpDir, inputStream.toString());

        ResourceBundle bundle = ResourceBundle.getBundle(BASE_NAME, pLocale);

        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(blockTitleFile));
        document.open();

        // Main paragraph
        Paragraph preface = new Paragraph();
        generateHeader(preface, bundle);
        generateTable(preface, bundle);
        addEmptyLine(preface, 1);
        if (!instanceAttributes.isEmpty()) {
            generateAttribute(preface, bundle);
            addEmptyLine(preface, 1);
        }
        if (workflow != null) {
            generateLyfeCycleState(preface, bundle);
        }

        document.add(preface);

        addMetaData(document);

        document.close();

        tmpDir.deleteOnExit();

        // Merge the pdf generated with the pdf given in the input stream
        //TODO: use PdfStamper to insert into the existing pdf.
        return mergePdfDocuments(new FileInputStream(blockTitleFile), inputStream);

    }

    /*
    * Merge two pdf from input streams
    * */
    public static InputStream mergePdfDocuments(InputStream input1, InputStream input2) {

        try {
            File tmpDir = com.google.common.io.Files.createTempDir();
            File tmpCopyFile = new File(tmpDir, TEMP_FILE_NAME);
            InputStream[] files = { input1, input2 };

            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, new FileOutputStream(tmpCopyFile));
            doc.open();
            PdfReader pdfReader;

            int n;
            // TODO check for resources to be closed
            for (InputStream file : files) {
                pdfReader = new PdfReader(file);
                n = pdfReader.getNumberOfPages();
                for (int page = 0; page < n;) {
                    copy.addPage(copy.getImportedPage(pdfReader, ++page));
                }
            }

            doc.close();

            tmpDir.deleteOnExit();

            return new FileInputStream(tmpCopyFile);
        } catch (Exception e) {
            LOGGER.log(Level.INFO, null, e);
        }

        return null;
    }

    /*
    * Generate a block title pdf page and add it to the pdf given in the input stream
    * */
    public static InputStream addBlockTitleToPDF(InputStream inputStream, DocumentIteration docI, Locale pLocale)
            throws IOException, DocumentException {
        DocumentTitleBlockGenerator documentTitleBlockGenerator = new DocumentTitleBlockGenerator(inputStream, docI,
                pLocale);
        return documentTitleBlockGenerator.generateBlockTitleToPDF(inputStream);
    }

    public static InputStream addBlockTitleToPDF(InputStream inputStream, PartIteration partIteration,
            Locale pLocale) throws IOException, DocumentException {
        PartTitleBlockGenerator partTitleBlockGenerator = new PartTitleBlockGenerator(inputStream, partIteration,
                pLocale);
        return partTitleBlockGenerator.generateBlockTitleToPDF(inputStream);
    }

    protected static void addEmptyLine(Paragraph paragraph, int number) {
        for (int i = 0; i < number; i++) {
            paragraph.add(new Paragraph(" "));
        }
    }

    protected void addMetaData(Document document) {
        document.addTitle(title);
        document.addSubject(subject);
        document.addKeywords(keywords);
        document.addAuthor(authorName);
        document.addCreator(authorName);
    }

}