package org.araqne.log.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CsvParser {
private final char qoute = '"';
private final char delimiter;
private final char escape;
private final ArrayList<String> cachedColumnHeaders = new ArrayList<String>();
public CsvParser(boolean useTab, boolean useDoubleQuote, String[] columnHeaders) {
this.delimiter = useTab ? '\t' : ',';
this.escape = useDoubleQuote ? '"' : '\\';
if (columnHeaders != null)
for (String header : columnHeaders)
cachedColumnHeaders.add(header);
}
public Map<String, Object> parse(String line) {
boolean containEscape = false;
boolean openQuote = false;
boolean openChar = false;
boolean checkEnd = false;
int startIndex = 0;
int endIndex = 0;
int length = line.length();
List<String> values = new ArrayList<String>();
for (int i = 0; i < length; i++) {
char c = line.charAt(i);
if (!openChar && c == qoute) {
if (!openQuote)
startIndex = i + 1;
else {
endIndex = i;
checkEnd = true;
}
openQuote = !openQuote;
} else if (openQuote && c == escape) {
if (!containEscape)
containEscape = true;
if (!openQuote && !openChar) {
openChar = true;
startIndex = i;
}
i++;
if (openChar)
endIndex = i + 1;
} else if (c == delimiter && !openQuote) {
String value = line.substring(startIndex, endIndex);
if (containEscape) {
value = removeEscape(value, escape);
containEscape = false;
}
values.add(value);
startIndex = i + 1;
endIndex = i + 1;
openChar = false;
checkEnd = false;
} else {
if (!openQuote && !openChar) {
startIndex = i;
openChar = true;
}
if ((!checkEnd && openChar) || openQuote)
endIndex = i + 1;
}
}
if (endIndex > length)
throw new IllegalArgumentException("invalid csv parse option. delimiter [" + delimiter + "], escape [" + escape
+ "], line [" + line + "]");
String value = line.substring(startIndex, endIndex);
if (containEscape)
value = removeEscape(value, escape);
values.add(value);
return toMap(values);
}
private Map<String, Object> toMap(List<String> values) {
Map<String, Object> m = new HashMap<String, Object>(values.size());
int i = 0;
for (String value : values) {
String header = null;
try {
header = cachedColumnHeaders.get(i);
} catch (IndexOutOfBoundsException e) {
header = "column" + i;
cachedColumnHeaders.add(header);
}
m.put(header, value);
i++;
}
return m;
}
private String removeEscape(String value, char escape) {
StringBuilder sb = new StringBuilder(value.length());
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == escape) {
sb.append(value.charAt(++i));
continue;
}
sb.append(c);
}
return sb.toString();
}
}