View Javadoc

1   /*
2   
3       Jameleon - An automation testing tool..
4       Copyright (C) 2003 Christian W. Hargraves (engrean@hotmail.com)
5       
6       This library is free software; you can redistribute it and/or
7       modify it under the terms of the GNU Lesser General Public
8       License as published by the Free Software Foundation; either
9       version 2.1 of the License, or (at your option) any later version.
10  
11      This library is distributed in the hope that it will be useful,
12      but WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14      Lesser General Public License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public
17      License along with this library; if not, write to the Free Software
18      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20  package net.sf.jameleon.data;
21  
22  import net.sf.jameleon.util.JameleonDefaultValues;
23  
24  import java.io.BufferedReader;
25  import java.io.InputStreamReader;
26  import java.io.IOException;
27  import java.io.FileInputStream;
28  import java.io.File;
29  import java.io.UnsupportedEncodingException;
30  
31  import java.util.ArrayList;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  
36  /***
37   * Am implementation of @{link DataDriver} for CSV Files.
38   * This implementation can accept different delimiters. The
39   * default delimiter is ','.
40   */
41  public class CsvDataDriver implements DataDriver{
42      protected File csvFile;
43      protected BufferedReader in;
44      protected final static char DEFAULT_DELIMETER = ',';
45      protected char delimiter = DEFAULT_DELIMETER;
46      protected String encoding = JameleonDefaultValues.FILE_CHARSET;
47      protected List keys;
48      protected String line;
49  
50      /***
51       * Default construtor. After calling this constructor,
52       * setFile() will need to be set.
53       */
54      public CsvDataDriver(){
55          csvFile = null;
56          in = null;
57          keys = new ArrayList();
58      }
59  
60      /***
61       * Sets the file to be read in to <code>csvFile</code>
62       * @param csvFile - the file to be used for parsing
63       */
64      public CsvDataDriver(File csvFile){
65          this();
66          this.csvFile = csvFile;
67      }
68  
69      /***
70       * Sets the file and the delimiter of the file to be read in
71       * @param csvFile - the file to be used for parsing
72       * @param delimiter -  the field delimiter of the csv file.
73       */
74      public CsvDataDriver(File csvFile, char delimiter){
75          this(csvFile);
76          this.delimiter = delimiter;
77      }
78  
79      /***
80       * Closes the handle to the data source
81       */
82      public void close() {
83          keys.clear();
84          if (in != null) {
85              try{
86                  in.close();
87              }catch(IOException ioe){}
88          }
89      }
90  
91      /***
92       * Opens the handle to the data source
93       * @throws IOException when the data source can not be found.
94       */
95      public void open() throws IOException {
96          if (csvFile != null) {
97              try{
98                  in = new BufferedReader(new InputStreamReader(new FileInputStream(csvFile), encoding));
99              }catch(UnsupportedEncodingException uee){
100                 throw new IOException(encoding + " is an unsupported encoding type");
101             }
102         }else{
103             throw new IOException("No file set to open");
104         }
105     }
106 
107     /***
108      * Gets the encoding of the csv file. Defaults to UTF-8
109      * @return the encoding of the csv file
110      */
111     public String getEncoding(){
112         return encoding;
113     }
114 
115     /***
116      * Sets the encoding of the csv file.
117      * @param encoding - the encoding of the csv file
118      */
119     public void setEncoding(String encoding){
120         this.encoding = encoding;
121     }
122 
123     /***
124      * Gets the CSV file used as a datasource.
125      * @return the CSV file used as a datasource.
126      */
127     public File getFile(){
128         return csvFile;
129     }
130 
131     /***
132      * Sets the CSV file used as a datasource.
133      * @param csvFile - the CSV file used as a datasource.
134      */
135     public void setFile(File csvFile){
136         this.csvFile = csvFile;
137     }
138 
139     /***
140      * Gets the next row from the data source
141      * @return a key-value HashMap representing the data row or null if
142      * no data row is available
143      * @throws IllegalStateException if there are more values than keys
144      */
145     public Map getNextRow() {
146         Map vars = null;
147         try{
148             if (line == null) {
149                 readLine();
150             }
151             if (line != null) {
152                 vars = new HashMap();
153                 List values = parseLine(line, false);
154                 if (values.size() > keys.size()) {
155                     throw new IllegalStateException(csvFile.getPath() + " has more values than keys!");
156                 }
157                 String tmp = null;
158                 for (int index = 0; index < values.size(); index++) {
159                     tmp = (String)values.get(index);
160                     if (tmp == null || tmp.length() == 0) {
161                         tmp = null;
162                     }
163                     vars.put(keys.get(index),tmp);
164                 }
165             }
166         }finally{
167             line = null;
168         }
169         return vars;
170     }
171 
172     /***
173      * Gets the field delimiter for the csv file
174      * @return the field delimiter for the csv file
175      */
176     public char getDelimiter(){
177         return delimiter;
178     }
179 
180     /***
181      * Sets the field delimiter for the csv file
182      * @param delimiter - the field delimiter for the csv file
183      */
184     public void setDelimiter(char delimiter){
185         this.delimiter = delimiter;
186     }
187 
188     /***
189      * Sets the key columns from the csv file
190      */
191     protected void setKeys(){
192         if (keys.size() == 0) {
193             getNextUcommentedLine();
194             if (line != null) {
195                 keys = parseLine(line, true);
196                 line = null;
197             }
198         }
199     }
200 
201     /***
202      * Tells whether the data source has another row
203      * @return true if the data source still has more rows
204      */
205     public boolean hasMoreRows() {
206         boolean moreRows = false;
207         if (line == null) {
208             readLine();
209         }
210         if (line != null) {
211             moreRows = true;
212         }
213         return moreRows;
214     }
215 
216     protected List parseLine(String line, boolean keysLine){
217 
218         List list = new ArrayList();
219         if (isLineCommented(line)) { return list; }
220 
221         String[] values = line.split( "//"+String.valueOf(delimiter), -1 );
222         for (int i = 0; i < values.length; i++) {
223             String value = values[i];
224             String trimmedValue = value.trim();
225             if ( trimmedValue.startsWith("\"") && trimmedValue.endsWith("\"") ) {
226                 list.add( trimmedValue.subSequence(1, trimmedValue.length()-1) );
227             } else {
228                 if (keysLine) {
229                     list.add(trimmedValue);
230                 } else {
231                     list.add(value);
232                 }
233             }
234         }
235 
236         return list;
237     }
238 
239     protected boolean isLineCommented(String line){
240         boolean commented = false;
241         if (line != null && line.startsWith("#")) {
242             commented = true;
243         }
244         return commented;
245     }
246 
247     protected void readLine(){
248         line = null;
249         setKeys();
250         getNextUcommentedLine();
251     }
252 
253     protected void getNextUcommentedLine(){
254         try{
255             String tempLine = null;
256             while (in != null && 
257                    in.ready() && 
258                    line == null &&
259                    (tempLine = new String(in.readLine().getBytes(encoding),encoding)) != null) {
260                 if (!isLineCommented(tempLine)) {
261                     line = tempLine;
262                 }
263             }
264         }catch(IOException ioe){
265             ioe.printStackTrace();
266         }
267     }
268 
269 }