1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jdiagnose.remote.file;
17
18 import java.io.BufferedReader;
19 import java.io.IOException;
20 import java.io.Reader;
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.NoSuchElementException;
25
26 import org.jdiagnose.exception.NestableRuntimeException;
27
28 /***
29 * @author jmccrindle
30 */
31 public class DefaultCsvParser implements CsvParser {
32
33 private boolean ensureColumnSize = false;
34
35 public Iterator parse(Reader r) throws IOException {
36 final BufferedReader reader = new BufferedReader(r);
37
38 return new Iterator() {
39
40 private int size = -1;
41 private String line = null;
42 private List result = null;
43
44 {
45 try {
46 updateResult();
47 } catch (IOException e) {
48 throw new NestableRuntimeException(e);
49 }
50 }
51
52 public void remove() {
53 throw new UnsupportedOperationException();
54 }
55
56 public boolean hasNext() {
57 return line != null;
58 }
59
60 private void updateResult() throws IOException {
61 line = reader.readLine();
62 if(line != null) {
63 result = parseLine(line);
64 if(ensureColumnSize) {
65 if(size == -1) {
66 size = result.size();
67 } else if(size != result.size()) {
68 throw new RuntimeException();
69 }
70 }
71 } else {
72 result = null;
73 }
74 }
75
76 public Object next() {
77 if(!hasNext()) {
78 throw new NoSuchElementException();
79 } else {
80 List currentResult = result;
81 try {
82 updateResult();
83 } catch (IOException e) {
84 throw new NestableRuntimeException(e);
85 }
86 return currentResult;
87 }
88 }
89 };
90
91 }
92
93 private static class CharacterIterator {
94 private String s;
95 private int index = 0;
96
97 public CharacterIterator(String s) {
98 this.s = s;
99 }
100
101 public char next() {
102 if(index <= s.length() - 1) {
103 return s.charAt(index++);
104 } else {
105 return '\0';
106 }
107 }
108
109 public char lookahead() {
110 if(index <= s.length() - 1) {
111 return s.charAt(index);
112 } else {
113 return '\0';
114 }
115 }
116
117 public boolean eol() {
118 return index >= s.length();
119 }
120
121 }
122
123 /***
124 * @param line
125 * @return
126 */
127 private List parseLine(String line) {
128 List result = new ArrayList();
129 StringBuffer buf = new StringBuffer();
130 boolean incell = false;
131 CharacterIterator iterator = new CharacterIterator(line);
132 while(!iterator.eol()) {
133 char c = iterator.next();
134 switch(c) {
135 case '"': char next = iterator.lookahead();
136 if(next == '"') {
137 buf.append(iterator.next());
138 } else {
139 incell = !incell;
140 }
141 break;
142 case ',': if(!incell) {
143 result.add(buf.toString());
144 buf.setLength(0);
145 incell = false;
146 } else {
147 buf.append(',');
148 }
149 break;
150 default: buf.append(c);
151 }
152 }
153 result.add(buf.toString());
154 return result;
155 }
156
157 public void setEnsureColumnSize(boolean ensureColumnSize) {
158 this.ensureColumnSize = ensureColumnSize;
159 }
160 }