package cz.cvut.fel.restauracefel.library.service; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Collection; import java.util.Map; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRField; import net.sf.jasperreports.engine.JRParameter; import net.sf.jasperreports.engine.JasperExportManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperPrintManager; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; import net.sf.jasperreports.engine.data.JRTableModelDataSource; import net.sf.jasperreports.engine.util.JRLoader; /** * Class for printig from list and table model to printer, PDF and CSV * * @author Lukas Kotrba <lukas.kotrba@hotmail.com> */ public class Printer { /** * Constructor */ private Printer() { } /** * Save given Collection data into PDF * * @param params Print parameters * @param data Collection with data * @param pressKit File with Jasper press kit (*.jasper) * @param destinationPath Destination file path * @throws net.sf.jasperreports.engine.JRException */ public static void printFromListToPDF(Map<String, Object> params, Collection data, File pressKit, String destinationPath) throws JRException { JasperReport jr = (JasperReport) JRLoader.loadObject(pressKit); params = localizeParameters(params, jr); JasperPrint jp = JasperFillManager.fillReport(jr, params, new JRBeanCollectionDataSource(data)); JasperExportManager.exportReportToPdfFile(jp, destinationPath); } /** * Prints given Collection data out on printer * * @param params Print parameters * @param data Collection data to be printed * @param pressKit File with Jasper press kit (*.jasper) * @throws net.sf.jasperreports.engine.JRException */ public static void printFromListToPrinter(Map<String, Object> params, Collection data, File pressKit) throws JRException { JasperReport jr = (JasperReport) JRLoader.loadObject(pressKit); params = localizeParameters(params, jr); JasperPrint jp = JasperFillManager.fillReport(jr, params, new JRBeanCollectionDataSource(data)); JasperPrintManager.printReport(jp, true); } /** * Save given TableModel data into specified file * * @param data Data to be printed * @param destinationFileName Destination file path */ public static void printFromTableToCSV(TableModel data, String path) { String output = ""; for (int i = 0; i < data.getColumnCount(); i++) { output += prepareForCSV(data.getColumnName(i)) + ";"; } output += "\n"; for (int i = 0; i < data.getRowCount(); i++) { for (int j = 0; j < data.getColumnCount(); j++) { output += prepareForCSV(data.getValueAt(i, j).toString()) + ";"; } output += "\n"; } try { File file = new File(path); if (!file.exists()) { file.createNewFile(); } FileWriter fWriter = new FileWriter(file); fWriter.write(output); fWriter.close(); } catch (IOException ex) { Logger.getLogger(Printer.class.getName()).log(Level.SEVERE, null, ex); } } /** * Save given TableModel data into PDF file * * @param params Print parameters * @param data Data to be printed * @param pressKit File with Jasper press kit (*.jasper) * @param destinationPath Destination file path * @throws net.sf.jasperreports.engine.JRException */ public static void printFromTableToPDF(Map<String, Object> params, TableModel data, File pressKit, String destinationPath) throws JRException { JasperReport jr = (JasperReport) JRLoader.loadObject(pressKit); data = replaceHeadersByFieldsKey(data, jr); params = localizeParameters(params, jr); JasperPrint jp = JasperFillManager.fillReport(jr, params, new JRTableModelDataSource(data)); JasperExportManager.exportReportToPdfFile(jp, destinationPath); } /** * Prints given data out on printer * * @param params Print parameters * @param data Data to be printed * @param pressKit File with Jasper press kit (*.jasper) * @throws net.sf.jasperreports.engine.JRException */ public static void printFromTableToPrinter(Map<String, Object> params, TableModel data, File pressKit) throws JRException { JasperReport jr = (JasperReport) JRLoader.loadObject(pressKit); data = replaceHeadersByFieldsKey(data, jr); params = localizeParameters(params, jr); JasperPrint jp = JasperFillManager.fillReport(jr, params, new JRTableModelDataSource(data)); JasperPrintManager.printReport(jp, true); } /** * Gets parameters from JasperReport press kit and return their localised version * * @param initialParams Into this Map parameters will be added * @param jReport JasperReports with requested parameters to localize * @return Map with localized parameters */ private static Map<String, Object> localizeParameters(Map<String, Object> initialParams, JasperReport jReport) { JRParameter[] jrPars = jReport.getParameters(); String name; ResourceBundle rb = LocalizationManager.getInstance().getResourceBundle("cz.cvut.fel.restauracefel.localization.restaurace_fel_bundle"); for (JRParameter param : jrPars) { name = param.getName(); // JReports has built-in parameters, which are all in capitals and these parameters should not be localised. // For us, user defined parameters are named with camel casing convetion - that's the reason why I check only the first letter for capitals if (Character.isUpperCase(name.charAt(0)) || initialParams.containsKey(name)) { continue; } initialParams.put(name, rb.getString(name)); } return initialParams; } /** * Prepares given text for including to CSV, by adding necessary escape sequences * * @param text Text for prepare * @return CSV safe text */ private static String prepareForCSV(String text) { if (text.indexOf('"') != -1) { text = text.replaceAll("\"", "\"\""); text = "\"" + text + "\""; } else if (text.indexOf(';') != -1 || text.startsWith(" ") || text.endsWith(" ")) { text = "\"" + text + "\""; } return text; } /** * Replaces appropriate headers by fields key * * @param table Table * @param jReport JasperReports with fields * @return TableModel with headers replaced by appropriate fields key */ private static TableModel replaceHeadersByFieldsKey(TableModel table, JasperReport jReport) { //<editor-fold defaultstate="collapsed" desc="Get headers from table"> String[] headers = new String[table.getColumnCount()]; for (int i = 0; i < table.getColumnCount(); i++) { headers[i] = table.getColumnName(i); //System.out.println(headers[i]); } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Get data from table"> Object[][] data = new Object[(int) table.getRowCount()][(int) table.getColumnCount()]; for (int row = 0; row < table.getRowCount(); row++) { for (int col = 0; col < table.getColumnCount(); col++) { data[row][col] = table.getValueAt(row, col); } } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Find and replace headers by key"> ResourceBundle rb = LocalizationManager.getInstance().getResourceBundle("cz.cvut.fel.restauracefel.localization.restaurace_fel_bundle"); JRField[] fields = jReport.getFields(); String loc; for (JRField field : fields) { loc = rb.getString(field.getName()); for (int i = 0; i < headers.length; i++) { if (headers[i].equals(loc)) { headers[i] = field.getName(); break; } } } //</editor-fold> return new DefaultTableModel(data, headers); } }