/** * @author ishaikh * */ package com.transformuk.bdt.view; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import org.springframework.web.servlet.view.AbstractView; import com.itextpdf.text.Anchor; import com.itextpdf.text.BaseColor; import com.itextpdf.text.Chunk; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Element; import com.itextpdf.text.Font; import com.itextpdf.text.Font.FontFamily; import com.itextpdf.text.PageSize; import com.itextpdf.text.Paragraph; import com.itextpdf.text.Phrase; import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.ColumnText; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; import com.itextpdf.text.pdf.PdfPageEventHelper; import com.itextpdf.text.pdf.PdfWriter; import com.itextpdf.tool.xml.Pipeline; import com.itextpdf.tool.xml.XMLWorker; import com.itextpdf.tool.xml.XMLWorkerHelper; import com.itextpdf.tool.xml.html.Tags; import com.itextpdf.tool.xml.parser.XMLParser; import com.itextpdf.tool.xml.pipeline.css.CSSResolver; import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline; import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline; import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline; import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext; import com.transformuk.bdt.domain.Bfsf; import com.transformuk.bdt.model.OtherSources; import com.transformuk.bdt.model.ReportModel; import com.transformuk.bdt.tld.Utils; @Component public class PdfReportView extends AbstractView { private static final int THREE = 3; private static final Logger logger = Logger.getLogger(PdfReportView.class); /** The fonts */ public static final Font[] FONT = new Font[7]; static { FONT[0] = new Font(FontFamily.HELVETICA, 24); FONT[1] = new Font(FontFamily.HELVETICA, 18, Font.BOLD); FONT[2] = new Font(FontFamily.HELVETICA, 12, Font.BOLD); FONT[3] = new Font(FontFamily.HELVETICA, 12); FONT[4] = new Font(FontFamily.HELVETICA, 12, Font.UNDERLINE, new BaseColor(0, 0, 255)); FONT[5] = new Font(FontFamily.HELVETICA, 14, Font.BOLD); FONT[6] = new Font(FontFamily.HELVETICA, 10); } public PdfReportView() { setContentType("application/pdf"); } @Override protected boolean generatesDownloadContent() { return true; } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest req, HttpServletResponse res) throws Exception { String ROOT_PATH = System.getProperty("catalina.home"); // get data model which is passed by the Spring container ReportModel reportModel = (ReportModel) model.get("reportModel"); // IE workaround: write into byte array first. ByteArrayOutputStream baos = createTemporaryOutputStream(); // step 1 Document document = new Document(PageSize.A4, 30, 30, 30, 40); // step 2 PdfWriter writer = newWriter(document, baos);//PdfWriter.getInstance(document, new FileOutputStream(ROOT_PATH + File.separator +"pdf.pdf")); writer.setBoxSize("art", new Rectangle(36, 54, 559, 788)); writer.setPageEvent(new HeaderFooter()); writer.setViewerPreferences(getViewerPreferences()); // step 3 document.open(); document.add(new Chunk("")); // step 4 try { HtmlPipelineContext htmlContext = new HtmlPipelineContext(null); htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); CSSResolver cssResolver = XMLWorkerHelper.getInstance() .getDefaultCssResolver(true); Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer))); XMLWorker worker = new XMLWorker(pipeline, true); XMLParser p = new XMLParser(worker); p.parse(new InputStreamReader(new FileInputStream(ROOT_PATH + File.separator + "bis.html"), "UTF-8")); //add mysupport addIntroAndMySupport(document); //add support and other information addSupportAndOtherInformation(document, reportModel); //add other useful sources addOtherUsefulSources(document); //add user data addUserData(document, reportModel); //add footer addFooterSection(document); }catch(Exception e) { logger.error("Exception creating pdf: "+e.getMessage()); } //step 5 document.close(); // Flush to HTTP response. writeToResponse(res, baos); } private int getViewerPreferences() { return PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage; } private PdfWriter newWriter(Document document, OutputStream os) throws DocumentException { return PdfWriter.getInstance(document, os); } public static void addIntroAndMySupport(Document document) throws DocumentException { //add line feed document.add(new Paragraph(" ")); Paragraph paragraph = new Paragraph("The national and local links below have been chosen as the " + "most relevant sources of help and support for your business needs.", FONT[3]); document.add(paragraph); //add line feed document.add(new Paragraph(" ")); paragraph = new Paragraph("My support", FONT[1]); document.add(paragraph); paragraph = new Paragraph("Links to support sources are listed in the areas you have indicated are important to you. " + "Some are related to your stated needs, and others are based on possible needs we have interpreted from your answers.", FONT[2]); document.add(paragraph); } public static void addSupportAndOtherInformation(Document document, ReportModel reportModel) throws DocumentException { Map<String, List<Bfsf>> bfsfSearchResultMap = reportModel.getSearchResult(); Map<String, List<OtherSources>> otherSourcesMap = reportModel.getOtherSources(); if (bfsfSearchResultMap != null || otherSourcesMap != null) { for (Entry<String, List<Bfsf>> entry : bfsfSearchResultMap.entrySet()) { //add line feed document.add(new Paragraph(" ")); Paragraph paragraph = new Paragraph(entry.getKey(), FONT[1]); document.add(paragraph); //add line feed document.add(new Paragraph(" ")); paragraph = new Paragraph("Support", FONT[5]); document.add(paragraph); for (Bfsf bfsf : entry.getValue()) { Phrase p = new Phrase(); Anchor anchor = new Anchor(bfsf.getTitle() + " » ", FONT[4]); anchor.setReference(bfsf.getWeb_url()); p.add(anchor); p.add(new Chunk(bfsf.getShort_description(), FONT[3])); document.add(p); //add line feed document.add(new Paragraph(" ")); } if (otherSourcesMap != null) { List<OtherSources> otherSourcesList = otherSourcesMap.get(entry.getKey()); paragraph = new Paragraph("Other information", FONT[5]); document.add(paragraph); int recordCount = 0; for (OtherSources otherSources : otherSourcesList) { //only show first three records if (recordCount < THREE) { Phrase p = new Phrase(); Anchor anchor = new Anchor(Utils.stripHtml(otherSources.getTitle()) + " » ", FONT[4]); anchor.setReference(otherSources.getUrl()); p.add(anchor); String description = ""; if (StringUtils.isNotBlank(otherSources.getDescription())) { description = Utils.stripHtml(otherSources.getDescription()); } else { String content = StringUtils.substringAfter(otherSources.getContent(), "<LABEL>Search</LABEL> <A>Home</A> <A>Business and self-employed</A>"); description = Utils.abbreviate(Utils.stripHtml(content), 143); } p.add(new Chunk(description, FONT[3])); document.add(p); //add line feed document.add(new Paragraph(" ")); recordCount++; } } } } } } public static void addUserData(Document document, ReportModel reportModel) throws DocumentException { //add line feed document.add(new Paragraph(" ")); Paragraph paragraph = new Paragraph("My business", FONT[1]); document.add(paragraph); //add line feed document.add(new Paragraph(" ")); // a table with three columns PdfPTable table = new PdfPTable(2); table.setHorizontalAlignment(Element.ALIGN_LEFT); table.setWidthPercentage(50); table.setSpacingBefore(5); // we add a cell with colspan 2 PdfPCell cell = new PdfPCell(new Phrase("Information provided", FONT[2])); cell.setColspan(2); //cell.setBackgroundColor(BaseColor.LIGHT_GRAY); //cell.setGrayFill(0.9f); cell.setHorizontalAlignment(Element.ALIGN_RIGHT); cell.setPadding(5); table.addCell(cell); if (StringUtils.isNotBlank(reportModel.getBusinessAge())) { table.addCell("Business age"); table.addCell(new PdfPCell(new Phrase(reportModel.getBusinessAge(), FONT[6]))); } if (StringUtils.isNotBlank(reportModel.getLegalStructure())) { table.addCell("Legal structure"); table.addCell(new PdfPCell(new Phrase(reportModel.getLegalStructure(), FONT[6]))); } if (StringUtils.isNotBlank(reportModel.getPostCode())) { table.addCell("Location"); table.addCell(new PdfPCell(new Phrase(reportModel.getPostCode(), FONT[6]))); } if (StringUtils.isNotBlank(reportModel.getWorkforce())) { table.addCell("Workforce"); table.addCell(new PdfPCell(new Phrase(reportModel.getWorkforce(), FONT[6]))); } if (StringUtils.isNotBlank(reportModel.getSector())) { table.addCell("Sector"); table.addCell(new PdfPCell(new Phrase(reportModel.getSector(), FONT[6]))); } document.add(table); } private void addOtherUsefulSources(Document document) throws DocumentException { //add line feed //document.add(new Paragraph(" ")); Paragraph paragraph = new Paragraph("Other useful sources:", FONT[1]); document.add(paragraph); Phrase p = new Phrase(); p.add(new Chunk("For support, Advice and inspiration for growing your business, visit ", FONT[3])); Anchor anchor = new Anchor("GREATBusiness »", FONT[4]); anchor.setReference("http://www.greatbusiness.gov.uk"); p.add(anchor); document.add(p); //add line feed document.add(new Paragraph(" ")); document.add(new Paragraph("You may also find these schemes and organisations useful:", FONT[3])); //add line feed document.add(new Paragraph(" ")); paragraph = new Paragraph(); anchor = new Anchor("Growth Vouchers »", FONT[4]); anchor.setReference("https://marketplace.enterprisenation.com/about"); paragraph.add(anchor); document.add(paragraph); document.add(new Paragraph("Accessing strategic business advice. Find out how Growth Vouchers can help your business to grow.", FONT[3])); //add line feed document.add(new Paragraph(" ")); paragraph = new Paragraph(); anchor = new Anchor("British Business Bank »", FONT[4]); anchor.setReference("http://british-business-bank.co.uk/"); paragraph.add(anchor); document.add(paragraph); p = new Phrase(); p.add(new Chunk("Unlocking finance. Find out how the British Business Bank is making financial markets work for smaller businesses; or see their guide to finance sources and tools - ", FONT[3])); anchor = new Anchor("The Business Finance Guide »", FONT[4]); anchor.setReference("http://www.icaew.com/~/media/Files/Technical/Corporate-finance/Guidelines/the-business-finance-guide.pdf"); p.add(anchor); document.add(p); //add line feed document.add(new Paragraph(" ")); paragraph = new Paragraph(); anchor = new Anchor("Innovate UK »", FONT[4]); anchor.setReference("http://www.innovateuk.org/"); paragraph.add(anchor); document.add(paragraph); document.add(new Paragraph("If you're looking to develop new products and services and bring them closer to market, Innovate UK provides a range of funding programmes and support.", FONT[3])); //add line feed document.add(new Paragraph(" ")); paragraph = new Paragraph(); anchor = new Anchor("Apprenticeships »", FONT[4]); anchor.setReference("http://www.greatbusiness.gov.uk/apprenticeships/"); paragraph.add(anchor); document.add(paragraph); document.add(new Paragraph("Apprenticeships are great for employers - apprentices improve productivity and help give businesses a competitive edge.", FONT[3])); //add line feed document.add(new Paragraph(" ")); paragraph = new Paragraph(); anchor = new Anchor("Contracts Finder »", FONT[4]); anchor.setReference("https://www.gov.uk/contracts-finder"); paragraph.add(anchor); document.add(paragraph); document.add(new Paragraph("Contracts Finder lets you search for information about contracts worth over £10,000 with the government and its agencies.", FONT[3])); } private void addFooterSection(Document document) throws DocumentException { //add line feed document.add(new Paragraph(" ")); Paragraph paragraph = new Paragraph("Want to speak to someone?", FONT[1]); document.add(paragraph); document.add(new Phrase("You can call the national Business Support Helpline on 0300 456 3565 (Monday to Friday, 9am – 6pm).", FONT[3])); //add line feed document.add(new Paragraph(" ")); Phrase p = new Phrase(); p.add(new Chunk("You can also talk to a local business adviser at ", FONT[3])); Anchor anchor = new Anchor("Greater London Authority", FONT[4]); anchor.setReference("https://www.london.gov.uk/priorities/business-economy/for-business/business-support"); p.add(anchor); p.add(new Chunk(" on 0300 456 3565.", FONT[3])); document.add(p); //add line feed document.add(new Paragraph(" ")); Paragraph para = new Paragraph(); anchor = new Anchor("Find out about call charges »", FONT[4]); anchor.setReference("https://www.gov.uk/call-charges"); para.add(anchor); document.add(para); } /** Inner class to add a header and a footer. */ class HeaderFooter extends PdfPageEventHelper { /** Current page number (will be reset for every chapter). */ int pagenumber; /** * Increase the page number. * @see com.itextpdf.text.pdf.PdfPageEventHelper#onStartPage( * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document) */ public void onStartPage(PdfWriter writer, Document document) { pagenumber++; } /** * Adds the header and the footer. * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage( * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document) */ public void onEndPage(PdfWriter writer, Document document) { Rectangle rect = writer.getBoxSize("art"); ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, new Phrase(String.format("page %d", pagenumber)), (rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0); } } }