1 28 package net.sf.jasperreports.engine.data; 29 30 import java.io.BufferedReader ; 31 import java.io.File ; 32 import java.io.FileInputStream ; 33 import java.io.FileNotFoundException ; 34 import java.io.IOException ; 35 import java.io.InputStream ; 36 import java.io.InputStreamReader ; 37 import java.io.Reader ; 38 import java.io.UnsupportedEncodingException ; 39 import java.math.BigDecimal ; 40 import java.math.BigInteger ; 41 import java.text.DateFormat ; 42 import java.text.DecimalFormat ; 43 import java.text.NumberFormat ; 44 import java.text.SimpleDateFormat ; 45 import java.util.HashMap ; 46 import java.util.Vector ; 47 48 import net.sf.jasperreports.engine.JRDataSource; 49 import net.sf.jasperreports.engine.JRException; 50 import net.sf.jasperreports.engine.JRField; 51 import net.sf.jasperreports.engine.JRRuntimeException; 52 53 54 67 public class JRCsvDataSource implements JRDataSource 68 { 69 private DateFormat dateFormat = new SimpleDateFormat (); 70 private NumberFormat numberFormat = new DecimalFormat (); 71 private char fieldDelimiter = ','; 72 private String recordDelimiter = "\n"; 73 private HashMap columnNames = new HashMap (); 74 private boolean useFirstRowAsHeader; 75 76 private Vector fields; 77 private Reader reader; 78 private char buffer[] = new char[1024]; 79 private int position; 80 private int bufSize; 81 private boolean processingStarted; 82 83 84 88 public JRCsvDataSource(InputStream stream) 89 { 90 this(new BufferedReader (new InputStreamReader (stream))); 91 } 92 93 94 99 public JRCsvDataSource(InputStream stream, String charsetName) throws UnsupportedEncodingException 100 { 101 this(new BufferedReader (new InputStreamReader (stream, charsetName))); 102 } 103 104 105 109 public JRCsvDataSource(File file) throws FileNotFoundException 110 { 111 this(new FileInputStream (file)); 112 } 113 114 115 120 public JRCsvDataSource(File file, String charsetName) throws FileNotFoundException , UnsupportedEncodingException 121 { 122 this(new FileInputStream (file), charsetName); 123 } 124 125 126 130 public JRCsvDataSource(Reader reader) 131 { 132 this.reader = reader; 133 } 134 135 136 139 public boolean next() throws JRException 140 { 141 try { 142 if (!processingStarted) { 143 if (useFirstRowAsHeader) { 144 parseRow(); 145 for (int i = 0; i < fields.size(); i++) { 146 String name = (String ) fields.get(i); 147 this.columnNames.put(name, new Integer (i)); 148 } 149 } 150 processingStarted = true; 151 } 152 153 return parseRow(); 154 } catch (IOException e) { 155 throw new JRException(e); 156 } 157 } 158 159 160 163 public Object getFieldValue(JRField jrField) throws JRException 164 { 165 String fieldName = jrField.getName(); 166 167 Integer columnIndex = (Integer ) columnNames.get(fieldName); 168 if (columnIndex == null && fieldName.startsWith("COLUMN_")) { 169 columnIndex = Integer.valueOf(fieldName.substring(7)); 170 } 171 if (columnIndex == null) 172 throw new JRException("Unknown column name : " + fieldName); 173 174 if (fields.size() > columnIndex.intValue()) { 175 String fieldValue = (String ) fields.get(columnIndex.intValue()); 176 Class valueClass = jrField.getValueClass(); 177 178 if (valueClass.equals(String .class)) 179 return fieldValue; 180 181 fieldValue = fieldValue.trim(); 182 183 if (fieldValue.length() == 0) 184 return null; 185 186 try { 187 if (valueClass.equals(Boolean .class)) { 188 return fieldValue.equalsIgnoreCase("true") ? Boolean.TRUE : Boolean.FALSE; 189 } 190 else if (valueClass.equals(Byte .class)) { 191 return new Byte ((numberFormat.parse(fieldValue)).byteValue()); 192 } 193 else if (valueClass.equals(Integer .class)) { 194 return new Integer ((numberFormat.parse(fieldValue)).intValue()); 195 } 196 else if (valueClass.equals(Long .class)) { 197 return new Long ((numberFormat.parse(fieldValue)).longValue()); 198 } 199 else if (valueClass.equals(Short .class)) { 200 return new Short ((numberFormat.parse(fieldValue)).shortValue()); 201 } 202 else if (valueClass.equals(Double .class)) { 203 return new Double ((numberFormat.parse(fieldValue)).doubleValue()); 204 } 205 else if (valueClass.equals(Float .class)) { 206 return new Float ((numberFormat.parse(fieldValue)).floatValue()); 207 } 208 else if (valueClass.equals(BigDecimal .class)) { 209 return new BigDecimal ((numberFormat.parse(fieldValue)).toString()); 210 } 211 else if (valueClass.equals(BigInteger .class)) { 212 return new BigInteger (String.valueOf(numberFormat.parse(fieldValue).longValue())); 213 } 214 else if(valueClass.equals(java.lang.Number .class)) { 215 return numberFormat.parse(fieldValue); 216 } 217 else if (valueClass.equals(java.util.Date .class)) { 218 return dateFormat.parse(fieldValue); 219 } 220 else if (valueClass.equals(java.sql.Timestamp .class)) { 221 return new java.sql.Timestamp (dateFormat.parse(fieldValue).getTime()); 222 } 223 else if (valueClass.equals(java.sql.Time .class)) { 224 return new java.sql.Time (dateFormat.parse(fieldValue).getTime()); 225 } 226 else 227 throw new JRException("Field '" + jrField.getName() + "' is of class '" + valueClass.getName() + "' and can not be converted"); 228 } catch (Exception e) { 229 throw new JRException("Unable to get value for field '" + jrField.getName() + "' of class '" + valueClass.getName() + "'", e); 230 } 231 } 232 233 throw new JRException("Unknown column name : " + fieldName); 234 } 235 236 237 240 private boolean parseRow() throws IOException 241 { 242 int pos = 0; 243 int startFieldPos = 0; 244 boolean insideQuotes = false; 245 boolean hadQuotes = false; 246 boolean misplacedQuote = false; 247 char c; 248 fields = new Vector (); 249 250 String row = getRow(); 251 if (row == null || row.length() == 0) 252 return false; 253 254 while (pos < row.length()) { 255 c = row.charAt(pos); 256 257 if (c == '"') { 258 if (!insideQuotes) { 260 if (!hadQuotes) { 261 insideQuotes = true; 262 hadQuotes = true; 263 } 264 else misplacedQuote = true; 266 } 267 else { 270 if (pos+1 < row.length() && row.charAt(pos+1) == '"') 271 pos++; 272 else 273 insideQuotes = false; 274 } 275 } 276 if (c == fieldDelimiter && !insideQuotes) { 278 String field = row.substring(startFieldPos, pos); 279 if (misplacedQuote) { 281 misplacedQuote = false; 282 hadQuotes = false; 283 field = ""; 284 } 285 else if (hadQuotes) { 287 field = field.trim(); 288 if (field.startsWith("\"") && field.endsWith("\"")) { 289 field = field.substring(1, field.length() - 1); 290 field = replaceAll(field, "\"\"", "\""); 291 } 292 else 293 field = ""; 294 hadQuotes = false; 295 } 296 297 fields.add(field); 298 startFieldPos = pos + 1; 299 } 300 301 pos++; 302 if ((pos == row.length()) && insideQuotes) { 305 row = row + recordDelimiter + getRow(); 306 } 307 } 308 309 String field = row.substring(startFieldPos, pos); 311 if (field == null) 312 return true; 313 314 if (misplacedQuote) 315 field = ""; 316 else if (hadQuotes) { 317 field = field.trim(); 318 if (field.startsWith("\"") && field.endsWith("\"")) { 319 field = field.substring(1, field.length() - 1); 320 field = replaceAll(field, "\"\"", "\""); 321 } 322 else 323 field = ""; 324 } 325 fields.add(field); 326 327 return true; 328 } 329 330 331 334 private String getRow() throws IOException 335 { 336 StringBuffer row = new StringBuffer (); 337 char c; 338 339 while (true) { 340 try { 341 c = getChar(); 342 343 if (c == recordDelimiter.charAt(0)) { 345 int i; 346 char[] temp = new char[recordDelimiter.length()]; 347 temp[0] = c; 348 boolean isDelimiter = true; 349 for (i = 1; i < recordDelimiter.length() && isDelimiter; i++) { 351 temp[i] = getChar(); 352 if (temp[i] != recordDelimiter.charAt(i)) 353 isDelimiter = false; 354 } 355 356 if (isDelimiter) 357 return row.toString(); 358 359 row.append(temp, 0, i); 360 } 361 362 row.append(c); 363 } catch (JRException e) { 364 return row.toString(); 365 } 366 367 } } 369 370 371 376 private char getChar() throws IOException , JRException 377 { 378 if (position + 1 > bufSize) { 380 bufSize = reader.read(buffer); 381 position = 0; 382 if (bufSize == -1) 383 throw new JRException("No more chars"); 384 } 385 386 return buffer[position++]; 387 } 388 389 390 393 public DateFormat getDateFormat() 394 { 395 return dateFormat; 396 } 397 398 399 402 public void setDateFormat(DateFormat dateFormat) 403 { 404 if (processingStarted) 405 throw new JRRuntimeException("Cannot modify data source properties after data reading has started"); 406 this.dateFormat = dateFormat; 407 } 408 409 410 413 public char getFieldDelimiter() 414 { 415 return fieldDelimiter; 416 } 417 418 419 424 public void setFieldDelimiter(char fieldDelimiter) 425 { 426 if (processingStarted) 427 throw new JRRuntimeException("Cannot modify data source properties after data reading has started"); 428 this.fieldDelimiter = fieldDelimiter; 429 } 430 431 432 435 public String getRecordDelimiter() 436 { 437 return recordDelimiter; 438 } 439 440 441 445 public void setRecordDelimiter(String recordDelimiter) 446 { 447 if (processingStarted) 448 throw new JRRuntimeException("Cannot modify data source properties after data reading has started"); 449 this.recordDelimiter = recordDelimiter; 450 } 451 452 453 456 public void setColumnNames(String [] columnNames) 457 { 458 if (processingStarted) 459 throw new JRRuntimeException("Cannot modify data source properties after data reading has started"); 460 for (int i = 0; i < columnNames.length; i++) 461 this.columnNames.put(columnNames[i], new Integer (i)); 462 } 463 464 465 469 public void setUseFirstRowAsHeader(boolean useFirstRowAsHeader) 470 { 471 if (processingStarted) 472 throw new JRRuntimeException("Cannot modify data source properties after data reading has started"); 473 this.useFirstRowAsHeader = useFirstRowAsHeader; 474 } 475 476 477 480 public void close() 481 { 482 try 483 { 484 reader.close(); 485 } 486 catch(IOException e) 487 { 488 } 490 } 491 492 493 private String replaceAll(String string, String substring, String replacement) 494 { 495 StringBuffer result = new StringBuffer (); 496 int index = string.indexOf(substring); 497 int oldIndex = 0; 498 while (index >= 0) { 499 result.append(string.substring(oldIndex, index)); 500 result.append(replacement); 501 index += substring.length(); 502 oldIndex = index; 503 504 index = string.indexOf(substring, index); 505 } 506 507 if (oldIndex < string.length()) 508 result.append(string.substring(oldIndex, string.length())); 509 510 return result.toString(); 511 } 512 513 514 public NumberFormat getNumberFormat() { 515 return numberFormat; 516 } 517 518 519 public void setNumberFormat(NumberFormat numberFormat) { 520 this.numberFormat = numberFormat; 521 } 522 } 523 524 525 | Popular Tags |