package mireka.transmission.queue.dataprop; import java.text.ParseException; import java.util.ArrayList; import java.util.List; class ListParser<T> { private final StringToElementConverter<T> elementConverter; private final String inputString; private final List<T> list = new ArrayList<T>(); private int i = 0; public ListParser(String inputString, StringToElementConverter<T> elementConverter) { this.inputString = inputString; this.elementConverter = elementConverter; } public List<T> parse() throws ParseException { parseInner(); return list; } private void parseInner() throws ParseException { skipWhitespaces(); if (peek() == -1) return; while (true) { if (peek() == '"') { addQuotedElement(); } else { addUnquotedElement(); skipWhitespaces(); } int ch = peek(); if (ch == -1) { return; } else if (ch == ',') { read(); // skip ',' skipWhitespaces(); continue; } else { throw new ParseException("Expected: ',' or EOF, received: '" + ch + "'", i); } } } private void skipWhitespaces() throws ParseException { while (nextIsWhitespace()) read(); } private boolean nextIsWhitespace() throws ParseException { int ch = peek(); return ch == ' ' || ch == '\t'; } private int peek() throws ParseException { if (i > inputString.length()) throw new ParseException("EOF already read", i); else if (i == inputString.length()) return -1; return inputString.charAt(i); } private int read() throws ParseException { int ch = peek(); i++; return ch; } private void addQuotedElement() throws ParseException { String elementString = readQuotedString(); addString(elementString); } private void addString(String elementString) { T element = elementConverter.toElement(elementString); list.add(element); } private String readQuotedString() throws ParseException { int ch = read(); if (ch != '"') throw new IllegalStateException(); StringBuilder buffer = new StringBuilder(); while ('"' != (ch = peek())) { if (ch == '\\') { buffer.append(readEscapedChar()); } else if (ch == -1) { throw new ParseException("Unexpected EOF", i); } else { buffer.append((char) read()); } } read(); // closing quote skipWhitespaces(); // spaces after ending quote return buffer.toString(); } private char readEscapedChar() throws ParseException { read(); // skip backslash int ch = read(); if (ch == -1) throw new ParseException("Unexpected EOF", i); return (char) ch; } private void addUnquotedElement() throws ParseException { String elementString = readUnquotedString(); addString(elementString); } private String readUnquotedString() throws ParseException { StringBuilder buffer = new StringBuilder(); while (!nextIsEndOfUnquotedString()) { buffer.append((char) read()); } String elementString = buffer.toString().trim(); return elementString; } private boolean nextIsEndOfUnquotedString() throws ParseException { int ch = peek(); return ch == ',' || ch == -1; } }