Java tutorial
/* * Copyright (C) 2013 Nafundi * * 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 com.nafundi.taskforce.codebook.logic; import com.googlecode.jatl.Html; import com.lowagie.text.DocumentException; import com.lowagie.text.pdf.BaseFont; import org.w3c.dom.Document; import org.w3c.tidy.Tidy; import org.xhtmlrenderer.pdf.ITextRenderer; import javax.swing.*; import java.io.*; import java.util.ArrayList; /** * Used to generate a Codebook in PDF * * @author Yaw Anokwa (yanokwa@nafundi.com) */ public class CodebookMaker extends SwingWorker<Integer, String> { private final ArrayList<CodebookEntry> codebookEntries; private final String locale; private final String inputFilename; private final String outputFolderPath; public CodebookMaker(ArrayList<CodebookEntry> codebookEntries, String locale, String inputFilename, String outputFolderPath) { this.codebookEntries = codebookEntries; this.locale = locale; this.inputFilename = inputFilename; this.outputFolderPath = outputFolderPath; } String getLocale() { return locale; } public Integer doInBackground() throws Exception { String errorMsg = ""; // string writer StringWriter writer = new StringWriter(); new Html(writer) { { body(); h4().text(inputFilename + " (" + locale + ")").end(); table().classAttr("table table-bordered table-condensed"); thead().tr(); th().h6().text("Variable Name").end().end(); th().h6().text("Question Text").end().end(); th().h6().text("Saved Value").end().end(); end().end(); tbody(); for (int i = 0; i < codebookEntries.size(); i++) { if (i % 2 == 0) { // fix for no background color in export to pdf tr().classAttr("gray"); } else { tr(); } CodebookEntry entry = codebookEntries.get(i); td().text(entry.getVariable()).end(); String question = entry.getQuestion(); String value = entry.getValue(); // select question if (question.contains("|")) { td().text(question.replace("|", "")).end(); td(); table().classAttr("table table-bordered table-condensed"); String values[] = value.split("\n"); for (int j = 0; j < values.length; j++) { tr(); //value td().text(values[j].split("\t")[1]).end(); //label td().text(values[j].split("\t")[0]).end(); end(); } end(); end(); } else { td().text(question).end(); td().text(value).end(); } end(); } done(); } }; // build html string // bootstrap css with only headings, body type, and tables // add custom tr.gray tag to fix bug in html to pdf export // change font family to be Arial Unicode and to include embedding String htmlHeader = "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/>\n" + "<style type=\"text/css\">.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:\"\";line-height:0;}.clearfix:after{clear:both;}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}body{margin:0;font-family:\"Arial Unicode MS\",\"Arial Unicode\", Arial, sans-serif;-fs-pdf-font-embed:embed;-fs-pdf-font-encoding: Identity-H;font-size:11px;line-height:20px;color:#333333;background-color:#ffffff;}a{color:#0088cc;text-decoration:none;}a:hover,a:focus{color:#005580;text-decoration:underline;}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px;}p{margin:0 0 10px;}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px;}small{font-size:85%;}strong{font-weight:bold;}em{font-style:italic;}cite{font-style:normal;}.muted{color:#999999;}a.muted:hover,a.muted:focus{color:#808080;}.text-warning{color:#c09853;}a.text-warning:hover,a.text-warning:focus{color:#a47e3c;}.text-publishError{color:#b94a48;}a.text-publishError:hover,a.text-publishError:focus{color:#953b39;}.text-info{color:#3a87ad;}a.text-info:hover,a.text-info:focus{color:#2d6987;}.text-success{color:#468847;}a.text-success:hover,a.text-success:focus{color:#356635;}.text-left{text-align:left;}.text-right{text-align:right;}.text-center{text-align:center;}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999999;}h1,h2,h3{line-height:40px;}h1{font-size:38.5px;}h2{font-size:31.5px;}h3{font-size:24.5px;}h4{font-size:17.5px;}h5{font-size:14px;}h6{font-size:11.9px;}h1 small{font-size:24.5px;}h2 small{font-size:17.5px;}h3 small{font-size:14px;}h4 small{font-size:14px;}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eeeeee;}ul,ol{padding:0;margin:0 0 10px 25px;}ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}li{line-height:20px;}ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}ul.inline,ol.inline{margin-left:0;list-style:none;}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;*zoom:1;padding-left:5px;padding-right:5px;}dl{margin-bottom:20px;}dt,dd{line-height:20px;}dt{font-weight:bold;}dd{margin-left:10px;}.dl-horizontal{*zoom:1;}.dl-horizontal:before,.dl-horizontal:after{display:table;content:\"\";line-height:0;}.dl-horizontal:after{clear:both;}.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.dl-horizontal dd{margin-left:180px;}hr{margin:20px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999;}abbr.initialism{font-size:90%;text-transform:uppercase;}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25;}blockquote small{display:block;line-height:20px;color:#999999;}blockquote small:before{content:'\\2014 \\00A0';}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;}blockquote.pull-right small:before{content:'';}blockquote.pull-right small:after{content:'\\00A0 \\2014';}q:before,q:after,blockquote:before,blockquote:after{content:\"\";}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px;}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}.table{width:100%;margin-bottom:20px;}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #dddddd;}.table th{font-weight:bold;}.table thead th{vertical-align:bottom;}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0;}.table tbody+tbody{border-top:2px solid #dddddd;}.table .table{background-color:#ffffff;}.table-condensed th,.table-condensed td{padding:4px 5px;}.table-bordered{border:1px solid #dddddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th,.table-bordered td{border-left:1px solid #dddddd;}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9;}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5;}table td[class*=\"span\"],table th[class*=\"span\"],.row-fluid table td[class*=\"span\"],.row-fluid table th[class*=\"span\"]{display:table-cell;float:none;margin-left:0;}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0;}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0;}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0;}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0;}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0;}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0;}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0;}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0;}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0;}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0;}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0;}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0;}.table tbody tr.success>td{background-color:#dff0d8;}.table tbody tr.publishError>td{background-color:#f2dede;}.table tbody tr.warning>td{background-color:#fcf8e3;}.table tbody tr.info>td{background-color:#d9edf7;}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6;}.table-hover tbody tr.publishError:hover>td{background-color:#ebcccc;}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc;}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3;}.table tbody tr.gray>td{background-color:#f9f9f9;}.hidden {visibility:hidden;}\t</style>\n" + "</head>"; String htmlFooter = "\n</html>"; String htmlDocument = htmlHeader + writer.getBuffer().toString() + htmlFooter; // make sure html entities aren't mangled in document building process Tidy tidy = new Tidy(); tidy.setQuiet(true); tidy.setXmlTags(false); tidy.setShowWarnings(false); tidy.setInputEncoding("UTF-8"); tidy.setOutputEncoding("UTF-8"); tidy.setXHTML(true); Document document = tidy.parseDOM(new ByteArrayInputStream(htmlDocument.getBytes("UTF-8")), null); // create render of document // ITextRender is not thread-safe synchronized (this) { ITextRenderer renderer = new ITextRenderer(); if (isWindows()) { renderer.getFontResolver().addFont("C:\\WINDOWS\\Fonts\\ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); } else if (isMac()) { //renderer.getFontResolver().addFont("/Library/Fonts/Arial Unicode.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/Library/Fonts/NotoNaskhArabic-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/Library/Fonts/NotoSans-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/Library/Fonts/NotoSans-Bold.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/Library/Fonts/NotoSansBengali-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/Library/Fonts/NotoSansBengali-Bold.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); } else if (isUnix()) { renderer.getFontResolver().addFont("/usr/share/fonts/truetype/fontawesome-webfont.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/usr/share/fonts/truetype/NotoNaskhArabic-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/usr/share/fonts/truetype/NotoSans-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/usr/share/fonts/truetype/NotoSans-Bold.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/usr/share/fonts/truetype/NotoSansBengali-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); renderer.getFontResolver().addFont("/usr/share/fonts/truetype/NotoSansBengali-Bold.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); } else { publish("Warning: No Arial Unicode found. Non-Latin characters may not display properly."); } renderer.setDocument(document, null); renderer.layout(); // write out document as pdf OutputStream outputStream = null; try { outputStream = new FileOutputStream( outputFolderPath + File.separator + inputFilename + " (" + locale + ").pdf"); } catch (FileNotFoundException e) { errorMsg = e.getMessage(); e.printStackTrace(); } try { renderer.createPDF(outputStream); } catch (DocumentException e) { errorMsg = e.getMessage(); e.printStackTrace(); } try { if (outputStream != null) { outputStream.close(); } } catch (IOException e) { errorMsg = e.getMessage(); e.printStackTrace(); } } if (!"".equals(errorMsg)) { publishError(errorMsg); return -1; } publish("Finished making " + getLocale() + " codebook"); return 0; } private void publishError(String errorMessage) { publish("Error: Failed to make " + getLocale() + " codebook because " + errorMessage + "."); } private String getOS() { return System.getProperty("os.name").toLowerCase(); } public boolean isWindows() { return (getOS().indexOf("win") >= 0); } public boolean isMac() { return (getOS().indexOf("mac") >= 0); } public boolean isUnix() { return (getOS().indexOf("nix") >= 0 || getOS().indexOf("nux") >= 0 || getOS().indexOf("aix") > 0); } }