package com.ibm.nmon.util;
import java.util.List;
import java.io.IOException;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import com.ibm.nmon.data.DataRecord;
import com.ibm.nmon.data.DataType;
import com.ibm.nmon.data.DataSet;
import com.ibm.nmon.data.ProcessDataSet;
import com.ibm.nmon.data.Process;
import com.ibm.nmon.gui.chart.data.DataTupleCategoryDataset;
import com.ibm.nmon.gui.chart.data.DataTupleDataset;
import com.ibm.nmon.gui.chart.data.DataTupleXYDataset;
import com.ibm.nmon.interval.Interval;
/**
* Helper class for writing CSV data to a Writer.
*/
public final class CSVWriter {
private static final SimpleDateFormat DATETIME = new SimpleDateFormat("yyyy-MM-dd,HH:mm:ss");
private static final DecimalFormat FORMAT = new DecimalFormat("0.000");
static {
// get and set required because DecimalFormat clones the symbols
java.text.DecimalFormatSymbols symbols = FORMAT.getDecimalFormatSymbols();
symbols.setNaN(""); // missing data => no output
symbols.setDecimalSeparator('.'); // force to avoid locale issues with , as separator
FORMAT.setDecimalFormatSymbols(symbols);
}
public static final void write(DataSet data, Interval interval, Writer writer) throws IOException {
StringBuilder builder = new StringBuilder(1024);
builder.append("Date,Time,");
for (DataType type : data.getTypes()) {
for (String field : type.getFields()) {
escape(type.toString(), builder);
builder.append(' ');
escape(field, builder);
builder.append(',');
}
}
builder.setCharAt(builder.length() - 1, '\n');
writer.write(builder.toString());
builder.setLength(0);
for (DataRecord record : data.getRecords(interval)) {
builder.append(DATETIME.format(new java.util.Date(record.getTime())));
builder.append(',');
for (DataType type : data.getTypes()) {
if (record.hasData(type)) {
for (String field : type.getFields()) {
builder.append(FORMAT.format(record.getData(type, field)));
builder.append(',');
}
}
else {
for (int i = 0; i < type.getFieldCount(); i++) {
builder.append(',');
}
}
}
builder.setCharAt(builder.length() - 1, '\n');
writer.write(builder.toString());
builder.setLength(0);
}
}
public static final void write(DataSet data, DataType type, Interval interval, Writer writer) throws IOException {
write(data, type, type.getFields(), interval, writer);
}
public static final void write(DataSet data, DataType type, String field, Interval interval, Writer writer)
throws IOException {
write(data, type, java.util.Collections.singletonList(field), interval, writer);
}
public static final void write(DataSet data, DataType type, List<String> fields, Interval interval, Writer writer)
throws IOException {
writer.write("Date,Time,");
for (int i = 0; i < fields.size() - 1; i++) {
escape(fields.get(i), writer);
writer.write(',');
}
escape(fields.get(fields.size() - 1), writer);
writer.write('\n');
for (DataRecord record : data.getRecords(interval)) {
writer.write(DATETIME.format(new java.util.Date(record.getTime())));
writer.write(',');
if (record.hasData(type)) {
for (int i = 0; i < fields.size() - 1; i++) {
writer.write(FORMAT.format(record.getData(type, fields.get(i))));
writer.write(',');
}
writer.write(FORMAT.format(record.getData(type, fields.get(fields.size() - 1))));
}
else {
for (int i = 0; i < fields.size(); i++) {
writer.write(',');
}
}
writer.write('\n');
}
}
public static void writeProcesses(DataSet data, Writer writer) throws IOException {
if (data instanceof ProcessDataSet) {
ProcessDataSet processData = (ProcessDataSet) data;
writer.write("PID,Name,StartDate,StartTime,EndDate,EndTime,CommandLine\n");
for (Process process : processData.getProcesses()) {
writer.write(Integer.toString(process.getId()));
writer.write(',');
escape(process.getName(), writer);
writer.write(',');
writer.write(DATETIME.format(process.getStartTime()));
writer.write(',');
writer.write(DATETIME.format(process.getEndTime()));
writer.write(',');
writer.write('"');
escape(process.getCommandLine(), writer);
writer.write('"');
writer.write('\n');
}
}
}
public static void write(DataTupleDataset data, Writer writer) throws IOException {
if (data instanceof DataTupleXYDataset) {
write((DataTupleXYDataset) data, writer);
}
else if (data instanceof DataTupleCategoryDataset) {
write((DataTupleCategoryDataset) data, writer);
}
}
public static void write(DataTupleXYDataset data, Writer writer) throws IOException {
writer.write("Date,Time,");
int seriesCount = data.getSeriesCount();
for (int i = 0; i < seriesCount - 1; i++) {
writer.write(data.getSeriesKey(i).toString());
writer.write(',');
}
writer.write(data.getSeriesKey(seriesCount - 1).toString());
writer.write('\n');
for (int i = 0; i < data.getItemCount(); i++) {
writer.write(DATETIME.format(data.getTimePeriod(i).getEnd()));
writer.write(',');
for (int j = 0; j < seriesCount - 1; j++) {
Number n = data.getY(j, i);
if (n == null) {
writer.write(FORMAT.format(Double.NaN));
}
else {
writer.write(FORMAT.format(n.doubleValue()));
}
writer.write(',');
}
Number n = data.getY(seriesCount - 1, i);
if (n == null) {
writer.write(FORMAT.format(Double.NaN));
}
else {
writer.write(FORMAT.format(n.doubleValue()));
}
writer.write('\n');
}
}
public static void write(DataTupleCategoryDataset data, Writer writer) throws IOException {
// output series names, leaving a blank column for item names
writer.write(',');
int columnCount = data.getColumnCount();
for (int i = 0; i < columnCount - 1; i++) {
writer.write(data.getColumnKey(i).toString());
writer.write(',');
}
writer.write(data.getColumnKey(columnCount - 1).toString());
writer.write('\n');
for (int i = 0; i < data.getRowCount(); i++) {
@SuppressWarnings("rawtypes")
Comparable rowKey = data.getRowKey(i);
writer.write(rowKey.toString());
writer.write(',');
for (int j = 0; j < columnCount - 1; j++) {
Object o = data.getValue(rowKey, data.getColumnKey(j));
if (o == null) {
writer.write(FORMAT.format(Double.NaN));
}
else {
writer.write(FORMAT.format(((Double) o).doubleValue()));
}
writer.write(',');
}
Object o = data.getValue(rowKey, data.getColumnKey(columnCount - 1));
if (o == null) {
writer.write(FORMAT.format(Double.NaN));
}
else {
writer.write(FORMAT.format(((Double) o).doubleValue()));
}
writer.write('\n');
}
}
private static void escape(String toEscape, Appendable appendable) throws IOException {
// no quotes or commas, just output the original string
if ((toEscape.indexOf("\"") == -1) && (toEscape.indexOf(",") == -1)) {
appendable.append(toEscape);
}
else {
// escape " with "" and quote the whole string
toEscape = toEscape.replaceAll("\"", "\"\"");
appendable.append("\"");
appendable.append(toEscape);
appendable.append("\"");
}
}
private CSVWriter() {}
}