View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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 }