package ca.sqlpower.sql;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.StringCharacterIterator;
public class WebResultCSVFormatter extends WebResultFormatter {
public WebResultCSVFormatter() {
super();
}
public void formatToStream(WebResultSet wrs, PrintWriter out)
throws SQLException, NoRowidException, IllegalStateException {
formatHeader(wrs,out);
formatBody(wrs,out);
}
public void formatHeader(WebResultSet wrs, PrintWriter out) throws SQLException {
int numCols=wrs.getColumnCount();
StringBuffer sb=new StringBuffer(256);
boolean thisIsTheFirstColumn = true;
for (int i = 1; i <= numCols; i++) {
if (columnNotAppropriate(wrs, i)) {
continue;
}
sb.setLength(0);
try {
if (!thisIsTheFirstColumn) {
sb.append(",");
}
sb.append(
makeStringSafe(beautifyHeading(wrs.getColumnLabel(i))));
out.print(sb);
thisIsTheFirstColumn = false;
} catch (ColumnNotDisplayableException e) {
// Column didn't get printed (which is good)
}
}
out.println("");
}
public void formatBody(WebResultSet wrs, PrintWriter out)
throws SQLException, NoRowidException {
int numCols=wrs.getColumnCount();
StringBuffer contents=new StringBuffer(256);
StringBuffer align=new StringBuffer(32);
while (wrs.next()) {
boolean thisIsTheFirstColumn = true;
for (int i = 1; i <= numCols; i++) {
if (columnNotAppropriate(wrs, i)) {
continue;
}
contents.setLength(0);
align.setLength(0);
try {
getColumnFormatted(wrs, i, contents, align);
if (!thisIsTheFirstColumn) {
out.print(",");
}
out.print(makeStringSafe(contents.toString()));
thisIsTheFirstColumn = false;
} catch (ColumnNotDisplayableException e) {
// Column didn't get printed (which is good)
} catch (UnsupportedOperationException e) {
// Column didn't get printed, but we wanted it to
out.print(makeStringSafe(wrs.getString(i)));
}
}
out.println("");
}
}
/**
* Makes a CSV-file-safe version of a given string. This includes
* escaping CR, LF, and double-quote characters with backslashes,
* and quoting strings that contain whitespace.
*
* @param original The original, unsafe string.
* @return The original string if it contained none of the special
* characters mentioned above; an empty string if the original was
* null; otherwise, a quoted version of the original string with
* the necessary characters backslash-escaped.
*/
public static String makeStringSafe(String original) {
if(original==null) {
return "";
}
StringBuffer escaped = new StringBuffer(original.length());
StringCharacterIterator it = new StringCharacterIterator(original);
boolean escapedDiffersFromOriginal=false;
char ch;
escaped.append("\"");
do {
ch=it.current();
switch(ch) {
case '\n':
escaped.append("\\n");
escapedDiffersFromOriginal=true;
break;
case '\r':
escaped.append("\\r");
escapedDiffersFromOriginal=true;
break;
case '"':
escaped.append("\\\"");
escapedDiffersFromOriginal=true;
break;
case '\\':
escaped.append("\\\\");
escapedDiffersFromOriginal=true;
break;
case ' ':
case '\f':
case '\t':
case ',':
// Whitespace and commas don't need to be escaped
// explicitly, but the whole string will need to be
// quoted.
escaped.append(ch);
escapedDiffersFromOriginal=true;
break;
default:
escaped.append(ch);
break;
}
} while( it.next() != StringCharacterIterator.DONE);
escaped.append("\"");
return (escapedDiffersFromOriginal ? escaped.toString() : original);
}
protected boolean columnNotAppropriate(WebResultSet wrs, int colNo) {
/* if(wrs.getColumnHyperlinks(colNo) != null) {
return true;
} */
int ctype=wrs.getColumnType(colNo);
switch(ctype) {
case FieldTypes.RADIO:
case FieldTypes.CHECKBOX:
case FieldTypes.ROWID:
case FieldTypes.DUMMY:
case FieldTypes.MUTEX_CHECKBOX:
return true;
default:
return false;
}
}
/**
* @see ca.sqlpower.sql.WebResultFormatter#getColumnFormatted(WebResultSet, int, StringBuffer, StringBuffer)
*/
protected void getColumnFormatted(
WebResultSet wrs,
int i,
StringBuffer contents,
StringBuffer align)
throws
SQLException,
NoRowidException,
ColumnNotDisplayableException,
IllegalStateException {
java.sql.ResultSetMetaData md = wrs.getRsmd();
switch (md.getColumnType(i)) {
case java.sql.Types.TIMESTAMP:
java.sql.Date tsDate=wrs.getDate(i);
if(tsDate==null) {
// leave empty
} else {
contents.append(
dateFormatter.format(new java.util.Date(tsDate.getTime())));
}
break;
default:
contents.append(wrs.getString(i));
}
}
}