fr.ybonnel.breizhcamppdf.PdfRenderer.java Source code

Java tutorial

Introduction

Here is the source code for fr.ybonnel.breizhcamppdf.PdfRenderer.java

Source

/*
 * Copyright 2013- Yan Bonnel
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fr.ybonnel.breizhcamppdf;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.html.simpleparser.HTMLWorker;
import com.itextpdf.text.pdf.*;
import com.petebevin.markdown.MarkdownProcessor;
import fr.ybonnel.breizhcamppdf.model.Speaker;
import fr.ybonnel.breizhcamppdf.model.Talk;
import fr.ybonnel.breizhcamppdf.model.TalkDetail;

import java.awt.*;
import java.io.IOException;
import java.io.StringReader;
import java.util.*;
import java.util.List;

public class PdfRenderer {

    private static final Font talkFont = FontFactory.getFont(FontFactory.HELVETICA, 11, Font.NORMAL,
            BaseColor.BLACK);
    private static final Font speakerFont = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.NORMAL,
            BaseColor.BLACK);

    private static final Font themeFont = FontFactory.getFont(FontFactory.HELVETICA, 8, Font.ITALIC,
            BaseColor.GRAY);

    private static final Font presentFont = FontFactory.getFont(FontFactory.HELVETICA, 13, Font.BOLD,
            BaseColor.GRAY);

    private static final Font talkFontTitle = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 17, Font.UNDERLINE,
            BaseColor.DARK_GRAY);

    private Document document;
    private PdfWriter pdfWriter;
    private DataService service = new DataService();

    public PdfRenderer(Document document, PdfWriter pdfWriter) {
        this.document = document;
        this.pdfWriter = pdfWriter;
    }

    public void render() throws DocumentException, IOException {

        // Footer
        pdfWriter.setPageEvent(new PdfPageEventHelper() {
            @Override
            public void onEndPage(PdfWriter writer, Document document) {

                if (writer.getPageNumber() > 1) {
                    Rectangle rect = document.getPageSize();
                    ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER,
                            new Phrase("BreizhCamp 2014"), (rect.getLeft() + rect.getRight()) / 2,
                            rect.getBottom() + 18, 0);
                }
            }
        });

        createFirstPage();
        List<Talk> talksToExplain = createProgrammePages();
        createTalksPages(talksToExplain);
    }

    private void createFirstPage() throws DocumentException, IOException {
        Rectangle savePagesize = document.getPageSize();
        document.setPageSize(PageSize.A4);
        document.newPage();
        Image imageLogo = Image.getInstance(PdfRenderer.class.getResource("/logo.png"));
        imageLogo.scaleToFit(document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin(),
                imageLogo.getHeight());
        document.add(imageLogo);

        Paragraph paragraph = new Paragraph("21, 22 et 23 mai");
        paragraph.setSpacingAfter(80);
        paragraph.getFont().setSize(20);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        document.add(paragraph);

        Paragraph title = new Paragraph("Programme 2014");
        title.setSpacingAfter(100);
        title.getFont().setSize(56);
        title.setAlignment(Element.ALIGN_CENTER);
        document.add(title);

        PdfPTable sponsors = new PdfPTable(4);
        sponsors.setWidthPercentage(90f);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/LogoZenika-H-(Quadri).jpg", 2);
        addSponsor(sponsors,
                "http://blogs.technet.com/resized-image.ashx/__size/450x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-80-54/6864.Microsoft-Logo.png",
                2);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/Google_Logo_3564x1189.png", 1);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/cbpaas.jpeg", 1);
        addSponsor(sponsors, "https://github.global.ssl.fastly.net/images/modules/logos_page/GitHub-Logo.png", 1);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/sonarsource-300x94.png", 1);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/serli.png", 1);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/Logo_sqli_group.png", 1);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/SofteamCadextanLogo_w200.png", 1);
        addSponsor(sponsors, "http://www.breizhcamp.org/img/logoSII_w200.png", 1);
        document.add(sponsors);

        Image istic = Image.getInstance("http://www.breizhcamp.org/img/Logo_ISTIC_BLACK_FRA.jpg");
        istic.scaleToFit(150, 150);
        istic.setAlignment(Element.ALIGN_CENTER);
        document.add(istic);

        document.setPageSize(savePagesize);
    }

    private void addSponsor(PdfPTable sponsors, String imageUrl, int colspan)
            throws DocumentException, IOException {
        PdfPCell sponsor = new PdfPCell();
        sponsor.setImage(Image.getInstance(imageUrl));
        sponsor.setColspan(colspan);
        sponsor.setBorder(Rectangle.NO_BORDER);
        sponsor.setVerticalAlignment(Element.ALIGN_MIDDLE);
        sponsors.addCell(sponsor);
    }

    private PdfPCell createHeaderCell(String content) {
        Paragraph paragraph = new Paragraph();
        Font font = new Font();
        font.setColor(BaseColor.WHITE);
        paragraph.setFont(font);
        paragraph.add(new Phrase(content));
        PdfPCell cell = new PdfPCell(paragraph);
        cell.setPaddingBottom(10);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setBackgroundColor(BaseColor.GRAY);
        return cell;
    }

    private int getRowSpan(String date, Talk talk) {

        int count = 0;
        for (String otherCreneau : service.getCreneaux().get(date)) {
            if (otherCreneau.compareTo(talk.getStart()) >= 0 && otherCreneau.compareTo(talk.getEnd()) < 0) {
                count++;
            }
        }
        return count;
    }

    private List<Talk> createProgrammePages() throws DocumentException, IOException {
        List<Talk> talksToExplain = new ArrayList<>();
        document.setPageSize(PageSize.A4.rotate());
        Font font = new Font();
        font.setStyle(Font.BOLD);
        font.setSize(14);

        for (String date : service.getDates()) {

            Set<String> tracksInPage = new HashSet<>();

            Map<String, Talk> precedentTalk = new HashMap<>();
            PdfPTable table = createBeginningOfPage(font, date);
            for (String creneau : service.getCreneaux().get(date)) {
                // Nouvelle page  14h
                if (creneau.startsWith("14:00") && !tracksInPage.isEmpty()) {
                    document.add(table);

                    addLegend(tracksInPage);
                    table = createBeginningOfPage(font, date);
                }

                PdfPCell cellCreneau = new PdfPCell();
                cellCreneau.setPaddingBottom(10);
                Paragraph startTime = new Paragraph(creneau);
                startTime.setAlignment(Element.ALIGN_CENTER);
                cellCreneau.addElement(startTime);
                Paragraph endTime = new Paragraph(getEndTime(date, creneau));
                endTime.setAlignment(Element.ALIGN_CENTER);
                cellCreneau.addElement(endTime);
                table.addCell(cellCreneau);
                for (String room : service.getRooms(date)) {
                    PdfPCell cell = new PdfPCell();
                    cell.setPaddingBottom(10);
                    cell.setHorizontalAlignment(Element.ALIGN_LEFT);

                    Talk talk = service.getTalkByDateAndCreneauxAndRoom(date, creneau, room);
                    if (talk != null) {
                        talksToExplain.add(talk);
                        remplirCellWithTalk(cell, talk);
                        cell.setRowspan(getRowSpan(date, talk));
                        precedentTalk.put(room, talk);
                        tracksInPage.add(talk.getTrack());
                        table.addCell(cell);
                    } else {
                        talk = precedentTalk.get(room);
                        if (!(talk != null && talk.getEnd().compareTo(creneau) > 0)) {
                            table.addCell(cell);
                        }
                    }
                }
            }
            document.add(table);
            addLegend(tracksInPage);
        }
        return talksToExplain;
    }

    private String getEndTime(String date, String creneau) {
        String endTime = "99:99";
        for (String room : service.getRooms(date)) {
            Talk talk = service.getTalkByDateAndCreneauxAndRoom(date, creneau, room);
            if (talk != null && talk.getEnd().compareTo(endTime) < 0) {
                endTime = talk.getEnd();
            }
        }
        return endTime;
    }

    private void addLegend(Set<String> tracksInPage) throws DocumentException {
        PdfPTable legend = new PdfPTable(tracksInPage.size() + 1);
        legend.setWidthPercentage(100f);
        PdfPCell cellTitle = new PdfPCell(new Phrase("Lgende : ", speakerFont));
        cellTitle.setBorder(Rectangle.NO_BORDER);
        cellTitle.setHorizontalAlignment(Element.ALIGN_CENTER);
        cellTitle.setPadding(2);
        legend.addCell(cellTitle);

        for (String track : tracksInPage) {
            PdfPCell color = new PdfPCell(new Phrase(track, speakerFont));
            color.setHorizontalAlignment(Element.ALIGN_CENTER);
            color.setPadding(2);
            color.setBackgroundColor(mapTrack.get(track));
            legend.addCell(color);
        }
        tracksInPage.clear();
        document.add(legend);
    }

    private PdfPTable createBeginningOfPage(Font font, String date) throws DocumentException {
        Paragraph titre;
        document.newPage();
        titre = new Paragraph();
        titre.setFont(font);
        titre.setAlignment(Paragraph.ALIGN_CENTER);
        titre.add(new Phrase("Programme du " + date));
        document.add(titre);

        float[] relativeWidth = new float[service.getRooms(date).size() + 1];
        Arrays.fill(relativeWidth, 1f);
        relativeWidth[0] = 0.5f;

        PdfPTable table = new PdfPTable(relativeWidth);

        table.setWidthPercentage(100);
        table.setSpacingBefore(10);
        table.setSpacingAfter(20);

        table.addCell(createHeaderCell("Heure"));
        for (String room : service.getRooms(date)) {
            table.addCell(createHeaderCell(room));
        }
        return table;
    }

    private static final Map<String, BaseColor> mapTrack = new HashMap<String, BaseColor>() {
        {
            BaseColor jaune = new BaseColor(Color.decode("#F9DB0B"));
            BaseColor orange = new BaseColor(Color.decode("#FF8C00"));
            BaseColor vert = new BaseColor(Color.decode("#56C566"));
            BaseColor bleu = new BaseColor(Color.decode("#B0C4DE"));
            BaseColor violet = new BaseColor(Color.decode("#A174B9"));

            put("Web", jaune);
            put("Cloud et BigData", orange);
            put("Agilit", vert);
            put("DevOps", bleu);
            put("Internet of Things", violet);
            put("Hardware", violet);

            put("Keynote", new BaseColor(Color.decode("#F8ECDE")));
            put("Architecture", orange);
            put("Langages", bleu);
            put("dcouverte", violet);
            put("Web et Mobile", jaune);
            put("Tooling", vert);
            put("Tool", vert);
        }
    };

    private void remplirCellWithTalk(PdfPCell cell, Talk talk) throws DocumentException, IOException {
        Image image = AvatarService.INSTANCE.getImage(
                PdfRenderer.class.getResource("/formats/" + talk.getFormat().replaceAll(" ", "") + ".png"));

        float[] widths = { 0.15f, 0.85f };
        PdfPTable table = new PdfPTable(widths);
        table.setWidthPercentage(100f);
        table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
        table.addCell(image);
        PdfPCell subCell = new PdfPCell();
        Chunk chunk = new Chunk(talk.getTitle(), talkFont);
        chunk.setLocalGoto("talk" + talk.getId());
        Paragraph titleTalk = new Paragraph();
        titleTalk.add(chunk);
        titleTalk.setAlignment(Paragraph.ALIGN_CENTER);
        subCell.addElement(titleTalk);
        Paragraph track = new Paragraph(new Phrase(talk.getTrack(), themeFont));
        track.setAlignment(Paragraph.ALIGN_CENTER);

        subCell.addElement(track);
        TalkDetail detail = TalkService.INSTANCE.getTalkDetail(talk);
        if (detail != null) {
            for (Speaker speaker : detail.getSpeakers()) {
                Paragraph speakerText = new Paragraph(speaker.getFullname(), speakerFont);
                speakerText.setAlignment(Paragraph.ALIGN_CENTER);
                subCell.addElement(speakerText);
            }
        }
        subCell.setBorder(Rectangle.NO_BORDER);
        table.addCell(subCell);
        cell.setBackgroundColor(mapTrack.get(talk.getTrack()));
        cell.addElement(table);
    }

    private MarkdownProcessor markdownProcessor = new MarkdownProcessor();

    private void createTalksPages(List<Talk> talksToExplain) throws DocumentException, IOException {
        document.setPageSize(PageSize.A4);
        document.newPage();

        Paragraph paragraph = new Paragraph("Liste des talks");
        paragraph.setSpacingAfter(25);
        paragraph.getFont().setSize(25);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        document.add(paragraph);

        for (TalkDetail talk : Lists.transform(talksToExplain, new Function<Talk, TalkDetail>() {
            @Override
            public TalkDetail apply(Talk input) {
                return TalkService.INSTANCE.getTalkDetail(input);
            }
        })) {

            if (talk == null) {
                continue;
            }

            Paragraph empty = new Paragraph(" ");
            PdfPTable table = new PdfPTable(1);
            table.setWidthPercentage(100);
            table.setKeepTogether(true);
            table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
            PdfPCell cell;
            Chunk titleTalk = new Chunk(talk.getTitle(), talkFontTitle);
            titleTalk.setLocalDestination("talk" + talk.getId());
            float[] withTitle = { 0.05f, 0.95f };
            PdfPTable titleWithFormat = new PdfPTable(withTitle);
            titleWithFormat.getDefaultCell().setBorder(Rectangle.NO_BORDER);
            titleWithFormat.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);

            Image image = AvatarService.INSTANCE.getImage(PdfRenderer.class
                    .getResource("/formats/" + talk.getTalk().getFormat().replaceAll(" ", "") + ".png"));
            titleWithFormat.addCell(image);
            titleWithFormat.addCell(new Paragraph(titleTalk));

            table.addCell(titleWithFormat);

            table.addCell(empty);

            table.addCell(new Paragraph("Salle " + talk.getTalk().getRoom() + " de " + talk.getTalk().getStart()
                    + "  " + talk.getTalk().getEnd(), presentFont));

            table.addCell(empty);

            cell = new PdfPCell();
            cell.setBorder(0);
            cell.setHorizontalAlignment(Element.ALIGN_JUSTIFIED);
            for (Element element : HTMLWorker
                    .parseToList(new StringReader(markdownProcessor.markdown(talk.getDescription())), null)) {
                if (element instanceof Paragraph) {
                    ((Paragraph) element).setAlignment(Element.ALIGN_JUSTIFIED);
                }
                cell.addElement(element);
            }
            table.addCell(cell);

            table.addCell(empty);

            table.addCell(new Paragraph("Prsent par :", presentFont));

            float[] widthSpeaker = { 0.05f, 0.95f };
            for (Speaker speaker : talk.getSpeakers()) {
                PdfPTable speakerWithAvatar = new PdfPTable(widthSpeaker);
                speakerWithAvatar.getDefaultCell().setBorder(Rectangle.NO_BORDER);
                speakerWithAvatar.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);

                speakerWithAvatar.addCell(AvatarService.INSTANCE.getImage(speaker.getAvatar()));
                speakerWithAvatar.addCell(new Phrase(speaker.getFullname()));
                table.addCell(speakerWithAvatar);
            }

            table.addCell(empty);
            table.addCell(empty);
            document.add(table);
        }
    }
}