package net.codjo.dataprocess.gui.util.std;
import net.codjo.gui.toolkit.table.GroupColumn;
import net.codjo.gui.toolkit.table.GroupableTableHeader;
import net.codjo.mad.client.request.RequestException;
import net.codjo.mad.common.WindowsHelper;
import net.codjo.mad.gui.framework.GuiContext;
import net.codjo.mad.gui.request.RequestTable;
import java.awt.Component;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JLabel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import org.apache.log4j.Logger;
/**
*
*/
public class ExportTextBuilder {
private static final Logger LOG = Logger.getLogger(ExportTextBuilder.class);
private static final int MAX_NB_FILES_TO_CREATE = 10;
private static final String NUMERIC_SORTER = "Numeric";
private static final String DEFAULT_DECIMAL_SEPARATOR = ".";
private static final String DEFAULT_FILE_BASE_NAME = "export_txt";
private static final String DEFAULT_FILE_EXT = ".txt";
private static final String DEFAULT_FILE_SEPARATOR = "\t";
private static final String TEMPORARY_DIRECTORY = System.getProperty("java.io.tmpdir");
private List<RequestTable> tableList = new ArrayList<RequestTable>();
private Map<RequestTable, List<Object[][]>> headerTable = new HashMap<RequestTable, List<Object[][]>>();
private GuiContext context;
private RenderValueFunctor renderValueFunctor = new MyRenderValueFunctor();
public ExportTextBuilder() {
}
public ExportTextBuilder add(RequestTable jTable) {
return add(jTable, true);
}
public ExportTextBuilder add(RequestTable jTable, boolean withHeader) {
this.tableList.add(jTable);
return this;
}
public ExportTextBuilder setHeaderData(RequestTable jTable, Object[][]... headers) {
List<Object[][]> headerList = new ArrayList<Object[][]>();
headerList.addAll(Arrays.asList(headers));
headerTable.put(jTable, headerList);
return this;
}
public void buildTextDatas(boolean exportAllPages, ExportTextWriter writer)
throws RequestException, IOException {
int maxColumnCount = findMaxColumnCount();
for (RequestTable table : tableList) {
int numcols = table.getColumnCount();
processHeader(table, maxColumnCount, writer);
processDataRows(table, maxColumnCount, numcols, writer);
if (exportAllPages) {
while (table.hasNextPage()) {
table.loadNextPage();
processDataRows(table, maxColumnCount, numcols, writer);
}
}
}
}
private void processDataRows(RequestTable table,
int maxColumnCount,
int numcols,
ExportTextWriter writer) throws IOException {
String[] sorters = new String[table.getColumnCount()];
for (int i = 0; i < table.getColumnCount(); i++) {
sorters[i] = table.getPreference()
.getColumns()
.get(table.convertColumnIndexToView(i))
.getSorter();
}
for (int rowIndex = 0; rowIndex < table.getRowCount(); rowIndex++) {
Object[] dataRow = new Object[maxColumnCount];
for (int colIndex = 0; colIndex < numcols; colIndex++) {
dataRow[colIndex] = renderValueFunctor.getRenderedValue(table, rowIndex, colIndex);
}
writeRow(dataRow, writer, sorters);
}
}
private void processHeader(RequestTable table, int maxColumnCount, ExportTextWriter writer)
throws IOException {
List<Object[][]> headerDataList = headerTable.get(table);
if (headerDataList != null) {
for (Object[][] headerData : headerDataList) {
for (Object[] aHeaderData : headerData) {
Object[] dataRow = new Object[maxColumnCount];
System.arraycopy(aHeaderData, 0, dataRow, 0, aHeaderData.length);
writeRow(dataRow, writer, null);
}
}
}
}
private int findMaxColumnCount() {
int length = 0;
for (RequestTable table : tableList) {
int columnCount = table.getColumnCount();
if (columnCount > length) {
length = columnCount;
}
}
return length;
}
public static Object[][] createColumnHeader(RequestTable jTable) {
JTableHeader tableHeader = jTable.getTableHeader();
if (tableHeader instanceof GroupableTableHeader) {
return createGroupableColumnHeader(tableHeader, jTable);
}
else {
return createDefaultColumnHeader(jTable);
}
}
private static Object[][] createDefaultColumnHeader(RequestTable jTable) {
TableColumnModel columnModel = jTable.getTableHeader().getColumnModel();
int columnCount = columnModel.getColumnCount();
Object[][] headerArray = new Object[1][columnCount];
for (int colIndex = 0; colIndex < columnCount; colIndex++) {
headerArray[0][colIndex] = columnModel.getColumn(colIndex).getHeaderValue();
}
return headerArray;
}
private static Object[][] createGroupableColumnHeader(JTableHeader tableHeader, RequestTable jTable) {
GroupableTableHeader header = (GroupableTableHeader)tableHeader;
int columnCount = jTable.getColumnCount();
int headerRowCount = header.getRowCount();
Object[][] headerArray = new Object[headerRowCount][columnCount];
TableColumnModel columnModel = jTable.getColumnModel();
for (int col = 0; col < columnCount; col++) {
TableColumn tableColumn = columnModel.getColumn(col);
int row = 0;
for (Iterator<GroupColumn> it = header.getColumnGroups(tableColumn); it.hasNext(); ) {
GroupColumn groupColumn = it.next();
headerArray[row][col] = groupColumn.getHeaderValue();
row++;
}
headerArray[headerRowCount - 1][col] = jTable.getColumnName(col);
}
return headerArray;
}
public List<RequestTable> getTableList() {
return tableList;
}
private static void writeRow(Object[] data, ExportTextWriter writer, String[] sorters)
throws IOException {
StringBuilder sb = new StringBuilder();
int numcols = data.length;
for (int j = 0; j < numcols; j++) {
Object val = data[j];
if (val != null && val instanceof String) {
if (null != writer.getDecimalSeparator()
&& null != sorters
&& NUMERIC_SORTER.equalsIgnoreCase(sorters[j])) {
val = ((String)val).replace(DEFAULT_DECIMAL_SEPARATOR, writer.getDecimalSeparator());
}
}
if (val != null) {
sb.append("\"").append(val).append("\"");
}
if (j < numcols - 1) {
sb.append(writer.getFileSeparator());
}
}
sb.append("\n");
writer.write(sb.toString());
}
private static String generateFilename(String fileBaseName, String fileExt, int nbFile) {
String fileName = TEMPORARY_DIRECTORY + fileBaseName;
if (nbFile == 0) {
fileName += fileExt;
}
else {
fileName += nbFile + fileExt;
}
return fileName;
}
public void generate(boolean exportAllPages) throws IOException, RequestException {
String fileBaseName;
String fileExt;
if (context != null) {
if (context.hasProperty("export.text.fileBaseName")) {
fileBaseName = (String)context.getProperty("export.text.fileBaseName");
}
else {
fileBaseName = DEFAULT_FILE_BASE_NAME;
}
if (context.hasProperty("export.text.fileExt")) {
fileExt = (String)context.getProperty("export.text.fileExt");
}
else {
fileExt = DEFAULT_FILE_EXT;
}
}
else {
throw new IllegalArgumentException(
"Le GuiContext n'a pas �t� initialis�. Appelez 'ExportTextBuilder.setGuiContext' avant.");
}
ExportTextWriter exportTextWriter = null;
String fileName;
try {
if (tableList.isEmpty()) {
throw new RequestException("No table was added, use ");
}
FileWriter file = null;
String errMsg = "";
int nbFile = 0;
fileName = generateFilename(fileBaseName, fileExt, nbFile);
while ((file == null) && (nbFile <= MAX_NB_FILES_TO_CREATE)) {
try {
file = new FileWriter(fileName);
}
catch (Exception ex) {
errMsg = ex.getMessage();
nbFile++;
fileName = generateFilename(fileBaseName, fileExt, nbFile);
}
}
if (file == null) {
context.displayInfo("Impossible d'ouvrir le fichier : " + errMsg);
throw new IOException("Impossible d'ouvrir le fichier : " + errMsg);
}
exportTextWriter = new ExportTextWriter(context, file);
context.displayInfo("Export de type text vers " + fileName);
buildTextDatas(exportAllPages, exportTextWriter);
}
catch (IOException ex) {
LOG.error(ex.getMessage(), ex);
context.displayInfo(ex.getLocalizedMessage());
throw new IOException(ex.getLocalizedMessage());
}
catch (RequestException ex) {
LOG.error(ex.getMessage(), ex);
context.displayInfo(ex.getLocalizedMessage());
throw new RequestException(ex.getLocalizedMessage());
}
finally {
if (exportTextWriter != null) {
exportTextWriter.close();
}
}
WindowsHelper.openWindowsFile(new File(fileName));
}
public void setGuiContext(GuiContext context) {
this.context = context;
}
GuiContext getContext() {
return context;
}
public void addAll(RequestTable... tables) {
for (RequestTable table : tables) {
add(table);
}
}
public void setRenderValueFunctor(RenderValueFunctor renderValueFunctor) {
this.renderValueFunctor = renderValueFunctor;
}
static class ExportTextWriter extends BufferedWriter {
private String fileSeparator = DEFAULT_FILE_SEPARATOR;
private String decimalSeparator = DEFAULT_DECIMAL_SEPARATOR;
ExportTextWriter(GuiContext context, Writer file) {
super(file);
configSeparator(context);
}
ExportTextWriter(GuiContext context, Writer file, int sz) {
super(file, sz);
configSeparator(context);
}
private void configSeparator(GuiContext context) {
if (context != null) {
if (context.hasProperty("export.text.fileSeparator")) {
fileSeparator = (String)context.getProperty("export.text.fileSeparator");
}
if (context.hasProperty("export.text.decimalSeparator")) {
decimalSeparator = (String)context.getProperty("export.text.decimalSeparator");
}
}
else {
throw new IllegalArgumentException(
"Le GuiContext n'a pas �t� initialis�. Appelez 'ExportTextBuilder.setGuiContext' avant.");
}
}
public String getFileSeparator() {
return fileSeparator;
}
public String getDecimalSeparator() {
return decimalSeparator;
}
}
public static interface RenderValueFunctor {
Object getRenderedValue(RequestTable jTable, int row, int col);
}
private static class MyRenderValueFunctor implements RenderValueFunctor {
public Object getRenderedValue(RequestTable jTable, int row, int col) {
int columnIndexToView = jTable.convertColumnIndexToView(col);
TableCellRenderer renderer = jTable.getCellRenderer(row, columnIndexToView);
Object value = jTable.getValueAt(row, col);
if (renderer != null) {
Component component = renderer
.getTableCellRendererComponent(jTable, value, false, false, row, col);
if (component instanceof JLabel) {
value = ((JLabel)component).getText();
}
}
return value;
}
}
}