Coverage report

  %line %branch
com.workingdogs.village.DataSet
0% 
0% 

 1  
 package com.workingdogs.village;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.ByteArrayOutputStream;
 23  
 import java.io.PrintWriter;
 24  
 
 25  
 import java.sql.Connection;
 26  
 import java.sql.ResultSet;
 27  
 import java.sql.SQLException;
 28  
 import java.sql.Statement;
 29  
 
 30  
 import java.util.Vector;
 31  
 
 32  
 /**
 33  
  * The DataSet represents a table in the database. It is extended by <a href="QueryDataSet.html">QueryDataSet</a> and <a
 34  
  * href="TableDataSet.html">TableDataSet</a> and should not be used directly. A DataSet contains a <a
 35  
  * href="Schema.html">Schema</a> and potentially a collection of <a href="Record.html">Records</a>.
 36  
  *
 37  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 38  
  * @version $Revision: 568 $
 39  
  */
 40  
 public abstract class DataSet
 41  
 {
 42  
     /** indicates that all records should be retrieved during a fetch */
 43  
     protected static final int ALL_RECORDS = -1;
 44  
 
 45  
     /** this DataSet's schema object */
 46  
     protected Schema schema;
 47  
 
 48  
     /** this DataSet's collection of Record objects */
 49  0
     protected Vector records = null;
 50  
 
 51  
     /** this DataSet's connection object */
 52  
     protected Connection conn;
 53  
 
 54  
     /** have all records been retrieved with the fetchRecords? */
 55  0
     private boolean allRecordsRetrieved = false;
 56  
 
 57  
     /** number of records retrieved */
 58  0
     private int recordRetrievedCount = 0;
 59  
 
 60  
     /** number of records that were last fetched */
 61  0
     private int lastFetchSize = 0;
 62  
 
 63  
     /** the columns in the SELECT statement for this DataSet */
 64  
     private String columns;
 65  
 
 66  
     /** the select string that was used to build this DataSet */
 67  
     protected StringBuffer selectString;
 68  
 
 69  
     /** the KeyDef for this DataSet */
 70  
     private KeyDef keyDefValue;
 71  
 
 72  
     /** the result set for this DataSet */
 73  
     protected ResultSet resultSet;
 74  
 
 75  
     /** the Statement for this DataSet */
 76  
     protected Statement stmt;
 77  
 
 78  
     /**
 79  
      * Private, not used
 80  
      *
 81  
      * @exception DataSetException
 82  
      * @exception SQLException
 83  
      */
 84  
     public DataSet()
 85  
             throws DataSetException, SQLException
 86  0
     {
 87  0
     }
 88  
 
 89  
     /**
 90  
      * Create a new DataSet with a connection and a Table name
 91  
      *
 92  
      * @param conn
 93  
      * @param tableName
 94  
      *
 95  
      * @exception DataSetException
 96  
      * @exception SQLException
 97  
      */
 98  
     DataSet(Connection conn, String tableName)
 99  
             throws DataSetException, SQLException
 100  0
     {
 101  0
         this.conn = conn;
 102  0
         this.columns = "*";
 103  0
         this.schema = new Schema().schema(conn, tableName);
 104  0
     }
 105  
 
 106  
     /**
 107  
      * Create a new DataSet with a connection, schema and KeyDef
 108  
      *
 109  
      * @param conn
 110  
      * @param schema
 111  
      * @param keydef
 112  
      *
 113  
      * @exception DataSetException
 114  
      * @exception SQLException
 115  
      */
 116  
     DataSet(Connection conn, Schema schema, KeyDef keydef)
 117  
             throws DataSetException, SQLException
 118  0
     {
 119  0
         if (conn == null)
 120  
         {
 121  0
             throw new SQLException("Database connection could not be established!");
 122  
         }
 123  0
         else if (schema == null)
 124  
         {
 125  0
             throw new DataSetException("You need to specify a valid schema!");
 126  
         }
 127  0
         else if (keydef == null)
 128  
         {
 129  0
             throw new DataSetException("You need to specify a valid KeyDef!");
 130  
         }
 131  
 
 132  0
         this.conn = conn;
 133  0
         this.schema = schema;
 134  0
         this.columns = "*";
 135  
 
 136  0
         this.keyDefValue = keydef;
 137  0
     }
 138  
 
 139  
     /**
 140  
      * Create a new DataSet with a connection, tablename and KeyDef
 141  
      *
 142  
      * @param conn
 143  
      * @param tableName
 144  
      * @param keydef
 145  
      *
 146  
      * @exception SQLException
 147  
      * @exception DataSetException
 148  
      */
 149  
     DataSet(Connection conn, String tableName, KeyDef keydef)
 150  
             throws SQLException, DataSetException
 151  0
     {
 152  0
         this.conn = conn;
 153  0
         this.keyDefValue = keydef;
 154  0
         this.columns = "*";
 155  0
         this.schema = new Schema().schema(conn, tableName);
 156  0
     }
 157  
 
 158  
     /**
 159  
      * Create a new DataSet with a connection, tablename and list of columns
 160  
      *
 161  
      * @param conn
 162  
      * @param tableName
 163  
      * @param columns
 164  
      *
 165  
      * @exception SQLException
 166  
      * @exception DataSetException
 167  
      */
 168  
     DataSet(Connection conn, String tableName, String columns)
 169  
             throws SQLException, DataSetException
 170  0
     {
 171  0
         this.conn = conn;
 172  0
         this.columns = columns;
 173  0
         this.schema = new Schema().schema(conn, tableName, columns);
 174  0
     }
 175  
 
 176  
     /**
 177  
      * Create a new DataSet with a connection, tableName, columns and a KeyDef
 178  
      *
 179  
      * @param conn
 180  
      * @param tableName
 181  
      * @param columns
 182  
      * @param keyDef
 183  
      *
 184  
      * @exception SQLException
 185  
      * @exception DataSetException
 186  
      */
 187  
     DataSet(Connection conn, String tableName, String columns, KeyDef keyDef)
 188  
             throws SQLException, DataSetException
 189  0
     {
 190  0
         this.conn = conn;
 191  0
         this.columns = columns;
 192  0
         this.keyDefValue = keyDef;
 193  0
         this.schema = new Schema().schema(conn, tableName, columns);
 194  0
     }
 195  
 
 196  
     /**
 197  
      * Gets the ResultSet for this DataSet
 198  
      *
 199  
      * @return the result set for this DataSet
 200  
      *
 201  
      * @exception SQLException
 202  
      * @exception DataSetException
 203  
      */
 204  
     public ResultSet resultSet()
 205  
             throws SQLException, DataSetException
 206  
     {
 207  0
         if (this.resultSet == null)
 208  
         {
 209  0
             throw new DataSetException("ResultSet is null.");
 210  
         }
 211  
 
 212  0
         return this.resultSet;
 213  
     }
 214  
 
 215  
     /**
 216  
      * Calls addRecord(DataSet)
 217  
      *
 218  
      * @return the added record
 219  
      *
 220  
      * @exception DataSetException
 221  
      * @exception SQLException
 222  
      */
 223  
     public Record addRecord()
 224  
             throws DataSetException, SQLException
 225  
     {
 226  0
         return addRecord(this);
 227  
     }
 228  
 
 229  
     /**
 230  
      * Creates a new Record within this DataSet
 231  
      *
 232  
      * @param ds
 233  
      *
 234  
      * @return the added record
 235  
      *
 236  
      * @exception DataSetException
 237  
      * @exception SQLException
 238  
      */
 239  
     public Record addRecord(DataSet ds)
 240  
             throws DataSetException, SQLException
 241  
     {
 242  0
         if (ds instanceof QueryDataSet)
 243  
         {
 244  0
             throw new DataSetException("You cannot add records to a QueryDataSet.");
 245  
         }
 246  
 
 247  0
         if (records == null)
 248  
         {
 249  0
             records = new Vector(10);
 250  
         }
 251  
 
 252  0
         Record rec = new Record(ds, true);
 253  0
         rec.markForInsert();
 254  0
         records.addElement(rec);
 255  
 
 256  0
         return rec;
 257  
     }
 258  
 
 259  
     /**
 260  
      * Check if all the records have been retrieve
 261  
      *
 262  
      * @return true if all records have been retrieved
 263  
      */
 264  
     public boolean allRecordsRetrieved()
 265  
     {
 266  0
         return this.allRecordsRetrieved;
 267  
     }
 268  
 
 269  
     /**
 270  
      * Set all records retrieved
 271  
      *
 272  
      * @param set TODO: DOCUMENT ME!
 273  
      */
 274  
     void setAllRecordsRetrieved(boolean set)
 275  
     {
 276  0
         this.allRecordsRetrieved = set;
 277  0
     }
 278  
 
 279  
     /**
 280  
      * Remove a record from the DataSet's internal storage
 281  
      *
 282  
      * @param rec
 283  
      *
 284  
      * @return the record removed
 285  
      *
 286  
      * @exception DataSetException
 287  
      */
 288  
     public Record removeRecord(Record rec)
 289  
             throws DataSetException
 290  
     {
 291  0
         Record removeRec = null;
 292  
 
 293  
         try
 294  
         {
 295  0
             int loc = this.records.indexOf(rec);
 296  0
             removeRec = (Record) this.records.elementAt(loc);
 297  0
             this.records.removeElementAt(loc);
 298  
         }
 299  0
         catch (Exception e)
 300  
         {
 301  0
             throw new DataSetException("Record could not be removed!");
 302  0
         }
 303  
 
 304  0
         return removeRec;
 305  
     }
 306  
 
 307  
     /**
 308  
      * Remove all records from the DataSet and nulls those records out and close() the DataSet.
 309  
      *
 310  
      * @return an instance of myself
 311  
      */
 312  
     public DataSet clearRecords()
 313  
     {
 314  0
         this.records.removeAllElements();
 315  0
         this.records = null;
 316  
 
 317  0
         return this;
 318  
     }
 319  
 
 320  
     /**
 321  
      * Removes the records from the DataSet, but does not null the records out
 322  
      *
 323  
      * @return an instance of myself
 324  
      */
 325  
     public DataSet releaseRecords()
 326  
     {
 327  0
         this.records = null;
 328  0
         this.recordRetrievedCount = 0;
 329  0
         this.lastFetchSize = 0;
 330  0
         setAllRecordsRetrieved(false);
 331  
 
 332  0
         return this;
 333  
     }
 334  
 
 335  
     /**
 336  
      * Releases the records, closes the ResultSet and the Statement, and nulls the Schema and Connection references.
 337  
      *
 338  
      * @exception SQLException
 339  
      * @exception DataSetException
 340  
      */
 341  
     public void close()
 342  
             throws SQLException, DataSetException
 343  
     {
 344  0
         releaseRecords();
 345  0
         this.schema = null;
 346  
 
 347  0
         if ((this.resultSet != null) && !(class="keyword">this instanceof QueryDataSet))
 348  
         {
 349  0
             resultSet().close();
 350  
         }
 351  
 
 352  0
         this.resultSet = null;
 353  
 
 354  0
         if (this.stmt != null)
 355  
         {
 356  0
             this.stmt.close();
 357  
         }
 358  
 
 359  0
         this.conn = null;
 360  0
     }
 361  
 
 362  
     /**
 363  
      * Essentially the same as releaseRecords, but it won't work on a QueryDataSet that has been created with a ResultSet
 364  
      *
 365  
      * @return an instance of myself
 366  
      *
 367  
      * @exception DataSetException
 368  
      * @exception SQLException
 369  
      */
 370  
     public DataSet reset()
 371  
             throws DataSetException, SQLException
 372  
     {
 373  0
         if (!((resultSet() != null) && (this instanceof QueryDataSet)))
 374  
         {
 375  0
             return releaseRecords();
 376  
         }
 377  
         else
 378  
         {
 379  0
             throw new DataSetException("You cannot call reset() on a QueryDataSet.");
 380  
         }
 381  
     }
 382  
 
 383  
     /**
 384  
      * Gets the current database connection
 385  
      *
 386  
      * @return a database connection
 387  
      *
 388  
      * @exception SQLException
 389  
      */
 390  
     public Connection connection()
 391  
             throws SQLException
 392  
     {
 393  0
         return this.conn;
 394  
     }
 395  
 
 396  
     /**
 397  
      * Gets the Schema for this DataSet
 398  
      *
 399  
      * @return the Schema for this DataSet
 400  
      */
 401  
     public Schema schema()
 402  
     {
 403  0
         return this.schema;
 404  
     }
 405  
 
 406  
     /**
 407  
      * Get Record at 0 based index position
 408  
      *
 409  
      * @param pos
 410  
      *
 411  
      * @return an instance of the found Record
 412  
      *
 413  
      * @exception DataSetException
 414  
      */
 415  
     public Record getRecord(int pos)
 416  
             throws DataSetException
 417  
     {
 418  0
         if (containsRecord(pos))
 419  
         {
 420  0
             Record rec = (Record) this.records.elementAt(pos);
 421  
 
 422  0
             if (this instanceof TableDataSet)
 423  
             {
 424  0
                 rec.markForUpdate();
 425  
             }
 426  
 
 427  0
             recordRetrievedCount++;
 428  
 
 429  0
             return rec;
 430  
         }
 431  
 
 432  0
         throw new DataSetException("Record not found at index: " + pos);
 433  
     }
 434  
 
 435  
     /**
 436  
      * Find Record at 0 based index position. This is an internal alternative to getRecord which tries to be smart about the type
 437  
      * of record it is.
 438  
      *
 439  
      * @param pos
 440  
      *
 441  
      * @return an instance of the found Record
 442  
      *
 443  
      * @exception DataSetException
 444  
      */
 445  
     Record findRecord(int pos)
 446  
             throws DataSetException
 447  
     {
 448  0
         if (containsRecord(pos))
 449  
         {
 450  0
             return (Record) this.records.elementAt(pos);
 451  
         }
 452  
 
 453  0
         throw new DataSetException("Record not found at index: " + pos);
 454  
     }
 455  
 
 456  
     /**
 457  
      * Check to see if the DataSet contains a Record at 0 based position
 458  
      *
 459  
      * @param pos
 460  
      *
 461  
      * @return true if record exists
 462  
      */
 463  
     public boolean containsRecord(int pos)
 464  
     {
 465  
         try
 466  
         {
 467  0
             if (this.records.elementAt(pos) != null)
 468  
             {
 469  0
                 return true;
 470  
             }
 471  
         }
 472  0
         catch (Exception e)
 473  
         {
 474  0
             return false;
 475  0
         }
 476  
 
 477  0
         return false;
 478  
     }
 479  
 
 480  
     /**
 481  
      * Causes the DataSet to hit the database and fetch all the records.
 482  
      *
 483  
      * @return an instance of myself
 484  
      *
 485  
      * @exception SQLException
 486  
      * @exception DataSetException
 487  
      */
 488  
     public DataSet fetchRecords()
 489  
             throws SQLException, DataSetException
 490  
     {
 491  0
         return fetchRecords(ALL_RECORDS);
 492  
     }
 493  
 
 494  
     /**
 495  
      * Causes the DataSet to hit the database and fetch max records.
 496  
      *
 497  
      * @param max
 498  
      *
 499  
      * @return an instance of myself
 500  
      *
 501  
      * @exception SQLException
 502  
      * @exception DataSetException
 503  
      */
 504  
     public DataSet fetchRecords(int max)
 505  
             throws SQLException, DataSetException
 506  
     {
 507  0
         return fetchRecords(0, max);
 508  
     }
 509  
 
 510  
     /**
 511  
      * Causes the DataSet to hit the database and fetch max records, starting at start. Record count begins at 0.
 512  
      *
 513  
      * @param start
 514  
      * @param max
 515  
      *
 516  
      * @return an instance of myself
 517  
      *
 518  
      * @exception SQLException
 519  
      * @exception DataSetException
 520  
      */
 521  
     public DataSet fetchRecords(int start, class="keyword">int max)
 522  
             throws SQLException, DataSetException
 523  
     {
 524  0
         if (max == 0)
 525  
         {
 526  0
             throw new DataSetException("Max is 1 based and must be greater than 0!");
 527  
         }
 528  0
         else if ((lastFetchSize() > 0) && (this.records != null))
 529  
         {
 530  0
             throw new DataSetException("You must call DataSet.clearRecords() before executing DataSet.fetchRecords() again!");
 531  
         }
 532  
 
 533  0
         if (selectString == null)
 534  
         {
 535  0
             selectString = new StringBuffer(256);
 536  0
             selectString.append("SELECT ");
 537  0
             selectString.append(schema().attributes());
 538  0
             selectString.append(" FROM ");
 539  0
             selectString.append(schema().tableName());
 540  
         }
 541  
 
 542  
         try
 543  
         {
 544  0
             if ((stmt == null) && (this.resultSet == class="keyword">null))
 545  
             {
 546  0
                 stmt = connection().createStatement();
 547  0
                 this.resultSet = stmt.executeQuery(selectString.toString());
 548  
             }
 549  
 
 550  0
             if (this.resultSet != null)
 551  
             {
 552  0
                 if ((this.records == null) && (max > 0))
 553  
                 {
 554  0
                     this.records = new Vector(max);
 555  
                 }
 556  
                 else
 557  
                 {
 558  0
                     this.records = new Vector();
 559  
                 }
 560  
 
 561  0
                 int startCounter = 0;
 562  0
                 int fetchCount = 0;
 563  
 
 564  0
                 while (!allRecordsRetrieved())
 565  
                 {
 566  0
                     if (fetchCount == max)
 567  
                     {
 568  0
                         break;
 569  
                     }
 570  
 
 571  0
                     if (this.resultSet.next())
 572  
                     {
 573  0
                         if (startCounter >= start)
 574  
                         {
 575  0
                             Record rec = new Record(this);
 576  0
                             records.addElement(rec);
 577  0
                             fetchCount++;
 578  
                         }
 579  
                         else
 580  
                         {
 581  0
                             startCounter++;
 582  
                         }
 583  
                     }
 584  
                     else
 585  
                     {
 586  0
                         setAllRecordsRetrieved(true);
 587  
 
 588  0
                         break;
 589  
                     }
 590  
                 }
 591  
 
 592  0
                 lastFetchSize = fetchCount;
 593  
             }
 594  
         }
 595  0
         catch (SQLException e)
 596  
         {
 597  0
             if (stmt != null)
 598  
             {
 599  0
                 stmt.close();
 600  
             }
 601  
 
 602  0
             throw new SQLException(e.getMessage());
 603  0
         }
 604  
 
 605  0
         return this;
 606  
     }
 607  
 
 608  
     /**
 609  
      * The number of records that were fetched with the last fetchRecords.
 610  
      *
 611  
      * @return int
 612  
      */
 613  
     public int lastFetchSize()
 614  
     {
 615  0
         return lastFetchSize;
 616  
     }
 617  
 
 618  
     /**
 619  
      * gets the KeyDef object for this DataSet
 620  
      *
 621  
      * @return the keydef for this DataSet, this value can be null
 622  
      */
 623  
     public KeyDef keydef()
 624  
     {
 625  0
         return this.keyDefValue;
 626  
     }
 627  
 
 628  
     /**
 629  
      * This returns a represention of this DataSet
 630  
      *
 631  
      * @return TODO: DOCUMENT ME!
 632  
      */
 633  
     public String toString()
 634  
     {
 635  
         try
 636  
         {
 637  0
             ByteArrayOutputStream bout = new ByteArrayOutputStream();
 638  0
             PrintWriter out = new PrintWriter(bout);
 639  
 
 640  0
             if (schema != null)
 641  
             {
 642  0
                 out.println(schema.toString());
 643  
             }
 644  
 
 645  0
             for (int i = 0; i < size(); i++)
 646  
             {
 647  0
                 out.println(findRecord(i));
 648  
             }
 649  
 
 650  0
             out.flush();
 651  
 
 652  0
             return bout.toString();
 653  
         }
 654  0
         catch (DataSetException e)
 655  
         {
 656  0
             return "{}";
 657  
         }
 658  
     }
 659  
 
 660  
     /**
 661  
      * Gets the tableName defined in the schema
 662  
      *
 663  
      * @return string
 664  
      *
 665  
      * @throws DataSetException TODO: DOCUMENT ME!
 666  
      */
 667  
     public String tableName()
 668  
             throws DataSetException
 669  
     {
 670  0
         return schema().tableName();
 671  
     }
 672  
 
 673  
     /**
 674  
      * Calculates the maxColumnWidths for the column in a DataSet I really don't know what this is used for so it isn't
 675  
      * implemented.
 676  
      *
 677  
      * @param with_heading
 678  
      *
 679  
      * @return int
 680  
      *
 681  
      * @exception DataSetException
 682  
      * @exception SQLException
 683  
      */
 684  
     public int [] maxColumnWidths(boolean with_heading)
 685  
             throws DataSetException, SQLException
 686  
     {
 687  0
         if (schema() == null)
 688  
         {
 689  0
             throw new DataSetException("Schema is null!");
 690  
         }
 691  
 
 692  0
         throw new DataSetException("Not yet implemented!");
 693  
     }
 694  
 
 695  
     /**
 696  
      * Classes extending this class must implement this method.
 697  
      *
 698  
      * @return the select string
 699  
      *
 700  
      * @throws DataSetException TODO: DOCUMENT ME!
 701  
      */
 702  
     public abstract String getSelectString()
 703  
             throws DataSetException;
 704  
 
 705  
     /**
 706  
      * Returns the columns attribute for the DataSet
 707  
      *
 708  
      * @return the columns attribute for the DataSet
 709  
      */
 710  
     String getColumns()
 711  
     {
 712  0
         return this.columns;
 713  
     }
 714  
 
 715  
     /**
 716  
      * Gets the number of Records in this DataSet. It is 0 based.
 717  
      *
 718  
      * @return number of Records in this DataSet
 719  
      */
 720  
     public int size()
 721  
     {
 722  0
         if (this.records == null)
 723  
         {
 724  0
             return 0;
 725  
         }
 726  
 
 727  0
         return this.records.size();
 728  
     }
 729  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.