/*
* Copyright 2008-2017 by Emeric Vernat
*
* This file is part of Java Melody.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bull.javamelody.swing.print;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.Locale;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JTable;
import net.bull.javamelody.I18NAdapter;
import net.bull.javamelody.swing.table.MBasicTable;
/**
* Writer CSV non localisé.
*
* @author Emeric Vernat
*/
public class MCsvWriter extends MPrinter {
/** Caractère de séparation dans les fichiers csv (non local). */
public static final char CSV_SEPARATOR = ',';
/**
* Icône Excel.
*/
public static final ImageIcon MSEXCEL_ICON = new ImageIcon(
MCsvWriter.class.getResource("/icons/ms excel.png"));
/** {@inheritDoc} */
@Override
public void print(final MBasicTable table, final OutputStream out) throws IOException {
writeCsv(table, out);
}
/** {@inheritDoc} */
@Override
public String getName() {
return I18NAdapter.getString("export_csv");
}
/** {@inheritDoc} */
@Override
public String getFileExtension() {
return "csv";
}
/** {@inheritDoc} */
@Override
public Icon getIcon() {
return MSEXCEL_ICON;
}
/**
* Encode un texte pour l'export au format csv ou csv local.
*
* @return String
* @param text
* String
* @param csvSeparator
* char
*/
protected String formatCsv(final String text, final char csvSeparator) {
String result = text;
if (result.indexOf('\n') != -1) {
// le retour chariot fonctionne dans les dernières versions d'excel entre des doubles quotes
// mais il ne fonctionne pas dans OpenOffice 1.1.2
result = result.replace('\n', ' ');
}
int index = result.indexOf('"');
while (index != -1) {
// on double les double-quote pour csv (non performant mais rare)
result = new StringBuilder(result).insert(index, '"').toString();
index = result.indexOf('"', index + 2);
}
if (text.indexOf(csvSeparator) != -1 || text.indexOf('"') != -1) {
final String tmp = '"' + result + '"';
result = tmp;
}
return result;
}
/**
* Exporte une JTable dans un fichier au format csv pour double-clique. (séparateur ',', formats nombres et dates US).
*
* @param table
* MBasicTable
* @param outputStream
* OutputStream
* @throws IOException
* Erreur disque
*/
protected void writeCsv(final MBasicTable table, final OutputStream outputStream)
throws IOException {
writeCsv(table, outputStream, DateFormat.getDateInstance(DateFormat.SHORT, Locale.US));
}
/**
* Exporte une JTable dans un fichier au format csv pour double-clique. (séparateur ',', formats nombres et dates US).
*
* @param table
* MBasicTable
* @param outputStream
* OutputStream
* @param dateFormat
* DateFormat
* @throws IOException
* Erreur disque
*/
protected void writeCsv(final MBasicTable table, final OutputStream outputStream,
final DateFormat dateFormat) throws IOException {
// récupération des informations utiles
final int columnCount = table.getColumnModel().getColumnCount();
final int rowCount = table.getRowCount();
final String charset = System.getProperty("file.encoding");
final Writer out = new OutputStreamWriter(outputStream, charset);
final char csvSeparator = CSV_SEPARATOR;
// le séparateur des .csv (',' à l'américaine)
final NumberFormat decimalFormat = NumberFormat.getInstance(Locale.US);
decimalFormat.setGroupingUsed(false);
final String eol = System.getProperty("line.separator");
// titres des colonnes
writeCsvHeader(table, out, csvSeparator);
// les données proprement dites (ligne par ligne puis colonne par colonne)
Object value;
String text;
for (int k = 0; k < rowCount; k++) {
for (int i = 0; i < columnCount; i++) {
value = getValueAt(table, k, i);
if (value instanceof Number) {
text = decimalFormat.format(value);
} else if (value instanceof Date) {
text = dateFormat.format(value);
} else if (value instanceof Boolean) {
text = value.toString();
} else {
text = getTextAt(table, k, i);
text = formatCsv(text, csvSeparator);
}
out.write(text);
if (i < columnCount - 1) {
out.write(csvSeparator);
}
}
if (k < rowCount - 1) {
out.write(eol);
}
}
out.flush();
}
/**
* Exporte les headers csv d'une JTable..
*
* @param table
* JTable
* @param out
* Writer
* @param csvSeparator
* char
* @throws IOException
* Erreur disque
*/
protected void writeCsvHeader(final JTable table, final Writer out, final char csvSeparator)
throws IOException {
// récupération des informations utiles
final int columnCount = table.getColumnModel().getColumnCount();
final String eol = System.getProperty("line.separator");
if (table.getName() != null) {
String title = formatCsv(table.getName(), csvSeparator);
if (title.startsWith("ID")) {
final String tmp = '"' + title + '"';
title = tmp;
}
out.write(title);
out.write(eol);
}
// titres des colonnes
String text;
for (int i = 0; i < columnCount; i++) {
text = String.valueOf(table.getColumnModel().getColumn(i).getHeaderValue());
text = formatCsv(text, csvSeparator);
if (i == 0 && text.startsWith("ID")) {
out.write('"' + text + '"'); // si commence par ID, Excel pense que c'est un sylk !
} else {
out.write(text);
}
if (i < columnCount - 1) {
out.write(csvSeparator);
}
}
out.write(eol);
}
}