/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cli_fmw.report.implemenatation;
import cli_fmw.main.ClipsException;
import cli_fmw.report.ExtraField;
import cli_fmw.report.TableReportOptions;
import cli_fmw.report.ReporterFactory;
import cli_fmw.report.SampleMapEntry;
import cli_fmw.report.implemenatation.JasperReportBuilder;
import cli_fmw.report.implemenatation.JasperSubReport;
import cli_fmw.report.implemenatation.JasperSubReportContener;
import cli_fmw.report.implemenatation.JasperTableBuilder;
import cli_fmw.report.implemenatation.JasperrCustomizerTable;
import cli_fmw.report.implemenatation.JasperrCustomizerTableItem;
import cli_fmw.report.implemenatation.ReportPreview;
import cli_fmw.report.implemenatation.StringTableModel;
import cli_fmw.report.SegmentedTableReporter;
import cli_fmw.utils.MessageBox;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRTableModelDataSource;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignExpression;
import net.sf.jasperreports.engine.design.JRDesignTextField;
/**
* Имплементация интерфейса AnalyseReporter на основе JasperReportBuilder
* @author finder
*/
public class SegmentedTableBuilder implements SegmentedTableReporter, JasperrCustomizerTableItem, JasperrCustomizerTable, JasperSubReport{
/**
* заголовок Анализа
*/
private String title;
/**
* модель таблицы, с получеными данными
*/
private StringTableModel model = new StringTableModel();
/**
* Список полей, которые будут добавлены до данных анализа.
*/
private ArrayList<Map.Entry<String, Object>> topFields;
/**
* Список полей, которые будут добавлены после анализа
*/
private ArrayList<Map.Entry<String, Object>> bottomFields;
/**
* опции которые будут использоватся при построении отчетов.
*/
private TableReportOptions options = new TableReportOptions();
private JasperTableBuilder tableBuilder = null;
private JasperReportBuilder reportBuilder = null;
private JRDesignExpression itemChekExp = null;
private JasperSubReportContener combinedReporter;
/**
* Устанавливает заголовок Анализа
* @param title
*/
@Override
public void setTitle(String title) {
this.title = title;
}
/**
* Устанавливает шапку таблицы.
* Размер массива определяет количество столбцов.
* 3<=list.size
* @param list
*/
@SuppressWarnings("unchecked")
@Override
public void setHeader(List<String> header) {
model.setDataVector(null, toOffsetVector(header));
}
/**
* Добавляет строку таблицу
* Размер массива должен совпадать с размером заголовка,
* иначе выбрасывается IllegalArgumentException
* @param list
*/
@Override
public void addRow(List<String> list) {
if (list.size() + 1 != model.getColumnCount()) {
throw new IllegalArgumentException("Число элементов в массиве должно совпадать с числом элементов переданных в setHeader");
}
model.addRow(toOffsetVector(list));
}
/**
* Добавляет строку разделитель в таблицу
* @param separator
*/
@Override
public void addSeparator(String separator) {
Vector<String> target = new Vector<String>(model.getColumnCount());
target.setSize(model.getColumnCount());
target.set(0, separator);
model.addRow(target);
}
/**
* Добавляет элемент, состоящий из 2 частей - параметр и значение
* @param title параметр
* @param value значение
* @param afterTable если true, то добавлять после таблицы
*/
@Override
public void addField(String title, String value, boolean afterTable) {
addField(new ExtraField(value, title), afterTable);
}
/**
* Добавляет элемент, состоящий из 2 частей - параметр и значение до таблицы
* @param title параметр
* @param value значение
*/
@Override
public void addField(String title, String value) {
addField(title, value, false);
}
/**
* Элемент отформатированный в соотведстви с параметрами структуры ExtraField
* @param field
* @param afterTable если true, то добавлять после таблицы
*/
@Override
public void addField(ExtraField field, boolean afterTable) {
if (afterTable){
if (bottomFields == null) {
bottomFields = new ArrayList<Map.Entry<String, Object>>();
}
bottomFields.add(new SampleMapEntry<String, Object>(null, field));
}
else{
if (topFields == null) {
topFields = new ArrayList<Map.Entry<String, Object>>();
}
topFields.add(new SampleMapEntry<String, Object>(null, field));
}
}
/**
* Формирует по полученным данним отчет, и показавает его во всплывающем окне.
*/
@SuppressWarnings("unchecked")
@Override
public void finish() {
if (combinedReporter == null){
try {
JasperPrint print = JasperFillManager.fillReport(getTemplate(), getParameters());
ReportPreview.showReport(print);
} catch (ClipsException ex) {
MessageBox.asyncShowExceptionOnly(ex, true);
} catch (JRException ex) {
MessageBox.asyncShowExceptionOnly(ex, true);
}
}
else{
combinedReporter.addSubReport(this);
}
}
/**
* коприрует поля в hashmap попутно преобразовывая их в строки.
* @param sourse - источник
* @param dest - назанчение
*/
public void putFields(Collection<Map.Entry<String, Object>> sourse, Map<String, Object> dest){
for (Map.Entry<String, Object> entry : sourse) {
if (entry.getKey() != null) {
dest.put(entry.getKey(), ReporterFactory.convertDataToString(entry.getValue()));
}
}
}
/**
* копирует содержимое List в Vector, и вставляет в качестве первого элемента null
* @param list
* @return
*/
private Vector<String> toOffsetVector(List<String> list){
Vector<String> target = new Vector<String>(list.size() + 1);
target.add(null);
target.addAll(list);
return target;
}
/**
*
* @param builder
*/
@Override
public void customizerBuilder(JasperReportBuilder builder){
if (reportBuilder != builder) {
throw new RuntimeException("Incorrect builder!");
}
}
@Override
public void customizeTableBuilder(JasperTableBuilder builder) {
if (tableBuilder != builder) {
throw new RuntimeException("Incorrect builder!");
}
tableBuilder.setBeginColoumn(1);
}
@Override
public boolean onNewTableElement(int pos, int size, int coloumn, boolean header, JRField dataField, JRDesignTextField element) throws JRException {
if (!header){
JRDesignExpression exp;
if (coloumn != 0){
if (itemChekExp == null){
JRField checkField = tableBuilder.createTableField(0);
itemChekExp = reportBuilder.createBooleanExpression("$F{" + checkField.getName() + "} == null");
}
exp = itemChekExp;
}
else{
JRField checkField = tableBuilder.createTableField(0);
exp = reportBuilder.createBooleanExpression("$F{" + checkField.getName() + "} != null");
element.setBold(true);
}
element.setPrintWhenExpression(exp);
}
return true;
}
@Override
public void onTableCreated(JRDesignBand colomnHeaderBand, JRDesignBand detalsBand, double[] itemSizes) throws JRException{
tableBuilder.createTableItem(0, reportBuilder.getDestingWidth(), 0, false);
}
@Override
public void setAsSubreport(JasperSubReportContener combinedReporter) {
this.combinedReporter = combinedReporter;
if (this.combinedReporter != null) {
this.combinedReporter.correctReportPageSize(options);
}
}
@Override
public JasperReport getTemplate() throws ClipsException, JRException {
tableBuilder = new JasperTableBuilder(options, model);
reportBuilder = new JasperReportBuilder(title, options, topFields, bottomFields, tableBuilder);
reportBuilder.applyCostumizer(this);
JasperReport template = reportBuilder.buildReport();
return template;
}
@Override
public Map<String, ?> getParameters() throws ClipsException, JRException {
HashMap<String, Object> param = new HashMap<String, Object>();
if (topFields != null){
putFields(topFields, param);
}
if (bottomFields != null){
putFields(bottomFields, param);
}
param.put(JRParameter.REPORT_DATA_SOURCE, new JRTableModelDataSource(model));
return param;
}
@Override
public void setPageOptions(TableReportOptions options) {
if (options == null) {
options = new TableReportOptions();
}
this.options = options;
if (this.combinedReporter != null) {
this.combinedReporter.correctReportPageSize(this.options);
}
}
}