package enterpriseapp.ui.reports;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.List;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRRtfExporter;
import net.sf.jasperreports.engine.export.JRXhtmlExporter;
import net.sf.jasperreports.engine.export.JRXmlExporter;
import net.sf.jasperreports.engine.export.oasis.JROdsExporter;
import net.sf.jasperreports.engine.export.oasis.JROdtExporter;
import net.sf.jasperreports.engine.export.ooxml.JRDocxExporter;
import net.sf.jasperreports.engine.export.ooxml.JRPptxExporter;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.j2ee.servlets.ImageServlet;
import org.vaadin.hene.popupbutton.PopupButton;
import ar.com.fdvs.dj.core.DynamicJasperHelper;
import ar.com.fdvs.dj.core.layout.ClassicLayoutManager;
import ar.com.fdvs.dj.domain.Style;
import ar.com.fdvs.dj.domain.builders.ColumnBuilder;
import ar.com.fdvs.dj.domain.builders.ColumnBuilderException;
import ar.com.fdvs.dj.domain.builders.DynamicReportBuilder;
import ar.com.fdvs.dj.domain.builders.FastReportBuilder;
import ar.com.fdvs.dj.domain.builders.GroupBuilder;
import ar.com.fdvs.dj.domain.builders.StyleBuilder;
import ar.com.fdvs.dj.domain.constants.Font;
import ar.com.fdvs.dj.domain.constants.GroupLayout;
import ar.com.fdvs.dj.domain.constants.HorizontalAlign;
import ar.com.fdvs.dj.domain.constants.Page;
import ar.com.fdvs.dj.domain.entities.columns.AbstractColumn;
import ar.com.fdvs.dj.domain.entities.columns.PropertyColumn;
import ar.com.fdvs.dj.domain.entities.conditionalStyle.ConditionalStyle;
import com.vaadin.server.StreamResource;
import com.vaadin.server.UserError;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Accordion;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.BaseTheme;
import enterpriseapp.EnterpriseApplication;
import enterpriseapp.Utils;
import enterpriseapp.ui.Constants;
/**
* @author Alejandro Duarte
*
*/
public abstract class AbstractReport extends CustomComponent implements ClickListener {
private static final long serialVersionUID = 1L;
protected HorizontalSplitPanel layout;
protected VerticalLayout leftLayout = new VerticalLayout();
protected HorizontalLayout displayLayout;
protected Button refreshButton;
protected PopupButton columnsButton;
protected PopupButton groupingButton;
protected PopupButton exportButton;
protected Button pdfButton;
protected Button excelButton;
protected Button wordButton;
protected Button powerPointButton;
protected Button odsButton;
protected Button odtButton;
protected Button rtfButton;
protected Button htmlButton;
protected Button csvButton;
protected Button xmlButton;
protected Accordion accordion;
protected CheckBox printBackgroundOnOddRowsCheckBox;
protected CheckBox printColumnNamesCheckBox;
protected CheckBox stretchWithOverflowCheckBox;
protected TextField columnsPerPageTextField;
protected TextField pageWidthTextField;
protected TextField pageHeightTextField;
protected TextField marginTopTextField;
protected TextField marginBottomTextField;
protected TextField marginLeftTextField;
protected TextField marginRightTextField;
protected CheckBox[] columnsCheckBoxes;
protected CheckBox[] groupingCheckBoxes;
protected VerticalLayout observationsLayout;
protected Label observationsLabel;
protected boolean showObservations = false;
public AbstractReport() { }
@Override
public void attach() {
super.attach();
initLayout();
build();
}
public abstract void updateReport() throws UnsupportedEncodingException;
/**
* @return property names that correspond to the objects returned by getData(). Each instance returned by
* getData() must have a getter for each property returned by this method.
*/
public abstract String[] getColumnProperties();
/**
* @return property classes that correspond to the objects returned by getData() according to getColumnProperties().
*/
public abstract Class<?>[] getColumnClasses();
/**
* @return titles to use on the table.
*/
public abstract String[] getColumnTitles();
/**
* Collection of rows to show on the table. Each object in the collection must define a getter for each String returned
* in getColumnProperties().
*/
public abstract Collection<?> getData();
/**
* @return A custom component to add to the accordion component. You can use it to add custom filtering or configuration
* to the report. Return null if no component is needed.
*/
public abstract Component getParametersComponent();
public Integer[] getColumnWidths() { return null; };
public String getFileName() { return "report"; };
public void configureColumn(String property, AbstractColumn column, DynamicReportBuilder reportBuilder) {};
public void configureColumnBuilder(String property, ColumnBuilder columnBuilder, DynamicReportBuilder reportBuilder) {};
public boolean getDefalutColumnCheckBox(String property) { return true; };
public String getColumnPattern(String property) { return null; };
public Style getColumnStyle(String property) { return null; };
public List<ConditionalStyle> getColumnConditionalStyle(String property) { return null; };
public static int mmToPoints(float f) {
return Math.round(f / 25.4f * 72); // 1in = 25.4mm = 72pt
}
public DynamicReportBuilder getReportBuilder() {
FastReportBuilder reportBuilder = new FastReportBuilder();
reportBuilder.setWhenNoData(Constants.uiEmptyReport, null);
reportBuilder.setPrintBackgroundOnOddRows((Boolean) printBackgroundOnOddRowsCheckBox.getValue());
reportBuilder.setPrintColumnNames((Boolean) printColumnNamesCheckBox.getValue());
reportBuilder.setUseFullPageWidth(true);
try {
Integer top = mmToPoints(new Float(marginTopTextField.getValue().toString()));
Integer bottom = mmToPoints(new Float(marginBottomTextField.getValue().toString()));
Integer left = mmToPoints(new Float(marginLeftTextField.getValue().toString()));
Integer right = mmToPoints(new Float(marginRightTextField.getValue().toString()));
Page page = new Page();
page.setWidth(mmToPoints(new Float(pageWidthTextField.getValue().toString())));
page.setHeight(mmToPoints(new Float(pageHeightTextField.getValue().toString())));
if(page.getHeight() < 140 + top + bottom || page.getWidth() < left + right || page.getHeight() < 1 || page.getWidth() < 1 || top < 0 || bottom < 0 || left < 0 || right < 0) {
throw new NumberFormatException();
}
reportBuilder.setPageSizeAndOrientation(page);
reportBuilder.setColumnsPerPage(new Integer(columnsPerPageTextField.getValue().toString()));
reportBuilder.setMargins(top, bottom, left, right);
} catch(NumberFormatException e) {
refreshButton.setComponentError(new UserError(Constants.uiReportConfigurationError));
}
return reportBuilder;
}
public void buildColumns(DynamicReportBuilder reportBuilder) {
try {
String[] title = getColumnTitles();
String[] property = getColumnProperties();
Class<?>[] clazz = getColumnClasses();
Integer[] width = getColumnWidths();
for(int i = 0; i < property.length; i++) {
if(columnsCheckBoxes[i].booleanValue()) {
ColumnBuilder columnBuilder = ColumnBuilder.getNew();
columnBuilder.setColumnProperty(property[i], clazz[i]);
columnBuilder.setTitle(title[i]);
if(width != null && width[i] != null) {
columnBuilder.setWidth(width[i]);
}
String columnPattern = getColumnPattern(property[i]);
if(columnPattern != null) {
columnBuilder.setPattern(columnPattern);
}
Style columnStyle = null;
if(groupingCheckBoxes[i].booleanValue()) {
columnStyle = new StyleBuilder(true).setHorizontalAlign(HorizontalAlign.LEFT).setFont(Font.ARIAL_MEDIUM_BOLD).setPaddingBottom(mmToPoints(5)).setPaddingTop(mmToPoints(10)).build();
} else {
columnStyle = getColumnStyle(property[i]);
}
if(columnStyle == null) {
columnStyle = new StyleBuilder(true).setStretchWithOverflow(stretchWithOverflowCheckBox.booleanValue()).build();
columnBuilder.setTruncateSuffix("...");
}
columnBuilder.setStyle(columnStyle);
List<ConditionalStyle> conditionalStyle = getColumnConditionalStyle(property[i]);
if(conditionalStyle != null) {
columnBuilder.addConditionalStyles(conditionalStyle);
}
configureColumnBuilder(property[i], columnBuilder, reportBuilder);
AbstractColumn column = columnBuilder.build();
reportBuilder.addColumn(column);
configureColumn(property[i], column, reportBuilder);
if(groupingCheckBoxes[i].booleanValue()) {
GroupBuilder groupBuilder = new GroupBuilder();
groupBuilder.setCriteriaColumn((PropertyColumn) column);
groupBuilder.setGroupLayout(GroupLayout.VALUE_IN_HEADER);
reportBuilder.addGroup(groupBuilder.build());
}
}
}
} catch (ColumnBuilderException e) {
throw new RuntimeException(e);
}
}
public String getLastVisiblePropertyName() {
String[] columnProperties = getColumnProperties();
for(int i = columnProperties.length - 1; i >= 0; i--) {
if(columnsCheckBoxes[i].booleanValue()) {
return columnProperties[i];
}
}
return null;
}
protected JRHtmlExporter getHtmlExporter() {
JRHtmlExporter exporter = new JRHtmlExporter();
String random = "" + Math.random() * 1000.0;
random = random.replace('.', '0').replace(',', '0');
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, Utils.getWebContextPath(EnterpriseApplication.getInstance()) + "/image?r=" + random + "&image=");
return exporter;
}
protected void build() {
try {
refreshButton.setComponentError(null);
setObservations("");
leftLayout.setMargin(true);
layout.setFirstComponent(leftLayout);
updateReport();
if(!getObservations().isEmpty()) {
refreshButton.setComponentError(new UserError(Constants.uiSeeObservationsOnTheReport));
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
protected ByteArrayOutputStream getOutputStream(JRExporter exporter) {
ByteArrayOutputStream outputStream = null;
try {
DynamicReportBuilder reportBuilder = getReportBuilder();
buildColumns(reportBuilder);
Collection<?> data = getData();
JasperPrint jasperPrint = DynamicJasperHelper.generateJasperPrint(reportBuilder.build(), new ClassicLayoutManager(), data);
outputStream = new ByteArrayOutputStream();
VaadinSession.getCurrent().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
exporter.exportReport();
outputStream.flush();
outputStream.close();
} catch (JRException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return outputStream;
}
public void initLayout() {
refreshButton = new Button(Constants.uiRefresh);
pdfButton = new Button(Constants.uiPdf);
excelButton = new Button(Constants.uiExcel);
wordButton = new Button(Constants.uiWord);
powerPointButton = new Button(Constants.uiPowerPoint);
odsButton = new Button(Constants.uiOds);
odtButton = new Button(Constants.uiOdt);
rtfButton = new Button(Constants.uiRtf);
htmlButton = new Button(Constants.uiHtml);
csvButton = new Button(Constants.uiCsv);
xmlButton = new Button(Constants.uiXml);
pdfButton.setStyleName(BaseTheme.BUTTON_LINK);
excelButton.setStyleName(BaseTheme.BUTTON_LINK);
wordButton.setStyleName(BaseTheme.BUTTON_LINK);
powerPointButton.setStyleName(BaseTheme.BUTTON_LINK);
odsButton.setStyleName(BaseTheme.BUTTON_LINK);
odtButton.setStyleName(BaseTheme.BUTTON_LINK);
rtfButton.setStyleName(BaseTheme.BUTTON_LINK);
htmlButton.setStyleName(BaseTheme.BUTTON_LINK);
csvButton.setStyleName(BaseTheme.BUTTON_LINK);
xmlButton.setStyleName(BaseTheme.BUTTON_LINK);
refreshButton.addListener(this);
pdfButton.addListener(this);
excelButton.addListener(this);
wordButton.addListener(this);
powerPointButton.addListener(this);
odsButton.addListener(this);
odtButton.addListener(this);
rtfButton.addListener(this);
htmlButton.addListener(this);
csvButton.addListener(this);
xmlButton.addListener(this);
VerticalLayout exportOptionsLayout = new VerticalLayout();
exportOptionsLayout.setSizeUndefined();
exportOptionsLayout.setSpacing(true);
exportOptionsLayout.addComponent(pdfButton);
exportOptionsLayout.addComponent(excelButton);
exportOptionsLayout.addComponent(wordButton);
exportOptionsLayout.addComponent(powerPointButton);
exportOptionsLayout.addComponent(odsButton);
exportOptionsLayout.addComponent(odtButton);
exportOptionsLayout.addComponent(rtfButton);
exportOptionsLayout.addComponent(htmlButton);
exportOptionsLayout.addComponent(csvButton);
exportOptionsLayout.addComponent(xmlButton);
exportButton = new PopupButton(Constants.uiPdf);
exportButton.setComponent(exportOptionsLayout);
exportButton.addClickListener(this);
String[] columnTitles = getColumnTitles();
columnsCheckBoxes = new CheckBox[columnTitles.length];
groupingCheckBoxes = new CheckBox[columnTitles.length];
VerticalLayout columnsLayout = new VerticalLayout();
columnsLayout.setSizeUndefined();
columnsLayout.setSpacing(true);
VerticalLayout groupingLayout = new VerticalLayout();
groupingLayout.setSizeUndefined();
groupingLayout.setSpacing(true);
for(int i = 0; i < columnTitles.length; i++) {
CheckBox columnCheckBox = new CheckBox(columnTitles[i], true);
columnCheckBox.setValue(getDefalutColumnCheckBox(getColumnProperties()[i]));
columnsLayout.addComponent(columnCheckBox);
columnsCheckBoxes[i] = columnCheckBox;
CheckBox groupingCheckBox = new CheckBox(columnTitles[i], false);
groupingLayout.addComponent(groupingCheckBox);
groupingCheckBoxes[i] = groupingCheckBox;
}
columnsButton = new PopupButton(Constants.uiColumns);
columnsButton.setComponent(columnsLayout);
groupingButton = new PopupButton(Constants.uiGrouping);
groupingButton.setComponent(groupingLayout);
displayLayout = new HorizontalLayout();
displayLayout.setSpacing(true);
displayLayout.addComponent(refreshButton);
displayLayout.addComponent(columnsButton);
displayLayout.addComponent(groupingButton);
displayLayout.addComponent(exportButton);
Panel exportPanel = new Panel();
exportPanel.setContent(displayLayout);
printBackgroundOnOddRowsCheckBox = new CheckBox(Constants.uiPrintBackgroundOnOddRows, true);
printColumnNamesCheckBox = new CheckBox(Constants.uiPrintColumnNames);
stretchWithOverflowCheckBox = new CheckBox(Constants.uiStretchWithOverflow);
printColumnNamesCheckBox.setValue(true);
columnsPerPageTextField = new TextField(Constants.uiColumnsPerPage);
columnsPerPageTextField.setValue("1");
pageWidthTextField = new TextField(Constants.uiPageWidth);
pageWidthTextField.setValue(Constants.reportPageWidth);
pageHeightTextField = new TextField(Constants.uiPageHeight);
pageHeightTextField.setValue(Constants.reportPageHeight);
marginTopTextField = new TextField(Constants.uiMarginTop);
marginTopTextField.setValue(Constants.reportMarginTop);
marginTopTextField.setWidth("115px");
marginBottomTextField = new TextField(Constants.uiMarginBottom);
marginBottomTextField.setValue(Constants.reportMarginBottom);
marginBottomTextField.setWidth("115px");
marginLeftTextField = new TextField(Constants.uiMarginLeft);
marginLeftTextField.setValue(Constants.reportMarginLeft);
marginLeftTextField.setWidth("115px");
marginRightTextField = new TextField(Constants.uiMarginRight);
marginRightTextField.setValue(Constants.reportMarginRight);
marginRightTextField.setWidth("115px");
Button reverseButton = new Button(Constants.uiReverse);
reverseButton.addListener(new Button.ClickListener() {
private static final long serialVersionUID = 1L;
@Override
public void buttonClick(ClickEvent event) {
Object height = pageHeightTextField.getValue();
pageHeightTextField.setValue(pageWidthTextField.getValue());
pageWidthTextField.setValue("" + height);
}
});
HorizontalLayout pageLayout = new HorizontalLayout();
pageLayout.setSpacing(true);
pageLayout.addComponent(pageWidthTextField);
pageLayout.addComponent(pageHeightTextField);
pageLayout.addComponent(reverseButton);
pageLayout.setComponentAlignment(reverseButton, Alignment.BOTTOM_LEFT);
GridLayout marginLayout = new GridLayout(3, 3);
marginLayout.addComponent(marginTopTextField, 1, 0);
marginLayout.addComponent(marginBottomTextField, 1, 2);
marginLayout.addComponent(marginLeftTextField, 0, 1);
marginLayout.addComponent(marginRightTextField, 2, 1);
Panel marginPanel = new Panel();
marginPanel.setSizeUndefined();
marginPanel.setContent(marginLayout);
VerticalLayout reportConfigurationLayout = new VerticalLayout();
reportConfigurationLayout.setWidth("100%");
reportConfigurationLayout.setMargin(true);
reportConfigurationLayout.setSpacing(true);
reportConfigurationLayout.addComponent(printBackgroundOnOddRowsCheckBox);
reportConfigurationLayout.addComponent(printColumnNamesCheckBox);
reportConfigurationLayout.addComponent(stretchWithOverflowCheckBox);
reportConfigurationLayout.addComponent(new Label());
reportConfigurationLayout.addComponent(columnsPerPageTextField);
reportConfigurationLayout.addComponent(new Label());
reportConfigurationLayout.addComponent(pageLayout);
reportConfigurationLayout.addComponent(new Label());
reportConfigurationLayout.addComponent(marginPanel);
Component parametersComponent = getParametersComponent();
VerticalLayout parametersLayout = new VerticalLayout();
parametersLayout.setMargin(true);
if(parametersComponent != null) {
parametersLayout.addComponent(parametersComponent);
}
observationsLabel = new Label("", Label.CONTENT_XHTML);
if(showObservations) {
observationsLayout = new VerticalLayout();
observationsLayout.setMargin(true);
observationsLayout.addComponent(observationsLabel);
}
accordion = new Accordion();
accordion.setSizeFull();
accordion.addTab(parametersLayout, Constants.uiParameters, null);
accordion.addTab(reportConfigurationLayout, Constants.uiConfiguration, null);
accordion.addTab(observationsLayout, Constants.uiObservations, null);
VerticalLayout rightLayout = new VerticalLayout();
rightLayout.setSizeFull();
rightLayout.setMargin(true);
rightLayout.addComponent(exportPanel);
rightLayout.addComponent(accordion);
rightLayout.setExpandRatio(accordion, 1);
layout = new HorizontalSplitPanel();
layout.setSplitPosition(65);
layout.setSizeFull();
layout.setSecondComponent(rightLayout);
setCompositionRoot(layout);
}
public void addObservation(String text) {
String currentText = observationsLabel.getValue().toString();
if(currentText.isEmpty()) {
setObservations("- " + text);
} else {
setObservations(currentText + "<br/><br/>- " + text);
}
}
public void setObservations(String text) {
observationsLabel.setValue(text);
}
public String getObservations() {
return (String) observationsLabel.getValue();
}
@Override
public void buttonClick(ClickEvent event) {
if(event.getButton().equals(refreshButton)) {
build();
} else if(event.getButton().equals(pdfButton)) {
exportToPdf();
} else if(event.getButton().equals(excelButton)) {
exportToExcel();
} else if(event.getButton().equals(wordButton)) {
exportToWord();
} else if(event.getButton().equals(powerPointButton)) {
exportToPowerPoint();
} else if(event.getButton().equals(odsButton)) {
exportToOds();
} else if(event.getButton().equals(odtButton)) {
exportToOdt();
} else if(event.getButton().equals(rtfButton)) {
exportToRtf();
} else if(event.getButton().equals(htmlButton)) {
exportToHtml();
} else if(event.getButton().equals(csvButton)) {
exportToCsv();
} else if(event.getButton().equals(xmlButton)) {
exportToXml();
}
}
public void exportToPdf() {
download(getFileName() + ".pdf", new JRPdfExporter());
}
public void exportToExcel() {
download(getFileName() + ".xlsx", new JRXlsxExporter());
}
public void exportToWord() {
download(getFileName() + ".docx", new JRDocxExporter());
}
public void exportToPowerPoint() {
download(getFileName() + ".pptx", new JRPptxExporter());
}
public void exportToOds() {
download(getFileName() + ".ods", new JROdsExporter());
}
public void exportToOdt() {
download(getFileName() + ".odf", new JROdtExporter());
}
public void exportToRtf() {
download(getFileName() + ".rtf", new JRRtfExporter());
}
public void exportToHtml() {
download(getFileName() + ".html", new JRXhtmlExporter());
}
public void exportToCsv() {
download(getFileName() + ".csv", new JRCsvExporter());
}
public void exportToXml() {
download(getFileName() + ".xml", new JRXmlExporter());
}
protected void download(String filename, final JRExporter exporter) {
StreamResource resource = new StreamResource(new StreamResource.StreamSource() {
private static final long serialVersionUID = 1L;
@Override
public InputStream getStream() {
return new ByteArrayInputStream(getOutputStream(exporter).toByteArray());
}
}, filename);
EnterpriseApplication.getInstance().getMainWindow().open(resource, "", true);
}
}