package net.techreadiness.plugin.action.reports; import java.awt.Color; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.List; import java.util.Map; import net.sf.jasperreports.engine.JRBand; import net.sf.jasperreports.engine.JRCommonText; import net.sf.jasperreports.engine.JRElement; import net.sf.jasperreports.engine.JRSection; import net.sf.jasperreports.engine.JasperExportManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.base.JRBaseTextField; import net.sf.jasperreports.engine.data.JRMapCollectionDataSource; import org.apache.commons.beanutils.BeanUtils; import ar.com.fdvs.dj.core.DynamicJasperHelper; import ar.com.fdvs.dj.core.layout.ClassicLayoutManager; import ar.com.fdvs.dj.domain.DynamicReport; import ar.com.fdvs.dj.domain.Style; import ar.com.fdvs.dj.domain.builders.ColumnBuilder; import ar.com.fdvs.dj.domain.builders.FastReportBuilder; import ar.com.fdvs.dj.domain.builders.StyleBuilder; import ar.com.fdvs.dj.domain.constants.Border; import ar.com.fdvs.dj.domain.constants.Font; import ar.com.fdvs.dj.domain.constants.HorizontalAlign; import ar.com.fdvs.dj.domain.constants.VerticalAlign; import ar.com.fdvs.dj.domain.entities.columns.AbstractColumn; import ar.com.fdvs.dj.domain.entities.conditionalStyle.ConditionalStyle; import com.google.common.collect.Lists; import com.google.common.collect.Maps; public class ReportExportPdf implements ReportExport { protected final Style detailStyle; protected final Style detailOddStyle; protected final Style headerStyle; protected List<String> columnLabels; protected List<String> columnKeys; protected List<Boolean> useConditionalStyles; protected Collection<Map<String, String>> data; protected Map<String, String> params; protected String template; protected List<ConditionalStyle> conditionalStyles; protected boolean suppressConditionalStyles; protected String legendTitle; public static class Builder { private final Map<String, String> params = Maps.newHashMap(); private final List<String> columnLabels; private final List<String> columnKeys; private List<Boolean> useConditionalStyles; private final Collection<Map<String, String>> data; public Builder(List<String> columnLabels, List<String> columnKeys, Collection<Map<String, String>> data) { this.columnLabels = columnLabels; this.columnKeys = columnKeys; this.data = data; } public Builder(List<String> columnLabels, List<String> columnKeys, List<Boolean> useConditionalStyles, Collection<Map<String, String>> data) { this.columnLabels = columnLabels; this.columnKeys = columnKeys; this.useConditionalStyles = useConditionalStyles; this.data = data; } public Builder title(String value) { params.put("title", value); return this; } public Builder subtitle(String value) { params.put("subtitle", value); return this; } public Builder consortium(String value) { params.put("consortium", value); return this; } public Builder aggregationMessage(String value) { params.put("aggregationMessage", value); return this; } public ReportExportPdf build() { return new ReportExportPdf(this); } } private ReportExportPdf(Builder builder) { columnKeys = builder.columnKeys; columnLabels = builder.columnLabels; useConditionalStyles = builder.useConditionalStyles; data = builder.data; params = builder.params; headerStyle = new StyleBuilder(false, "headerStyle").setBackgroundColor(new Color(238, 239, 239)) .setPaddingBottom(4).setFont(new Font(8, "SansSerif", true)).setTextColor(new Color(88, 88, 90)) .setVerticalAlign(VerticalAlign.TOP).setHorizontalAlign(HorizontalAlign.LEFT) .setBorderBottom(Border.PEN_2_POINT).setBorderColor(new Color(222, 223, 224)).setTransparent(false).build(); detailStyle = new StyleBuilder(false, "detailStyle").setBackgroundColor(Color.WHITE) .setFont(new Font(8, "SansSerif", false)).setVerticalAlign(VerticalAlign.MIDDLE) .setHorizontalAlign(HorizontalAlign.LEFT).setPaddingLeft(2).setBorder(Border.NO_BORDER).build(); detailOddStyle = new StyleBuilder(false, "detailOddStyle").setBackgroundColor(new Color(247, 248, 248)).build(); } public void setMapUrl(String value) { params.put("mapUrl", value); } public void setDCMapUrl(String value) { params.put("dcMapUrl", value); } public void setTemplate(String value) { template = value; } public List<ConditionalStyle> getConditionalStyles() { return conditionalStyles; } public void setConditionalStyles(List<ConditionalStyle> conditionalStyles) { this.conditionalStyles = conditionalStyles; } public Style getDetailStyle() { return detailStyle; } public void setSuppressConditionalStyles(boolean suppressConditionalStyles) { this.suppressConditionalStyles = suppressConditionalStyles; } public void setLegendTitle(String legendTitle) { params.put("legendTitle", legendTitle); } @Override public byte[] getReport() throws Exception { if (data == null || columnKeys == null) { throw new Exception("No data to report."); } // build report DynamicReport report = buildReport(); // build reporting data source // fill report JasperReport jasperReport = DynamicJasperHelper.generateJasperReport(report, new ClassicLayoutManager(), params); adjustTextMarkup(jasperReport); if (data == null || data.isEmpty()) { data = Lists.newArrayList(); if (columnKeys.size() > 0) { Map<String, String> noData = Maps.newHashMap(); noData.put(columnKeys.get(0), "No Results"); data.add(noData); } } JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JRMapCollectionDataSource(data)); return JasperExportManager.exportReportToPdf(jasperPrint); } public void adjustTextMarkup(JasperReport jr) { JRSection detailSection = jr.getDetailSection(); for (JRBand band : detailSection.getBands()) { if (band.getElements().length > 0) { JRBaseTextField text = (JRBaseTextField) band.getElements()[0]; text.setBold(true); for (JRElement element : band.getElements()) { JRBaseTextField column = (JRBaseTextField) element; column.setMarkup(JRCommonText.MARKUP_HTML); } } } } private DynamicReport buildReport() throws Exception { FastReportBuilder report = new FastReportBuilder(); report.setPrintBackgroundOnOddRows(true).setOddRowBackgroundStyle(detailOddStyle) .setDefaultStyles(new Style(), new Style(), headerStyle, detailStyle).setUseFullPageWidth(true) .setDetailHeight(48).setHeaderHeight(20); if (useConditionalStyles == null || useConditionalStyles.isEmpty()) { for (int i = 0; i < columnKeys.size() - 1; i++) { report.addColumn(columnLabels.get(i), columnKeys.get(i), String.class.getName(), 50); } AbstractColumn columnAmount; if (!suppressConditionalStyles) { columnAmount = ColumnBuilder .getNew() .setColumnProperty(columnKeys.get(columnKeys.size() - 1), String.class.getName()) .setTitle(columnLabels.get(columnLabels.size() - 1)) .setWidth(50) .addConditionalStyles( conditionalStyles != null ? conditionalStyles : createConditionalStyles(detailStyle)) .build(); } else { columnAmount = ColumnBuilder.getNew() .setColumnProperty(columnKeys.get(columnKeys.size() - 1), String.class.getName()) .setTitle(columnLabels.get(columnLabels.size() - 1)).setWidth(50).build(); } report.addColumn(columnAmount); } else { // this for loop is used if you use the "useConditionalStyles" list // normally, the last column is the only one to use conditional styles // but the progress report needed multiple for (int i = 0; i < columnKeys.size(); i++) { if (useConditionalStyles.get(i)) { AbstractColumn columnAmount = ColumnBuilder .getNew() .setColumnProperty(columnKeys.get(i), String.class.getName()) .setTitle(columnLabels.get(i)) .setWidth(50) .addConditionalStyles( conditionalStyles != null ? conditionalStyles : createConditionalStyles(detailStyle)) .build(); report.addColumn(columnAmount); } else { report.addColumn(columnLabels.get(i), columnKeys.get(i), String.class.getName(), 50); } } } if (template != null) { report.setTemplateFile(template); } else if (params.get("mapUrl") != null) { report.setTemplateFile("reports/wrapper-map.jrxml"); } else { report.setTemplateFile("reports/wrapper.jrxml"); } return report.build(); } private static List<ConditionalStyle> createConditionalStyles(Style baseStyle) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { Style reportLevel1 = (Style) BeanUtils.cloneBean(baseStyle); reportLevel1.setBackgroundColor(new Color(184, 31, 75)); reportLevel1.setTextColor(Color.white); reportLevel1.setTransparent(false); Style reportLevel2 = (Style) BeanUtils.cloneBean(baseStyle); reportLevel2.setBackgroundColor(new Color(246, 133, 31)); reportLevel2.setTransparent(false); Style reportLevel3 = (Style) BeanUtils.cloneBean(baseStyle); reportLevel3.setBackgroundColor(new Color(252, 185, 19)); reportLevel3.setTransparent(false); Style reportLevel4 = (Style) BeanUtils.cloneBean(baseStyle); reportLevel4.setBackgroundColor(new Color(0, 161, 94)); reportLevel4.setTransparent(false); ReportPdfHighlightCondition status1 = new ReportPdfHighlightCondition(0, .25); ReportPdfHighlightCondition status2 = new ReportPdfHighlightCondition(.26, .5); ReportPdfHighlightCondition status3 = new ReportPdfHighlightCondition(.51, .75); ReportPdfHighlightCondition status4 = new ReportPdfHighlightCondition(.76, 1); ReportPdfBooleanCondition statusYes = new ReportPdfBooleanCondition("Yes"); ReportPdfBooleanCondition statusNo = new ReportPdfBooleanCondition("No"); List<ConditionalStyle> conditionalStyles = Lists.newArrayList(); conditionalStyles.add(new ConditionalStyle(status1, reportLevel1)); conditionalStyles.add(new ConditionalStyle(status2, reportLevel2)); conditionalStyles.add(new ConditionalStyle(status3, reportLevel3)); conditionalStyles.add(new ConditionalStyle(status4, reportLevel4)); conditionalStyles.add(new ConditionalStyle(statusYes, reportLevel4)); conditionalStyles.add(new ConditionalStyle(statusNo, reportLevel1)); return conditionalStyles; } }