KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > it > businesslogic > ireport > connection > JRCsvDataSourceInspector


1 /*
2  * Copyright (C) 2005 - 2006 JasperSoft Corporation. All rights reserved.
3  * http://www.jaspersoft.com.
4  *
5  * Unless you have purchased a commercial license agreement from JasperSoft,
6  * the following license terms apply:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as published by
10  * the Free Software Foundation.
11  *
12  * This program is distributed WITHOUT ANY WARRANTY; and without the
13  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see http://www.gnu.org/licenses/gpl.txt
18  * or write to:
19  *
20  * Free Software Foundation, Inc.,
21  * 59 Temple Place - Suite 330,
22  * Boston, MA USA 02111-1307
23  *
24  *
25  *
26  *
27  * JRCsvDataSourceInspector.java
28  *
29  * Created on February 16, 2006, 1:27 PM
30  *
31  */

32
33 package it.businesslogic.ireport.connection;
34
35 import it.businesslogic.ireport.JRField;
36 import java.io.File JavaDoc;
37 import java.io.FileNotFoundException JavaDoc;
38 import java.io.FileReader JavaDoc;
39 import java.io.IOException JavaDoc;
40 import java.io.InputStream JavaDoc;
41 import java.io.InputStreamReader JavaDoc;
42 import java.io.Reader JavaDoc;
43 import java.math.BigDecimal JavaDoc;
44 import java.text.DateFormat JavaDoc;
45 import java.text.SimpleDateFormat JavaDoc;
46 import java.util.HashMap JavaDoc;
47 import java.util.Vector JavaDoc;
48 import net.sf.jasperreports.engine.JRException;
49 import net.sf.jasperreports.engine.JRRuntimeException;
50
51 /**
52  *
53  * @author gtoffoli
54  * This class derives from JRCsvDataSource and is used to read the field names.
55  */

56 public class JRCsvDataSourceInspector {
57     
58         private DateFormat JavaDoc dateFormat = new SimpleDateFormat JavaDoc();
59     private char fieldDelimiter = ',';
60     private String JavaDoc recordDelimiter = "\n";
61     private HashMap JavaDoc columnNames = new HashMap JavaDoc();
62
63     private Vector JavaDoc fields;
64     private Reader JavaDoc reader;
65     private char buffer[] = new char[1024];
66     private int position;
67     private int bufSize;
68
69     /**
70      * @param stream an input stream containing CSV data
71      */

72     public JRCsvDataSourceInspector(InputStream JavaDoc stream)
73     {
74         this(new InputStreamReader JavaDoc(stream));
75     }
76
77
78     /**
79      * Builds a datasource instance.
80      * @param file a file containing CSV data
81      */

82     public JRCsvDataSourceInspector(File JavaDoc file) throws FileNotFoundException JavaDoc
83     {
84         this(new FileReader JavaDoc(file));
85     }
86
87
88     /**
89      * Builds a datasource instance.
90      * @param reader a <tt>Reader</tt> instance, for reading the stream
91      */

92     public JRCsvDataSourceInspector(Reader JavaDoc reader)
93     {
94         this.reader = reader;
95     }
96
97
98     /**
99      * Parses a row of CSV data and extracts the fields it contains
100      */

101     private boolean parseRow() throws IOException JavaDoc
102     {
103         int pos = 0;
104         int startFieldPos = 0;
105         boolean insideQuotes = false;
106         boolean hadQuotes = false;
107         boolean misplacedQuote = false;
108         char c;
109         fields = new Vector JavaDoc();
110
111         String JavaDoc row = getRow();
112         if (row == null || row.length() == 0)
113             return false;
114
115         while (pos < row.length()) {
116             c = row.charAt(pos);
117
118             if (c == '"') {
119                 // already inside a text containing quotes
120
if (!insideQuotes) {
121                     if (!hadQuotes) {
122                         insideQuotes = true;
123                         hadQuotes = true;
124                     }
125                     else // the field contains a bad string, like "fo"o", instead of "fo""o"
126
misplacedQuote = true;
127                 }
128                 // found a quote when already inside quotes, expecting two consecutive quotes, otherwise it means
129
// it's a closing quote
130
else {
131                     if (pos+1 < row.length() && row.charAt(pos+1) == '"')
132                         pos++;
133                     else
134                         insideQuotes = false;
135                 }
136             }
137             // field delimiter found, copy the field contents to the field array
138
if (c == fieldDelimiter && !insideQuotes) {
139                 String JavaDoc field = row.substring(startFieldPos, pos);
140                 // if an illegal quote was found, the entire field is considered illegal
141
if (misplacedQuote) {
142                     misplacedQuote = false;
143                     hadQuotes = false;
144                     field = "";
145                 }
146                 // if the field was between quotes, remove them and turn any escaped quotes inside the text into normal quotes
147
else if (hadQuotes) {
148                     field = field.trim();
149                     if (field.startsWith("\"") && field.endsWith("\"")) {
150                         field = field.substring(1, field.length() - 1);
151                         field = replaceAll(field, "\"\"", "\"");
152                     }
153                     else
154                         field = "";
155                     hadQuotes = false;
156                 }
157
158                 fields.add(field);
159                 startFieldPos = pos + 1;
160             }
161
162             pos++;
163             // if the record delimiter was found inside a quoted field, it is not an actual record delimiter,
164
// so another line should be read
165
if ((pos == row.length()) && insideQuotes) {
166                 row = row + recordDelimiter + getRow();
167             }
168         }
169
170         // end of row was reached, so the final characters form the last field in the record
171
String JavaDoc field = row.substring(startFieldPos, pos);
172         if (field == null || field.length() == 0)
173             return true;
174
175         if (misplacedQuote)
176             field = "";
177         else if (hadQuotes) {
178             field = field.trim();
179             if (field.startsWith("\"") && field.endsWith("\"")) {
180                 field = field.substring(1, field.length() - 1);
181                 field = replaceAll(field, "\"\"", "\"");
182             }
183             else
184                 field = "";
185         }
186         fields.add(field);
187
188         return true;
189     }
190
191
192     /**
193      * Reads a row from the stream. A row is a sequence of characters separated by the record delimiter.
194      */

195     private String JavaDoc getRow() throws IOException JavaDoc
196     {
197         StringBuffer JavaDoc row = new StringBuffer JavaDoc();
198         char c;
199
200         while (true) {
201             try {
202                 c = getChar();
203
204                 // searches for the first character of the record delimiter
205
if (c == recordDelimiter.charAt(0)) {
206                     int i;
207                     char[] temp = new char[recordDelimiter.length()];
208                     temp[0] = c;
209                     boolean isDelimiter = true;
210                     // checks if the following characters in the stream form the record delimiter
211
for (i = 1; i < recordDelimiter.length() && isDelimiter; i++) {
212                         temp[i] = getChar();
213                         if (temp[i] != recordDelimiter.charAt(i))
214                             isDelimiter = false;
215                     }
216
217                     if (isDelimiter)
218                         return row.toString();
219
220                     row.append(temp, 0, i);
221                 }
222
223                 row.append(c);
224             } catch (JRException e) {
225                 return row.toString();
226             }
227
228         } // end while
229
}
230
231
232     /**
233      * Reads a character from the stream.
234      * @throws IOException if any I/O error occurs
235      * @throws JRException if end of stream has been reached
236      */

237     private char getChar() throws IOException JavaDoc, JRException
238     {
239         // end of buffer, fill a new buffer
240
if (position + 1 > bufSize) {
241             bufSize = reader.read(buffer);
242             position = 0;
243             if (bufSize == -1)
244                 throw new JRException("No more chars");
245         }
246
247         return buffer[position++];
248     }
249
250
251     /**
252      * Gets the date format that will be used to parse date fields
253      */

254     public DateFormat JavaDoc getDateFormat()
255     {
256         return dateFormat;
257     }
258
259
260     /**
261      * Sets the desired date format to be used for parsing date fields
262      */

263     public void setDateFormat(DateFormat JavaDoc dateFormat)
264     {
265         this.dateFormat = dateFormat;
266     }
267
268
269     /**
270      * Returns the field delimiter character.
271      */

272     public char getFieldDelimiter()
273     {
274         return fieldDelimiter;
275     }
276
277
278     /**
279      * Sets the field delimiter character. The default is comma. If characters such as comma or quotes are specified,
280      * the results can be unpredictable.
281      * @param fieldDelimiter
282      */

283     public void setFieldDelimiter(char fieldDelimiter)
284     {
285         this.fieldDelimiter = fieldDelimiter;
286     }
287
288
289     /**
290      * Returns the record delimiter string.
291      */

292     public String JavaDoc getRecordDelimiter()
293     {
294         return recordDelimiter;
295     }
296
297
298     /**
299      * Sets the record delimiter string. The default is line feed (\n).
300      * @param recordDelimiter
301      */

302     public void setRecordDelimiter(String JavaDoc recordDelimiter)
303     {
304         this.recordDelimiter = recordDelimiter;
305     }
306
307
308     /**
309      * Specifies an array of strings representing column names matching field names in the report template
310      */

311     public void setColumnNames(String JavaDoc[] columnNames)
312     {
313                 this.columnNames.clear();
314         for (int i = 0; i < columnNames.length; i++)
315             this.columnNames.put(columnNames[i], new Integer JavaDoc(i));
316     }
317
318         public Vector JavaDoc getColumnNames() throws java.io.IOException JavaDoc
319         {
320             parseRow();
321             return fields;
322         }
323
324     private String JavaDoc replaceAll(String JavaDoc string, String JavaDoc substring, String JavaDoc replacement)
325     {
326         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
327         int index = string.indexOf(substring);
328         int oldIndex = 0;
329         while (index >= 0) {
330             result.append(string.substring(oldIndex, index));
331             result.append(replacement);
332             index += substring.length();
333             oldIndex = index;
334
335             index = string.indexOf(substring, index);
336         }
337
338         if (oldIndex < string.length())
339             result.append(string.substring(oldIndex, string.length()));
340
341         return result.toString();
342     }
343     
344     
345 }
346
Popular Tags