1 71 72 package org.jfree.data.jdbc; 73 74 import java.sql.Connection ; 75 import java.sql.DriverManager ; 76 import java.sql.ResultSet ; 77 import java.sql.ResultSetMetaData ; 78 import java.sql.SQLException ; 79 import java.sql.Statement ; 80 import java.sql.Types ; 81 import java.util.ArrayList ; 82 import java.util.Date ; 83 84 import org.jfree.data.Range; 85 import org.jfree.data.RangeInfo; 86 import org.jfree.data.general.Dataset; 87 import org.jfree.data.xy.AbstractXYDataset; 88 import org.jfree.data.xy.TableXYDataset; 89 import org.jfree.data.xy.XYDataset; 90 import org.jfree.util.Log; 91 92 101 public class JDBCXYDataset extends AbstractXYDataset 102 implements XYDataset, 103 TableXYDataset, 104 RangeInfo { 105 106 107 private transient Connection connection; 108 109 110 private String [] columnNames = {}; 111 112 113 private ArrayList rows; 114 115 116 private double maxValue = 0.0; 117 118 119 private double minValue = 0.0; 120 121 122 private boolean isTimeSeries = false; 123 124 128 private JDBCXYDataset() { 129 this.rows = new ArrayList (); 130 } 131 132 144 public JDBCXYDataset(String url, 145 String driverName, 146 String user, 147 String password) 148 throws SQLException , ClassNotFoundException { 149 150 this(); 151 Class.forName(driverName); 152 this.connection = DriverManager.getConnection(url, user, password); 153 } 154 155 163 public JDBCXYDataset(Connection con) throws SQLException { 164 this(); 165 this.connection = con; 166 } 167 168 177 public JDBCXYDataset(Connection con, String query) throws SQLException { 178 this(con); 179 executeQuery(query); 180 } 181 182 188 public boolean isTimeSeries() { 189 return this.isTimeSeries; 190 } 191 192 198 public void setTimeSeries(boolean timeSeries) { 199 this.isTimeSeries = timeSeries; 200 } 201 202 214 public void executeQuery(String query) throws SQLException { 215 executeQuery(this.connection, query); 216 } 217 218 231 public void executeQuery(Connection con, String query) 232 throws SQLException { 233 234 if (con == null) { 235 throw new SQLException ( 236 "There is no database to execute the query." 237 ); 238 } 239 240 ResultSet resultSet = null; 241 Statement statement = null; 242 try { 243 statement = con.createStatement(); 244 resultSet = statement.executeQuery(query); 245 ResultSetMetaData metaData = resultSet.getMetaData(); 246 247 int numberOfColumns = metaData.getColumnCount(); 248 int numberOfValidColumns = 0; 249 int [] columnTypes = new int[numberOfColumns]; 250 for (int column = 0; column < numberOfColumns; column++) { 251 try { 252 int type = metaData.getColumnType(column + 1); 253 switch (type) { 254 255 case Types.NUMERIC: 256 case Types.REAL: 257 case Types.INTEGER: 258 case Types.DOUBLE: 259 case Types.FLOAT: 260 case Types.DECIMAL: 261 case Types.BIT: 262 case Types.DATE: 263 case Types.TIME: 264 case Types.TIMESTAMP: 265 case Types.BIGINT: 266 case Types.SMALLINT: 267 ++numberOfValidColumns; 268 columnTypes[column] = type; 269 break; 270 default: 271 Log.warn( 272 "Unable to load column " 273 + column + " (" + type + "," 274 + metaData.getColumnClassName(column + 1) 275 + ")" 276 ); 277 columnTypes[column] = Types.NULL; 278 break; 279 } 280 } 281 catch (SQLException e) { 282 columnTypes[column] = Types.NULL; 283 throw e; 284 } 285 } 286 287 288 if (numberOfValidColumns <= 1) { 289 throw new SQLException ( 290 "Not enough valid columns where generated by query." 291 ); 292 } 293 294 this.columnNames = new String [numberOfValidColumns - 1]; 296 int currentColumn = 0; 298 for (int column = 1; column < numberOfColumns; column++) { 299 if (columnTypes[column] != Types.NULL) { 300 this.columnNames[currentColumn] 301 = metaData.getColumnLabel(column + 1); 302 ++currentColumn; 303 } 304 } 305 306 if (this.rows != null) { 308 for (int column = 0; column < this.rows.size(); column++) { 309 ArrayList row = (ArrayList ) this.rows.get(column); 310 row.clear(); 311 } 312 this.rows.clear(); 313 } 314 315 switch (columnTypes[0]) { 317 case Types.DATE: 318 case Types.TIME: 319 case Types.TIMESTAMP: 320 this.isTimeSeries = true; 321 break; 322 default : 323 this.isTimeSeries = false; 324 break; 325 } 326 327 while (resultSet.next()) { 330 ArrayList newRow = new ArrayList (); 331 for (int column = 0; column < numberOfColumns; column++) { 332 Object xObject = resultSet.getObject(column + 1); 333 switch (columnTypes[column]) { 334 case Types.NUMERIC: 335 case Types.REAL: 336 case Types.INTEGER: 337 case Types.DOUBLE: 338 case Types.FLOAT: 339 case Types.DECIMAL: 340 case Types.BIGINT: 341 case Types.SMALLINT: 342 newRow.add(xObject); 343 break; 344 345 case Types.DATE: 346 case Types.TIME: 347 case Types.TIMESTAMP: 348 newRow.add(new Long (((Date ) xObject).getTime())); 349 break; 350 case Types.NULL: 351 break; 352 default: 353 System.err.println("Unknown data"); 354 columnTypes[column] = Types.NULL; 355 break; 356 } 357 } 358 this.rows.add(newRow); 359 } 360 361 if (this.rows.size() == 0) { 363 ArrayList newRow = new ArrayList (); 364 for (int column = 0; column < numberOfColumns; column++) { 365 if (columnTypes[column] != Types.NULL) { 366 newRow.add(new Integer (0)); 367 } 368 } 369 this.rows.add(newRow); 370 } 371 372 if (this.rows.size() < 1) { 374 this.maxValue = 0.0; 375 this.minValue = 0.0; 376 } 377 else { 378 ArrayList row = (ArrayList ) this.rows.get(0); 379 this.maxValue = Double.NEGATIVE_INFINITY; 380 this.minValue = Double.POSITIVE_INFINITY; 381 for (int rowNum = 0; rowNum < this.rows.size(); ++rowNum) { 382 row = (ArrayList ) this.rows.get(rowNum); 383 for (int column = 1; column < numberOfColumns; column++) { 384 Object testValue = row.get(column); 385 if (testValue != null) { 386 double test = ((Number ) testValue).doubleValue(); 387 388 if (test < this.minValue) { 389 this.minValue = test; 390 } 391 if (test > this.maxValue) { 392 this.maxValue = test; 393 } 394 } 395 } 396 } 397 } 398 399 fireDatasetChanged(); } 401 finally { 402 if (resultSet != null) { 403 try { 404 resultSet.close(); 405 } 406 catch (Exception e) { 407 } 409 } 410 if (statement != null) { 411 try { 412 statement.close(); 413 } 414 catch (Exception e) { 415 } 417 } 418 } 419 420 } 421 422 434 public Number getX(int seriesIndex, int itemIndex) { 435 ArrayList row = (ArrayList ) this.rows.get(itemIndex); 436 return (Number ) row.get(0); 437 } 438 439 449 public Number getY(int seriesIndex, int itemIndex) { 450 ArrayList row = (ArrayList ) this.rows.get(itemIndex); 451 return (Number ) row.get(seriesIndex + 1); 452 } 453 454 463 public int getItemCount(int seriesIndex) { 464 return this.rows.size(); 465 } 466 467 473 public int getItemCount() { 474 return getItemCount(0); 475 } 476 477 485 public int getSeriesCount() { 486 return this.columnNames.length; 487 } 488 489 499 public Comparable getSeriesKey(int seriesIndex) { 500 501 if ((seriesIndex < this.columnNames.length) 502 && (this.columnNames[seriesIndex] != null)) { 503 return this.columnNames[seriesIndex]; 504 } 505 else { 506 return ""; 507 } 508 509 } 510 511 520 public int getLegendItemCount() { 521 return getSeriesCount(); 522 } 523 524 533 public String [] getLegendItemLabels() { 534 return this.columnNames; 535 } 536 537 540 public void close() { 541 542 try { 543 this.connection.close(); 544 } 545 catch (Exception e) { 546 System.err.println("JdbcXYDataset: swallowing exception."); 547 } 548 549 } 550 551 559 public double getRangeLowerBound(boolean includeInterval) { 560 return this.minValue; 561 } 562 563 571 public double getRangeUpperBound(boolean includeInterval) { 572 return this.maxValue; 573 } 574 575 583 public Range getRangeBounds(boolean includeInterval) { 584 return new Range(this.minValue, this.maxValue); 585 } 586 587 } 588 | Popular Tags |