com.actelion.research.spiritapp.print.CagePrinterPDF.java Source code

Java tutorial

Introduction

Here is the source code for com.actelion.research.spiritapp.print.CagePrinterPDF.java

Source

/*
 * Spirit, a study/biosample management tool for research.
 * Copyright (C) 2018 Idorsia Pharmaceuticals Ltd., Hegenheimermattweg 91,
 * CH-4123 Allschwil, Switzerland.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 * @author Joel Freyss
 */

package com.actelion.research.spiritapp.print;

import java.awt.Color;
import java.awt.Desktop;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import com.actelion.research.spiritcore.business.biosample.Biosample;
import com.actelion.research.spiritcore.business.biosample.BiotypeMetadata;
import com.actelion.research.spiritcore.business.biosample.Container;
import com.actelion.research.spiritcore.business.study.Group;
import com.actelion.research.spiritcore.business.study.NamedTreatment;
import com.actelion.research.spiritcore.business.study.Study;
import com.actelion.research.spiritcore.util.MiscUtils;
import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.FontFactory;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.ColumnText;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;

public class CagePrinterPDF {

    public static void printCages(List<Container> cages, boolean printGroupsTreatments, boolean printTreatmentDesc,
            boolean whiteBackground) throws Exception {
        final int margin = 15;
        File f = File.createTempFile("cages__", ".pdf");
        Document doc = new Document(PageSize.A4.rotate());
        Image maleImg, femaleImg, nosexImg;
        try {
            maleImg = Image.getInstance(CagePrinterPDF.class.getResource("male.png"));
            femaleImg = Image.getInstance(CagePrinterPDF.class.getResource("female.png"));
            nosexImg = Image.getInstance(CagePrinterPDF.class.getResource("nosex.png"));
        } catch (Exception e) {
            throw new Exception("Could not find images in the classpath: " + e);
        }

        FileOutputStream os = new FileOutputStream(f);
        PdfWriter writer = PdfWriter.getInstance(doc, os);
        doc.open();

        PdfContentByte canvas = writer.getDirectContentUnder();

        float tileW = (doc.getPageSize().getWidth()) / 4;
        float tileH = (doc.getPageSize().getHeight()) / 2;
        for (int i = 0; i < cages.size(); i++) {
            Container cage = cages.get(i);

            Study study = cage.getStudy();
            Set<Group> groups = cage.getGroups();
            Group group = cage.getGroup();
            Set<Biosample> animals = new TreeSet<>(Biosample.COMPARATOR_NAME);
            animals.addAll(cage.getBiosamples());

            //Find the treatments applied to this group
            Set<NamedTreatment> allTreatments = new LinkedHashSet<>();
            for (Group gr : groups) {
                allTreatments.addAll(gr.getAllTreatments(-1));
            }

            //Draw
            if (i % 8 == 0) {
                if (i > 0)
                    doc.newPage();
                drawCageSeparation(doc, canvas);
            }

            int col = (i % 8) % 4;
            int row = (i % 8) / 4;

            float x = margin + tileW * col;
            float x2 = x + tileW - margin;
            float baseY = tileH * row;
            float y;

            //Display Sex
            canvas.moveTo(tileW * col - 50, doc.getPageSize().getHeight() - (tileH * row + 50));
            Image img = null;
            String sex = getMetadata(animals, "Sex");
            if (study.isBlindAll()) {
                img = nosexImg;
            } else if (sex.equals("M")) {
                img = maleImg;
            } else if (sex.equals("F")) {
                img = femaleImg;
            } else if (sex.length() > 0) {
                img = nosexImg;
            }
            if (img != null) {
                img.scaleToFit(20, 20);
                img.setAbsolutePosition(tileW * (col + 1) - 33,
                        doc.getPageSize().getHeight() - (tileH * row + 12 + margin));
                doc.add(img);
            }
            if (group != null && group.getColor() != null && (study != null && !study.isBlind())
                    && !whiteBackground) {
                Color c = group.getColor();
                canvas.saveState();
                canvas.setRGBColorFill(c.getRed() / 3 + 170, c.getGreen() / 3 + 170, c.getBlue() / 3 + 170);
                canvas.rectangle(x - margin + 1, doc.getPageSize().getHeight() - baseY - tileH + 1, tileW - 2,
                        tileH - 2);
                canvas.fill();
                canvas.restoreState();
            }
            Color treatmentColor = Color.BLACK;
            if (allTreatments.size() > 0 && !study.isBlind() && printGroupsTreatments) {
                int offset = 0;
                for (NamedTreatment t : allTreatments) {
                    if (t.getColor() != null) {
                        if (allTreatments.size() == 1)
                            treatmentColor = new Color(t.getColor().getRed() / 2, t.getColor().getGreen() / 2,
                                    t.getColor().getBlue() / 2);
                        canvas.saveState();
                        canvas.setColorStroke(Color.BLACK);
                        canvas.setRGBColorFill(t.getColor().getRed(), t.getColor().getGreen(),
                                t.getColor().getBlue());
                        y = baseY + 42 + 15 + 86 + 13 + 22 + 14 + 23 + 28;
                        canvas.rectangle(x + 20 + offset * 5, doc.getPageSize().getHeight() - y - (offset % 2) * 4,
                                22, 22);
                        canvas.fillStroke();
                        canvas.restoreState();
                        offset++;
                    }
                }
            }

            canvas.beginText();
            canvas.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA_BOLD, "Cp1252", false), 16f);
            canvas.showTextAligned(Element.ALIGN_LEFT, cage.getContainerId(), x,
                    doc.getPageSize().getHeight() - (baseY + 23), 0);

            canvas.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA_OBLIQUE, "Cp1252", false), 11f);
            y = 42 + baseY;
            canvas.showTextAligned(Element.ALIGN_LEFT, "Type: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 15;
            canvas.showTextAligned(Element.ALIGN_LEFT, "Animals_ID: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 86;
            canvas.showTextAligned(Element.ALIGN_LEFT, "Delivery date: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 13;
            canvas.showTextAligned(Element.ALIGN_LEFT, "PO Number: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 22;
            canvas.showTextAligned(Element.ALIGN_LEFT, "Study: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 14;
            if (study != null && !study.isBlind() && printGroupsTreatments)
                canvas.showTextAligned(Element.ALIGN_LEFT, "Group: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 23;
            if (study != null && !study.isBlind() && printGroupsTreatments)
                canvas.showTextAligned(Element.ALIGN_LEFT, "Treatment: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 50;
            canvas.showTextAligned(Element.ALIGN_LEFT, "License: ", x, doc.getPageSize().getHeight() - y, 0);
            y += 13;
            canvas.showTextAligned(Element.ALIGN_LEFT, "Experimenter: ", x, doc.getPageSize().getHeight() - y, 0);
            canvas.endText();

            y = 42 + baseY;
            print(canvas, study.isBlindAll() ? "Blinded" : getMetadata(animals, "Type"), x + 65,
                    doc.getPageSize().getHeight() - y, x2, 11, 11, FontFactory.HELVETICA, Color.BLACK, 11f);
            y += 15;

            if (animals.size() <= 6) {
                int n = 0;
                for (Biosample animal : animals) {
                    print(canvas, animal.getSampleId(), x + 75, doc.getPageSize().getHeight() - y - 12 * n, x2 - 50,
                            12, 12, FontFactory.HELVETICA, Color.BLACK, 11f);
                    if (animal.getSampleName() != null && animal.getSampleName().length() > 0) {
                        print(canvas, "[ " + animal.getSampleName() + " ]", x2 - 60,
                                doc.getPageSize().getHeight() - y - 12 * n, x2, 12, 12, FontFactory.HELVETICA_BOLD,
                                Color.BLACK, 11f);
                    }
                    n++;
                }
            } else {
                int nPerRow = animals.size() / 2;
                int n = 0;
                for (Biosample animal : animals) {
                    int nx = n / nPerRow;
                    int ny = n % nPerRow;
                    print(canvas, animal.getSampleId(), x + nx * (x2 - x) / 2,
                            doc.getPageSize().getHeight() - y - 12 * ny - 12, x + (1 + nx) * (x2 - x) / 2, 12, 12,
                            FontFactory.HELVETICA, Color.BLACK, 10f);
                    if (animal.getSampleName() != null && animal.getSampleName().length() > 0) {
                        print(canvas, "[ " + animal.getSampleName() + " ]", x + (1 + nx) * (x2 - x) / 2 - 35,
                                doc.getPageSize().getHeight() - y - 12 * ny - 12, x + (1 + nx) * (x2 - x) / 2, 12,
                                12, FontFactory.HELVETICA_BOLD, Color.BLACK, 10f);
                    }
                    n++;
                }
            }

            y += 86;
            print(canvas, getMetadata(animals, "Delivery Date"), x + 75, doc.getPageSize().getHeight() - y, x2, 0,
                    10, FontFactory.HELVETICA, Color.BLACK, 10f);
            y += 13;
            print(canvas, getMetadata(animals, "PO Number"), x + 75, doc.getPageSize().getHeight() - y, x2, 0, 10,
                    FontFactory.HELVETICA, Color.BLACK, 10f);
            y += 22;
            print(canvas, study.getStudyIdAndInternalId(), x + 40, doc.getPageSize().getHeight() - y, x2, 0, 11,
                    BaseFont.HELVETICA_BOLD, Color.BLACK, 11f);
            y += 14;
            if (!study.isBlind() && printGroupsTreatments)
                print(canvas, getGroups(animals), x + 40, doc.getPageSize().getHeight() - y, x2, 22, 11,
                        BaseFont.HELVETICA_BOLD, Color.BLACK, 11f);
            y += 23;
            if (!study.isBlind() && printGroupsTreatments)
                print(canvas, getTreatments(animals, printTreatmentDesc), x + 62, doc.getPageSize().getHeight() - y,
                        x2, 50, printTreatmentDesc ? 9 : 12, FontFactory.HELVETICA, treatmentColor,
                        printTreatmentDesc ? 9f : 10f);
            y += 50;
            print(canvas, study.getMetadataMap().get("LICENSENO"), x + 74, doc.getPageSize().getHeight() - y, x2,
                    15, 10, FontFactory.HELVETICA, Color.BLACK, 10f);
            y += 13;
            print(canvas, study.getMetadataMap().get("EXPERIMENTER"), x + 74, doc.getPageSize().getHeight() - y, x2,
                    20, 10, FontFactory.HELVETICA, Color.BLACK, 10f);
        }

        doc.close();
        os.close();
        Desktop.getDesktop().open(f);
        try {
            Thread.sleep(500);
        } catch (Exception e) {
        }

    }

    private static void print(PdfContentByte canvas, String txt, float x, float y, float maxX, int maxHeight,
            int lineHeight, String fontName, Color color, float fontSize) throws Exception {
        float width = maxX - x - 5;
        float minY = Math.min(y, y - maxHeight + lineHeight - 3);
        if (txt == null)
            return;

        canvas.setFontAndSize(BaseFont.createFont(fontName, "Cp1252", false), fontSize);
        while (txt.length() > 0 && y >= minY) {
            int index = 0;
            while (true) {
                int index2 = index + 1;
                if (index2 >= txt.length()) {
                    index = index2;
                    break;
                }
                float w = canvas.getEffectiveStringWidth(txt.substring(0, index2), true);
                System.out.println("CagePrinterPDF.print()   " + txt.substring(0, index2) + " " + w + "," + width);
                if (w > width)
                    break;
                index = index2;
            }
            if (index < 0)
                index = txt.length();
            String t = txt.substring(0, index);
            System.out.println(
                    "CagePrinterPDF.print() " + t + " at " + x + "x" + y + " (of " + txt + ") minY=" + minY);
            txt = txt.substring(index).trim();
            Phrase phrase = new Paragraph(t, FontFactory.getFont(fontName, fontSize, color));
            ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, x, y, 0);
            y -= lineHeight;
        }
    }

    private static String getGroups(Collection<Biosample> animals) {
        Set<String> res = new LinkedHashSet<>();
        for (Group g : Biosample.getGroups(animals)) {
            res.add(g == null ? "N/A" : g.getName());
        }
        return MiscUtils.flatten(res);
    }

    private static String getTreatments(Collection<Biosample> animals, boolean printTreatmentDesc) {
        Set<String> res = new LinkedHashSet<>();
        Set<Group> groups = Biosample.getGroups(animals);
        for (Group gr : groups) {
            String s = gr == null ? ""
                    : gr.getTreatmentDescription(-1, groups.size() > 1 ? false : printTreatmentDesc);
            res.add(s == null || s.length() == 0 ? "N/A" : s);
        }
        return MiscUtils.flatten(res);
    }

    private static String getMetadata(Collection<Biosample> animals, String metadata) {
        Set<String> res = new HashSet<>();
        for (Biosample a : animals) {
            BiotypeMetadata bm = a.getBiotype().getMetadata(metadata);
            String m = bm == null || a.getMetadataValue(bm) == null ? "N/A"
                    : a.getMetadataValue(bm).replaceAll("/", " ");
            res.add(m);
        }
        return MiscUtils.flatten(res);
    }

    private static void drawCageSeparation(Document doc, PdfContentByte canvas) {
        canvas.setLineWidth(1f);
        canvas.setColorStroke(Color.BLACK);
        canvas.moveTo(0, doc.getPageSize().getHeight() / 2);
        canvas.lineTo(doc.getPageSize().getWidth(), doc.getPageSize().getHeight() / 2);
        canvas.moveTo(doc.getPageSize().getWidth() / 4, 0);
        canvas.lineTo(doc.getPageSize().getWidth() / 4, doc.getPageSize().getHeight());
        canvas.moveTo(2 * doc.getPageSize().getWidth() / 4, doc.getPageSize().getBottom());
        canvas.lineTo(2 * doc.getPageSize().getWidth() / 4, doc.getPageSize().getHeight());
        canvas.moveTo(3 * doc.getPageSize().getWidth() / 4, 0);
        canvas.lineTo(3 * doc.getPageSize().getWidth() / 4, doc.getPageSize().getHeight());
        canvas.stroke();
    }
}