package co.smartreceipts.android.workers.reports.csv;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import co.smartreceipts.android.filters.Filter;
import co.smartreceipts.android.model.Column;
import co.smartreceipts.android.workers.reports.TableGenerator;
/**
* Implements the {@link TableGenerator} contract to generate
* a {@link String}, which is a CSV
*
* @author williambaumann
*/
public final class CsvTableGenerator<DataType> implements TableGenerator<String, DataType> {
private static final String QUOTE = "\"";
private static final String ESCAPED_QUOTE = "\"\"";
private static final String[] STRINGS_THAT_MUST_BE_QUOTED = {",", "\"", "\n", "\r\n"};
private final List<Column<DataType>> mColumns;
private final Filter<DataType> mFilter;
private final boolean mPrintHeaders;
private final boolean mPrintFooters;
public CsvTableGenerator(@NonNull List<Column<DataType>> columns, boolean printHeaders, boolean printFooters) {
this(columns, null, printHeaders, printFooters);
}
public CsvTableGenerator(@NonNull List<Column<DataType>> columns, @Nullable Filter<DataType> filter, boolean printHeaders, boolean printFooters) {
mColumns = columns;
mFilter = filter;
mPrintHeaders = printHeaders;
mPrintFooters = printFooters;
}
@NonNull
@Override
public String generate(@NonNull List<DataType> list) {
if (!list.isEmpty()) {
final int columnCount = mColumns.size();
final StringBuilder csvBuilder = new StringBuilder("");
// Add the header
if (mPrintHeaders) {
for (int i = 0; i < columnCount; i++) {
addCell(csvBuilder, mColumns.get(i).getHeader());
}
csvBuilder.append("\n");
}
// Add each row
final List<DataType> filteredList = new ArrayList<>(list.size());
for (int j = 0; j < list.size(); j++) {
final DataType data = list.get(j);
if (mFilter == null || mFilter.accept(data)) {
for (int i = 0; i < columnCount; i++) {
addCell(csvBuilder, mColumns.get(i).getValue(data));
}
filteredList.add(data);
}
csvBuilder.append("\n");
}
// Add the footer
if (mPrintFooters) {
for (int i = 0; i < columnCount; i++) {
addCell(csvBuilder, mColumns.get(i).getFooter(filteredList));
}
csvBuilder.append("\n");
}
return csvBuilder.toString();
} else {
return ""; // Just return an empty csv if we don't have any objects
}
}
private void addCell(@NonNull StringBuilder csvBuilder, @Nullable String value) {
if (value != null) {
if (value.contains(QUOTE)) {
value = value.replace(QUOTE, ESCAPED_QUOTE);
}
for (String stringToQuote : STRINGS_THAT_MUST_BE_QUOTED) {
if (value.contains(stringToQuote)) {
value = QUOTE + value + QUOTE;
break;
}
}
csvBuilder.append(value);
}
csvBuilder.append(",");
}
}