Java tutorial
/******************************************************************************* * This file is part of ISPyB. * * ISPyB is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ISPyB 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with ISPyB. If not, see <http://www.gnu.org/licenses/>. * * Contributors : S. Delageniere, R. Leal, L. Launer, K. Levik, S. Veyrier, P. Brenchereau, M. Bodin, A. De Maria Antolinos ******************************************************************************/ package ispyb.common.util.export; import java.awt.Color; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.log4j.Logger; import com.lowagie.text.BadElementException; import com.lowagie.text.Cell; import com.lowagie.text.Chunk; import com.lowagie.text.Document; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.HeaderFooter; import com.lowagie.text.Image; import com.lowagie.text.PageSize; import com.lowagie.text.Paragraph; import com.lowagie.text.Phrase; import com.lowagie.text.Table; import com.lowagie.text.pdf.PdfWriter; import com.lowagie.text.rtf.RtfWriter2; import ispyb.common.util.Constants; import ispyb.common.util.Formatter; import ispyb.common.util.PathUtils; import ispyb.server.common.services.sessions.Session3Service; import ispyb.server.common.util.ejb.Ejb3ServiceLocator; import ispyb.server.mx.services.collections.DataCollection3Service; import ispyb.server.mx.services.collections.Image3Service; import ispyb.server.mx.vos.collections.Session3VO; /** * allows creation of PDF or RTF report - general report for EXI, available in the * * @author Solange Delageniere * */ public class ExiPdfRtfExporter { private final static Logger LOG = Logger.getLogger(ExiPdfRtfExporter.class); // constants color public final static Color GREEN_COLOR = new Color(17, 197, 3); public final static Color RED_COLOR = new Color(202, 58, 2); public final static Color WHITE_COLOR = new Color(255, 255, 255); public final static Color BLUE_COLOR = new Color(160, 200, 237); public final static Color LIGHT_GREY_COLOR = new Color(192, 192, 192); public final static Color LIGHT_BLUE_COLOR = new Color(126, 182, 235); public final static Color SUBWEDGE_COLOR = new Color(238, 248, 252); public final static Color WEDGE_COLOR = new Color(171, 222, 245); public final static Color LIGHT_YELLOW_COLOR = new Color(245, 246, 206); public final static Color GREEN_COLOR_RANK = new Color(0, 139, 139); public final static Color NULL_COLOR_RANK = new Color(104, 136, 168); // constant fonts public final static Font FONT_HELVETICA_10 = new Font(Font.HELVETICA, 10, Font.BOLD); public final static Font VERY_SMALL_FONT = new Font(Font.HELVETICA, 2); public final static Font FONT_SPACE = new Font(Font.HELVETICA, 6); public final static Font FONT_TITLE = new Font(Font.HELVETICA, 8, Font.BOLD | Font.UNDERLINE); public final static Font FONT_TITLE_11 = new Font(Font.HELVETICA, 11, Font.BOLD | Font.UNDERLINE); public final static Font FONT_DOC = new Font(Font.HELVETICA, 8, Font.NORMAL, Color.BLACK); public final static Font FONT_DOC_BLUE = new Font(Font.HELVETICA, 8, Font.NORMAL, Color.BLUE); public final static Font FONT_DOC_ITALIC = new Font(Font.HELVETICA, 8, Font.ITALIC, Color.BLACK); public final static Font FONT_DOC_11 = new Font(Font.HELVETICA, 11, Font.NORMAL, Color.BLACK); public final static Font FONT_DOC_11_ITALIC = new Font(Font.HELVETICA, 11, Font.ITALIC, Color.BLACK); public final static Font FONT_DOC_EXPONENT = new Font(Font.HELVETICA, 11, Font.NORMAL, Color.BLACK); public final static Font FONT_DOC_EXPONENT_BLUE = new Font(Font.HELVETICA, 11, Font.NORMAL, Color.BLUE); public final static Font FONT_DOC_BOLD = new Font(Font.HELVETICA, 8, Font.BOLD); public final static Font FONT_DOC_PARAM_TITLE = new Font(Font.HELVETICA, 8, Font.NORMAL, LIGHT_GREY_COLOR); public final static Font FONT_INDEXING_NOTDONE = new Font(Font.HELVETICA, 8, Font.NORMAL, LIGHT_GREY_COLOR); public final static Font FONT_INDEXING_FAILED = new Font(Font.HELVETICA, 8, Font.NORMAL, RED_COLOR); public final static Font FONT_INDEXING_SUCCESS = new Font(Font.HELVETICA, 8, Font.NORMAL, GREEN_COLOR); public final static int NB_COL_DATACOLLECTION = 8; public final static int SIZE_FONT = 8; public final static int SMALL_FONT = 6; public final static int TEXT_RISE_EXP = 2; public final static int TEXT_RISE_SUB = -2; public final static int NB_DATA_COLLECTION_PER_PAGE = 2; public final static float INDENTATION_LEFT = 10f; public final static float GREY_FILL_DATA = 0.99f; public final static float GREY_FILL_DATA_COLLECT = 0.8f; public final static float GREY_FILL_HEADER = 0.6f; // images size public final static float CRYSTAL_IMAGE_WIDTH = 281; public final static float CRYSTAL_IMAGE_HEIGHT = 174; public final static float IMAGE_HEIGHT = 120; // public final static float CRYSTAL_IMAGE_WIDTH = 160; // public final static float CRYSTAL_IMAGE_HEIGHT = 99; public final static float DIFF_IMAGE_WIDTH = 174; public final static float DIFF_IMAGE_HEIGHT = 174; // proposal String proposalDesc; // session info Integer sessionId; // nb row to export Integer nbRowsMax; private Session3VO slv; // dataCollectionViewObject List List<Map<String, Object>> dataCollections = new ArrayList<Map<String, Object>>(); DecimalFormat df2; DecimalFormat df3; private final Ejb3ServiceLocator ejb3ServiceLocator = Ejb3ServiceLocator.getInstance(); private Session3Service sessionService; private DataCollection3Service dcService; private Image3Service imageService; public ExiPdfRtfExporter(String proposalDesc, Integer sessionId, List<Map<String, Object>> dataCollections, Integer nbRowsMax) throws Exception { this.proposalDesc = proposalDesc; this.sessionId = sessionId; this.dataCollections = dataCollections; this.nbRowsMax = nbRowsMax; init(); } private void init() throws Exception { df2 = (DecimalFormat) NumberFormat.getInstance(Locale.US); df2.applyPattern("#####0.00"); df3 = (DecimalFormat) NumberFormat.getInstance(Locale.US); df3.applyPattern("#####0.000"); sessionService = (Session3Service) ejb3ServiceLocator.getLocalService(Session3Service.class); dcService = (DataCollection3Service) ejb3ServiceLocator.getLocalService(DataCollection3Service.class); imageService = (Image3Service) ejb3ServiceLocator.getLocalService(Image3Service.class); slv = sessionService.findByPk(sessionId, false/*withDataCollectionGroup*/, false/*withEnergyScan*/, false/*withXFESpectrum*/); } /** * export datacollection report * * @param rtfFormat * @return * @throws Exception */ public ByteArrayOutputStream exportDataCollectionReport(boolean rtfFormat) throws Exception { this.init(); // create simple doc and write to a ByteArrayOutputStream Document document = new Document(PageSize.A4.rotate(), 20, 20, 20, 20); ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (!rtfFormat) { PdfWriter.getInstance(document, baos); } else { RtfWriter2.getInstance(document, baos); } // ============================= // Header + footer // ============================= setHeader(document); setFooter(document); document.open(); // =============================== // Body // =============================== // Crystallographer added only for IFX proposal in case of MXPress // experiment setCrystallographer(document); // Session comments setSessionComments(document); // session title& info setSessionTable(document); // ====================== // Data Collection table // ====================== document.add(new Paragraph(" ")); setDataCollectionTable(document); // ====================== // End of file // ====================== document.close(); return baos; } /** * sets the header in the specified document * * @param document * @throws Exception */ private void setHeader(Document document) throws Exception { HeaderFooter header; String h = "Data Collections for Proposal: " + proposalDesc; if (slv != null) { h += " on Beamline: " + (slv.getBeamlineName() == null ? "" : slv.getBeamlineName()) + " --- Session start date: " + (slv.getStartDate() == null ? "" : Formatter.formatDate(slv.getStartDate())); } header = new HeaderFooter(new Phrase(h, FONT_HELVETICA_10), false); header.setAlignment(Element.ALIGN_CENTER); header.setBorderWidth(1); header.getBefore().getFont().setSize(SIZE_FONT); document.setHeader(header); } /** * set footer in the specified document * * @param document * @throws Exception */ private void setFooter(Document document) throws Exception { HeaderFooter footer = new HeaderFooter(new Phrase("Page n."), true); footer.setAlignment(Element.ALIGN_RIGHT); footer.setBorderWidth(1); footer.getBefore().getFont().setSize(SMALL_FONT); document.setFooter(footer); } /** * set the crystallographer - only for IFX proposal * * @param document * @throws Exception */ private void setCrystallographer(Document document) throws Exception { // Crystallographer added only for IFX proposal in case of MXPress // experiment if (proposalDesc.toLowerCase().contains(Constants.PROPOSAL_CODE_FX) && slv != null) { String beamlineOp = ""; if (slv.getBeamlineOperator() != null) { beamlineOp = slv.getBeamlineOperator(); } document.add(new Paragraph("Crystallographer:", FONT_TITLE)); document.add(new Paragraph(beamlineOp, FONT_DOC)); } } /** * set sessions comments * * @param document * @throws Exception */ private void setSessionComments(Document document) throws Exception { if (slv != null) { document.add(new Paragraph(Constants.SESSION_VISIT_CAP + " comments:", FONT_TITLE)); document.add(new Paragraph(slv.getComments(), FONT_DOC)); } } /*** * sets the sessions informations in the pdf document for fx or ix accounts * (Issue 1049) * * @param document * @throws Exception */ private void setSessionTable(Document document) throws Exception { String proposalCode = proposalDesc.substring(0, 2); if (slv != null && (proposalCode.toLowerCase().equals(Constants.PROPOSAL_CODE_FX) || proposalCode.equals(Constants.PROPOSAL_CODE_IX))) { if (proposalCode.toLowerCase().equals(Constants.PROPOSAL_CODE_FX)) { // session // title // only // for // FX // accounts document.add(new Paragraph("Session title:", FONT_TITLE)); document.add(new Paragraph(slv.getSessionTitle(), FONT_DOC)); } Table sessionTable = new Table(2); // sessionTable.setWidth(50); // percentage sessionTable.setPadding(3); sessionTable.setCellsFitPage(true); sessionTable.getDefaultCell().setBorderWidth(0); sessionTable.setBorder(0); sessionTable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT); boolean hasData = false; // print only if the value > 0 if (proposalCode.toLowerCase().equals(Constants.PROPOSAL_CODE_FX)) { // structure // determinations // only // for // FX // accounts if (slv.getStructureDeterminations() != null && !slv.getStructureDeterminations().isNaN() && slv.getStructureDeterminations() != 0) { hasData = true; sessionTable.addCell(new Paragraph("Structure determinations", FONT_DOC_BOLD)); sessionTable.addCell(new Paragraph("" + slv.getStructureDeterminations(), FONT_DOC)); } } if (slv.getDewarTransport() != null && !slv.getDewarTransport().isNaN() && slv.getDewarTransport() != 0) { hasData = true; sessionTable.addCell(new Paragraph("Dewar transport", FONT_DOC_BOLD)); sessionTable.addCell(new Paragraph("" + slv.getDewarTransport(), FONT_DOC)); } if (slv.getDatabackupFrance() != null && !slv.getDatabackupFrance().isNaN() && slv.getDatabackupFrance() != 0) { hasData = true; sessionTable.addCell(new Paragraph("Data backup & Express delivery France", FONT_DOC_BOLD)); sessionTable.addCell(new Paragraph("" + slv.getDatabackupFrance(), FONT_DOC)); } if (slv.getDatabackupEurope() != null && !slv.getDatabackupEurope().isNaN() && slv.getDatabackupEurope() != 0) { hasData = true; sessionTable.addCell(new Paragraph("Data backup & Express delivery Europe", FONT_DOC_BOLD)); sessionTable.addCell(new Paragraph("" + slv.getDatabackupEurope(), FONT_DOC)); } if (hasData) { document.add(sessionTable); } } } /** * set the dataCollection table * * @param document * @throws Exception */ private void setDataCollectionTable(Document document) throws Exception { document.add(new Paragraph("Data Collections:", FONT_TITLE)); document.add(new Paragraph(" ")); if (dataCollections.isEmpty()) { document.add(new Paragraph("There is no data collection in this report", FONT_DOC)); } else { document.add(new Paragraph(" ")); // DataCollection Rows Iterator<Map<String, Object>> it = dataCollections.iterator(); int i = 0; while (it.hasNext() && i < nbRowsMax) { Map<String, Object> dataCollectionMapData = it.next(); LOG.info("dcMap=" + dataCollectionMapData.toString()); setDataCollectionMapData(document, dataCollectionMapData); i++; } document.add(new Paragraph(" ")); } } /** * set a line for a specified dataCollection in the dataCollection table * * @param document * @param table * @param col * @param session * @param df2 * @param df3 * @throws Exception */ private void setDataCollectionMapData(Document document, Map<String, Object> dataCollectionMapItem) throws Exception { // 1st row String parag = getCellParam(dataCollectionMapItem, "DataCollectionGroup_experimentType") + " " + getCellParam(dataCollectionMapItem, "DataCollection_startTime"); Paragraph p = new Paragraph(parag, FONT_DOC_BLUE); document.add(p); //row2 parag = getCellParam(dataCollectionMapItem, "DataCollection_imageDirectory"); document.add(new Paragraph(parag, FONT_DOC_ITALIC)); //row3 Table table = new Table(NB_COL_DATACOLLECTION); table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT); table.getDefaultCell().setBorderWidth(0); // 1st Cell parag = "Workflow: \n" + "Protein: \n" + "Sample: \n" + "Prefix: \n" + "Run #: \n" + "Images: \n" + "Transmission: \n"; LOG.info("parag=" + parag); p = new Paragraph(parag, FONT_DOC); table.addCell(p); // Cell2 parag = getCellParam(dataCollectionMapItem, "Workflow_workflowType") + "\n" + getCellParam(dataCollectionMapItem, "Protein_acronym") + "\n" + getCellParam(dataCollectionMapItem, "BLSample_name") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_imagePrefix") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_dataCollectionNumber") + "\n" + getCellParam(dataCollectionMapItem, "Protein_acronym") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_transmission") + "\n"; LOG.info("parag=" + parag); p = new Paragraph(parag, FONT_DOC_BOLD); table.addCell(p); // 3 Cell parag = "Resolution (corner): \n" + "Wavelength: \n" + "Omega range: \n" + "Omega start: \n" + "Exposure time: \n" + "Flux start: \n" + "Flux end: \n"; table.addCell(new Paragraph(parag, FONT_DOC)); // Cell 4 parag = getCellParam(dataCollectionMapItem, "DataCollection_resolutionAtCorner") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_wavelength") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_axisRange") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_omegaStart") + "\n" + getCellParam(dataCollectionMapItem, "exposureTime") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_flux") + "\n" + getCellParam(dataCollectionMapItem, "DataCollection_flux_end") + "\n"; table.addCell(new Paragraph(parag, FONT_DOC_BOLD)); // 5 Cell add cell containing autoproc results table.addCell(" "); // 6 Cell : thumbnail if (!getCellParam(dataCollectionMapItem, "lastImageId").isEmpty()) { String thumbnailPath = (imageService .findByPk(new Integer(getCellParam(dataCollectionMapItem, "lastImageId")))) .getJpegThumbnailFileFullPath(); Cell cellThumbnail = getCellImage(thumbnailPath); cellThumbnail.setBorderWidth(0); table.addCell(cellThumbnail); } else { table.addCell(" "); } //cellThumbnail.setRowspan(nbRows); // 7 Cell : snapshot Cell cellSnapshot = getCellImage(dataCollectionMapItem, "DataCollection_xtalSnapshotFullPath1"); //cellSnapshot.setRowspan(nbRows); cellSnapshot.setBorderWidth(0); table.addCell(cellSnapshot); // 8 Cell : graph or other plot if (!getCellParam(dataCollectionMapItem, "DataCollection_dataCollectionId").isEmpty()) { String plotPath = (dcService.findByPk( new Integer(getCellParam(dataCollectionMapItem, "DataCollection_dataCollectionId")), false, false)).getImageQualityIndicatorsPlotPath(); Cell cellGraph = getCellImage(plotPath); cellGraph.setBorderWidth(0); table.addCell(cellGraph); } else { table.addCell(" "); } document.add(table); // row3 if (dataCollectionMapItem.get("DataCollection_comments") != null && dataCollectionMapItem.get("DataCollection_comments") != "") document.add(new Paragraph(dataCollectionMapItem.get("DataCollection_comments").toString(), FONT_DOC)); else document.add(new Paragraph(" ")); return; } /** * get the value or replace by blank if null to fill a cell paragraph * * @param param * @param dataCollectionMap * @throws Exception */ private String getCellParam(Map<String, Object> dataCollectionMap, String param) throws Exception { String paramValue = ""; if (dataCollectionMap.get(param) != null) { paramValue = dataCollectionMap.get(param).toString(); } return paramValue; } /** * returns a simple cell witha given value inside * * @param value * @return */ private Cell getCellValue(String value) { Cell cell = new Cell(); cell.setHorizontalAlignment(Element.ALIGN_LEFT); cell.add(new Paragraph(value, FONT_DOC_BOLD)); cell.setColspan(1); return cell; } /** * returns a cell with a given image inside * * @param image * @return * @throws Exception */ private Cell getCellImage(Map<String, Object> dataCollectionMapItem, String imageParam) throws Exception { if (dataCollectionMapItem.get(imageParam) != null && !(dataCollectionMapItem.get(imageParam).toString()).equals("")) { String image = dataCollectionMapItem.get(imageParam).toString(); image = PathUtils.getPath(image); try { Image jpg1 = Image.getInstance(image); jpg1.scaleAbsolute(jpg1.getWidth() * IMAGE_HEIGHT / jpg1.getHeight(), IMAGE_HEIGHT); Cell cell = new Cell(jpg1); cell.setLeading(0); cell.setBorderWidth(0); cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setVerticalAlignment(Element.ALIGN_CENTER); return cell; } catch (IOException e) { return new Cell(new Paragraph(image + " not found", FONT_DOC)); } } return new Cell(new Paragraph("", FONT_DOC)); } /** * returns a cell with a given image inside * * @param image * @return * @throws Exception */ private Cell getCellImage(String imagePath) throws Exception { if (imagePath != null) { String image = PathUtils.getPath(imagePath); try { Image jpg1 = Image.getInstance(image); jpg1.scaleAbsolute(jpg1.getWidth() * IMAGE_HEIGHT / jpg1.getHeight(), IMAGE_HEIGHT); Cell cell = new Cell(jpg1); cell.setLeading(0); cell.setBorderWidth(0); cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setVerticalAlignment(Element.ALIGN_CENTER); return cell; } catch (IOException e) { return new Cell(new Paragraph(image + " not found", FONT_DOC)); } } return new Cell(new Paragraph("", FONT_DOC)); } private Chunk getChunkImage(String image) throws BadElementException, MalformedURLException, IOException { Image jpg = Image.getInstance(image); jpg.scaleAbsolute(jpg.getWidth() * 10 / jpg.getHeight(), 10); return new Chunk(jpg, 0, 0); } private Cell getEmptyCell(int colspan) throws Exception { Cell emptyCell = new Cell(new Paragraph("", FONT_DOC)); emptyCell.setColspan(colspan); return emptyCell; } }