Coverage report

  %line %branch
com.workingdogs.village.Record
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.math.BigDecimal;
 26  
 
 27  
 import java.sql.Connection;
 28  
 import java.sql.PreparedStatement;
 29  
 import java.sql.ResultSet;
 30  
 import java.sql.SQLException;
 31  
 
 32  
 /**
 33  
  * A Record represents a row in the database. It contains a collection of <a href="Value.html">Values</A> which are the individual
 34  
  * contents of each column in the row.
 35  
  *
 36  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 37  
  * @version $Revision: 568 $
 38  
  */
 39  
 public class Record
 40  
 {
 41  
     /** an array of Value objects, this is 1 based */
 42  
     private Value [] values;
 43  
 
 44  
     /** a 1 To 1 relationship between Values and whether they are clean or not */
 45  
     private boolean [] isClean;
 46  
 
 47  
     /** the parent DataSet for this Record */
 48  
     private DataSet parentDataSet;
 49  
 
 50  
     /** number of columns in this Record */
 51  
     private int numberOfColumns;
 52  
 
 53  
     /** this is the state of this record */
 54  0
     private int saveType = 0;
 55  
 
 56  
     /** a saved copy of the schema for this Record */
 57  
     private Schema schema;
 58  
 
 59  
     /**
 60  
      * This isn't used and doesn't do anything.
 61  
      */
 62  
     public Record()
 63  0
     {
 64  
         // don't do anything
 65  0
     }
 66  
 
 67  
     /**
 68  
      * Creates a new Record and sets the parent dataset to the passed in value. This method also creates the Value objects which
 69  
      * are associated with this Record.
 70  
      *
 71  
      * @param ds TODO: DOCUMENT ME!
 72  
      *
 73  
      * @throws DataSetException TODO: DOCUMENT ME!
 74  
      * @throws SQLException TODO: DOCUMENT ME!
 75  
      */
 76  
     public Record(DataSet ds)
 77  
             throws DataSetException, SQLException
 78  0
     {
 79  0
         setParentDataSet(ds);
 80  0
         initializeRecord();
 81  0
         createValues(dataset().resultSet());
 82  0
     }
 83  
 
 84  
     /**
 85  
      * This is a special case method for Record. This case is really only used when DataSet.addRecord() is called because we may
 86  
      * not have an existing ResultSet so there will not be any values in the Value objects that are created. Passing null to
 87  
      * createValues forces the Value object to be created, but no processing to be done within the Value object constructor.
 88  
      *
 89  
      * <P>
 90  
      * This method is a package method only because it is really not useful outside of the package.
 91  
      * </p>
 92  
      *
 93  
      * @param ds the dataset
 94  
      * @param addRecord whether or not this method is being called from DataSet.addRecord()
 95  
      *
 96  
      * @throws DataSetException TODO: DOCUMENT ME!
 97  
      * @throws SQLException TODO: DOCUMENT ME!
 98  
      */
 99  
     Record(DataSet ds, boolean addRecord)
 100  
             throws DataSetException, SQLException
 101  0
     {
 102  0
         setParentDataSet(ds);
 103  0
         initializeRecord();
 104  0
         createValues(null);
 105  0
     }
 106  
 
 107  
     /**
 108  
      * Performs initialization for this Record.
 109  
      *
 110  
      * @throws DataSetException TODO: DOCUMENT ME!
 111  
      */
 112  
     private void initializeRecord()
 113  
             throws DataSetException
 114  
     {
 115  0
         this.schema = dataset().schema();
 116  0
         this.numberOfColumns = schema.numberOfColumns();
 117  0
         this.values = new Value[size() + 1];
 118  0
         this.isClean = new boolean[size() + 1];
 119  0
         setSaveType(Enums.UNKNOWN);
 120  
 
 121  0
         for (int i = 1; i <= size(); i++)
 122  
         {
 123  0
             markValueClean(i);
 124  0
             this.values[i] = null;
 125  
         }
 126  0
     }
 127  
 
 128  
     /**
 129  
      * Creates the value objects for this Record. It is 1 based
 130  
      *
 131  
      * @param rs TODO: DOCUMENT ME!
 132  
      *
 133  
      * @exception DataSetException
 134  
      * @exception SQLException
 135  
      */
 136  
     private void createValues(ResultSet rs)
 137  
             throws DataSetException, SQLException
 138  
     {
 139  0
         for (int i = 1; i <= size(); i++)
 140  
         {
 141  0
             Value val = new Value(rs, i, schema().column(i).typeEnum());
 142  0
             this.values[i] = val;
 143  
         }
 144  0
     }
 145  
 
 146  
     /**
 147  
      * Saves the data in this Record to the database. Uses the parent dataset's connection.
 148  
      *
 149  
      * @return 1 if the save completed. 0 otherwise.
 150  
      *
 151  
      * @throws DataSetException TODO: DOCUMENT ME!
 152  
      * @throws SQLException TODO: DOCUMENT ME!
 153  
      */
 154  
     public int save()
 155  
             throws DataSetException, SQLException
 156  
     {
 157  0
         return save(dataset().connection());
 158  
     }
 159  
 
 160  
     /**
 161  
      * Saves the data in this Record to the database. Uses the connection passed into it.
 162  
      *
 163  
      * @param connection TODO: DOCUMENT ME!
 164  
      *
 165  
      * @return 1 if the save completed. 0 otherwise.
 166  
      *
 167  
      * @throws DataSetException TODO: DOCUMENT ME!
 168  
      * @throws SQLException TODO: DOCUMENT ME!
 169  
      */
 170  
     public int save(Connection connection)
 171  
             throws DataSetException, SQLException
 172  
     {
 173  0
         int returnValue = 0;
 174  
 
 175  0
         if (dataset() instanceof QueryDataSet)
 176  
         {
 177  0
             throw new DataSetException("You cannot save a QueryDataSet. Please use a TableDataSet instead.");
 178  
         }
 179  
 
 180  0
         if (!needsToBeSaved())
 181  
         {
 182  0
             return class="keyword">returnValue;
 183  
         }
 184  
 
 185  0
         if (toBeSavedWithInsert())
 186  
         {
 187  0
             returnValue = saveWithInsert(connection);
 188  
         }
 189  0
         else if (toBeSavedWithUpdate())
 190  
         {
 191  0
             returnValue = saveWithUpdate(connection);
 192  
         }
 193  0
         else if (toBeSavedWithDelete())
 194  
         {
 195  0
             returnValue = saveWithDelete(connection);
 196  
         }
 197  
 
 198  0
         return class="keyword">returnValue;
 199  
     }
 200  
 
 201  
     /**
 202  
      * Saves the data in this Record to the database with an DELETE statement
 203  
      *
 204  
      * @param connection TODO: DOCUMENT ME!
 205  
      *
 206  
      * @return SQL DELETE statement
 207  
      *
 208  
      * @throws DataSetException TODO: DOCUMENT ME!
 209  
      * @throws SQLException TODO: DOCUMENT ME!
 210  
      */
 211  
     private int saveWithDelete(Connection connection)
 212  
             throws DataSetException, SQLException
 213  
     {
 214  0
         PreparedStatement stmt = null;
 215  
 
 216  
         try
 217  
         {
 218  0
             stmt = connection.prepareStatement(getSaveString());
 219  
 
 220  0
             int ps = 1;
 221  
 
 222  0
             for (int i = 1; i <= dataset().keydef().size(); i++)
 223  
             {
 224  0
                 Value val = getValue(dataset().keydef().getAttrib(i));
 225  
 
 226  0
                 val.setPreparedStatementValue(stmt, ps++);
 227  
             }
 228  
 
 229  0
             int ret = stmt.executeUpdate();
 230  
 
 231  
             // note that the actual deletion of the Record objects
 232  
             // from the TDS is now in the save() method of the TDS
 233  
             // instead of here. This fixes a bug where multiple
 234  
             // records would not be deleted properly because they
 235  
             // were being removed from here and the Records Vector
 236  
             // was getting out of sync with reality. So, just
 237  
             // mark them as needing to be removed here.
 238  0
             setSaveType(Enums.ZOMBIE);
 239  
 
 240  0
             if (ret > 1)
 241  
             {
 242  0
                 throw new SQLException("There were " + ret + " rows deleted with this records key value.");
 243  
             }
 244  
 
 245  0
             return ret;
 246  
         }
 247  0
         catch (SQLException e1)
 248  
         {
 249  0
             throw e1;
 250  
         }
 251  
         finally
 252  
         {
 253  0
             try
 254  
             {
 255  0
                 if (stmt != null)
 256  
                 {
 257  0
                     stmt.close();
 258  
                 }
 259  
             }
 260  0
             catch (SQLException e2)
 261  
             {
 262  0
                 throw e2;
 263  0
             }
 264  
         }
 265  
     }
 266  
 
 267  
     /**
 268  
      * Saves the data in this Record to the database with an UPDATE statement
 269  
      *
 270  
      * @param connection TODO: DOCUMENT ME!
 271  
      *
 272  
      * @return SQL UPDATE statement
 273  
      *
 274  
      * @throws DataSetException TODO: DOCUMENT ME!
 275  
      * @throws SQLException TODO: DOCUMENT ME!
 276  
      */
 277  
     private int saveWithUpdate(Connection connection)
 278  
             throws DataSetException, SQLException
 279  
     {
 280  0
         PreparedStatement stmt = null;
 281  
 
 282  
         try
 283  
         {
 284  0
             stmt = connection.prepareStatement(getSaveString());
 285  
 
 286  0
             int ps = 1;
 287  
 
 288  0
             for (int i = 1; i <= size(); i++)
 289  
             {
 290  0
                 Value val = getValue(i);
 291  
 
 292  0
                 if (!valueIsClean(i) && !schema().column(i).readOnly())
 293  
                 {
 294  0
                     val.setPreparedStatementValue(stmt, ps++);
 295  
                 }
 296  
             }
 297  
 
 298  0
             for (int i = 1; i <= dataset().keydef().size(); i++)
 299  
             {
 300  0
                 Value val = getValue(dataset().keydef().getAttrib(i));
 301  
 
 302  0
                 val.setPreparedStatementValue(stmt, ps++);
 303  
             }
 304  
 
 305  0
             int ret = stmt.executeUpdate();
 306  
 
 307  0
             if (((TableDataSet) dataset()).refreshOnSave())
 308  
             {
 309  0
                 refresh(dataset().connection());
 310  
             }
 311  
             else
 312  
             {
 313  
                 // Marks all of the values clean since they have now been saved
 314  0
                 markRecordClean();
 315  
             }
 316  
 
 317  0
             setSaveType(Enums.AFTERUPDATE);
 318  
 
 319  0
             if (ret > 1)
 320  
             {
 321  0
                 throw new SQLException("There were " + ret + " rows updated with this records key value.");
 322  
             }
 323  
 
 324  0
             return ret;
 325  
         }
 326  0
         catch (SQLException e1)
 327  
         {
 328  0
             throw e1;
 329  
         }
 330  
         finally
 331  
         {
 332  0
             try
 333  
             {
 334  0
                 if (stmt != null)
 335  
                 {
 336  0
                     stmt.close();
 337  
                 }
 338  
             }
 339  0
             catch (SQLException e2)
 340  
             {
 341  0
                 throw e2;
 342  0
             }
 343  
         }
 344  
     }
 345  
 
 346  
     /**
 347  
      * Saves the data in this Record to the database with an INSERT statement
 348  
      *
 349  
      * @param connection TODO: DOCUMENT ME!
 350  
      *
 351  
      * @return SQL INSERT statement
 352  
      *
 353  
      * @throws DataSetException TODO: DOCUMENT ME!
 354  
      * @throws SQLException TODO: DOCUMENT ME!
 355  
      */
 356  
     private int saveWithInsert(Connection connection)
 357  
             throws DataSetException, SQLException
 358  
     {
 359  0
         PreparedStatement stmt = null;
 360  
 
 361  
         try
 362  
         {
 363  0
             stmt = connection.prepareStatement(getSaveString());
 364  
 
 365  0
             int ps = 1;
 366  
 
 367  0
             for (int i = 1; i <= size(); i++)
 368  
             {
 369  0
                 Value val = getValue(i);
 370  
 
 371  0
                 if (!valueIsClean(i) && !schema().column(i).readOnly())
 372  
                 {
 373  0
                     val.setPreparedStatementValue(stmt, ps++);
 374  
                 }
 375  
             }
 376  
 
 377  0
             int ret = stmt.executeUpdate();
 378  
 
 379  0
             if (((TableDataSet) dataset()).refreshOnSave())
 380  
             {
 381  0
                 refresh(dataset().connection());
 382  
             }
 383  
             else
 384  
             {
 385  
                 // Marks all of the values clean since they have now been saved
 386  0
                 markRecordClean();
 387  
             }
 388  
 
 389  0
             setSaveType(Enums.AFTERINSERT);
 390  
 
 391  0
             if (ret > 1)
 392  
             {
 393  0
                 throw new SQLException("There were " + ret + " rows inserted with this records key value.");
 394  
             }
 395  
 
 396  0
             return ret;
 397  
         }
 398  0
         catch (SQLException e1)
 399  
         {
 400  0
             throw e1;
 401  
         }
 402  
         finally
 403  
         {
 404  0
             try
 405  
             {
 406  0
                 if (stmt != null)
 407  
                 {
 408  0
                     stmt.close();
 409  
                 }
 410  
             }
 411  0
             catch (SQLException e2)
 412  
             {
 413  0
                 throw e2;
 414  0
             }
 415  
         }
 416  
     }
 417  
 
 418  
     /**
 419  
      * Builds the SQL UPDATE statement for this Record
 420  
      *
 421  
      * @return SQL UPDATE statement
 422  
      *
 423  
      * @throws DataSetException TODO: DOCUMENT ME!
 424  
      */
 425  
     private String getUpdateSaveString()
 426  
             throws DataSetException
 427  
     {
 428  0
         KeyDef kd = dataset().keydef();
 429  
 
 430  0
         if ((kd == null) || (kd.size() == 0))
 431  
         {
 432  0
             throw new DataSetException(
 433  
                 "You must specify KeyDef attributes for this TableDataSet in order to create a Record for update.");
 434  
         }
 435  0
         else if (recordIsClean())
 436  
         {
 437  0
             throw new DataSetException("You must Record.setValue() on a column before doing an update.");
 438  
         }
 439  
 
 440  0
         StringBuffer iss1 = new StringBuffer(256);
 441  0
         StringBuffer iss2 = new StringBuffer(256);
 442  0
         boolean comma = false;
 443  
 
 444  0
         for (int i = 1; i <= size(); i++)
 445  
         {
 446  0
             if (!valueIsClean(i) && !schema().column(i).readOnly())
 447  
             {
 448  0
                 if (!comma)
 449  
                 {
 450  0
                     iss1.append(schema().column(i).name());
 451  0
                     iss1.append(" = ?");
 452  0
                     comma = true;
 453  
                 }
 454  
                 else
 455  
                 {
 456  0
                     iss1.append(", ");
 457  0
                     iss1.append(schema().column(i).name());
 458  0
                     iss1.append(" = ?");
 459  
                 }
 460  
             }
 461  
         }
 462  
 
 463  0
         comma = false;
 464  
 
 465  0
         for (int i = 1; i <= kd.size(); i++)
 466  
         {
 467  0
             String attrib = kd.getAttrib(i);
 468  
 
 469  0
             if (!valueIsClean(schema().index(attrib)))
 470  
             {
 471  0
                 throw new DataSetException("The value for column '" + attrib + "' is a key value and cannot be updated.");
 472  
             }
 473  
 
 474  0
             if (!comma)
 475  
             {
 476  0
                 iss2.append(attrib);
 477  0
                 iss2.append(" = ?");
 478  0
                 comma = true;
 479  
             }
 480  
             else
 481  
             {
 482  0
                 iss2.append(" AND ");
 483  0
                 iss2.append(attrib);
 484  0
                 iss2.append(" = ?");
 485  
             }
 486  
         }
 487  
 
 488  0
         return "UPDATE " + schema().tableName() + " SET " + iss1.toString() + " WHERE " + iss2.toString();
 489  
     }
 490  
 
 491  
     /**
 492  
      * Builds the SQL DELETE statement for this Record
 493  
      *
 494  
      * @return SQL DELETE statement
 495  
      *
 496  
      * @throws DataSetException TODO: DOCUMENT ME!
 497  
      */
 498  
     private String getDeleteSaveString()
 499  
             throws DataSetException
 500  
     {
 501  0
         KeyDef kd = dataset().keydef();
 502  
 
 503  0
         if ((kd == null) || (kd.size() == 0))
 504  
         {
 505  0
             throw new DataSetException("You must specify KeyDef attributes for this TableDataSet in order to delete a Record.");
 506  
         }
 507  
 
 508  0
         StringBuffer iss1 = new StringBuffer(256);
 509  
 
 510  0
         boolean comma = false;
 511  
 
 512  0
         for (int i = 1; i <= kd.size(); i++)
 513  
         {
 514  0
             if (!comma)
 515  
             {
 516  0
                 iss1.append(kd.getAttrib(i));
 517  0
                 iss1.append(" = ?");
 518  0
                 comma = true;
 519  
             }
 520  
             else
 521  
             {
 522  0
                 iss1.append(" AND ");
 523  0
                 iss1.append(kd.getAttrib(i));
 524  0
                 iss1.append(" = ? ");
 525  
             }
 526  
         }
 527  
 
 528  0
         return "DELETE FROM " + schema().tableName() + " WHERE " + iss1.toString();
 529  
     }
 530  
 
 531  
     /**
 532  
      * Builds the SQL INSERT statement for this Record
 533  
      *
 534  
      * @return SQL INSERT statement
 535  
      *
 536  
      * @throws DataSetException TODO: DOCUMENT ME!
 537  
      */
 538  
     private String getInsertSaveString()
 539  
             throws DataSetException
 540  
     {
 541  0
         StringBuffer iss1 = new StringBuffer(256);
 542  0
         StringBuffer iss2 = new StringBuffer(256);
 543  
 
 544  0
         boolean comma = false;
 545  
 
 546  0
         for (int i = 1; i <= size(); i++)
 547  
         {
 548  0
             if (!valueIsClean(i) && !schema().column(i).readOnly())
 549  
             {
 550  0
                 if (!comma)
 551  
                 {
 552  0
                     iss1.append(schema().column(i).name());
 553  0
                     iss2.append("?");
 554  0
                     comma = true;
 555  
                 }
 556  
                 else
 557  
                 {
 558  0
                     iss1.append(", " + schema().column(i).name());
 559  0
                     iss2.append(", ?");
 560  
                 }
 561  
             }
 562  
         }
 563  
 
 564  0
         return "INSERT INTO " + schema().tableName() + " ( " + iss1.toString() + " ) VALUES ( " + iss2.toString() + " )";
 565  
     }
 566  
 
 567  
     /*
 568  
      *       private Hashtable getAffectedColumns()
 569  
      *         throws DataSetException
 570  
      *       {
 571  
      *               Hashtable affectedColumns = new Hashtable ( size() );
 572  
      *               for ( int i = 1; i <= size(); i++ )
 573  
      *         {
 574  
      *           if ( valueIsClean(i) == false )
 575  
      *             affectedColumns.put ( (Object) new Integer(i) , (Object) schema().getColumns()[i].name() );
 576  
      *         }
 577  
      *               return affectedColumns;
 578  
      *       }
 579  
      */
 580  
 
 581  
     /**
 582  
      * Gets the appropriate SQL string for this record.
 583  
      *
 584  
      * @return SQL string
 585  
      *
 586  
      * @throws DataSetException TODO: DOCUMENT ME!
 587  
      */
 588  
     public String getSaveString()
 589  
             throws DataSetException
 590  
     {
 591  0
         if (toBeSavedWithInsert())
 592  
         {
 593  0
             return getInsertSaveString();
 594  
         }
 595  0
         else if (toBeSavedWithUpdate())
 596  
         {
 597  0
             return getUpdateSaveString();
 598  
         }
 599  0
         else if (toBeSavedWithDelete())
 600  
         {
 601  0
             return getDeleteSaveString();
 602  
         }
 603  
         else
 604  
         {
 605  0
             throw new DataSetException("Not able to return save string: " + this.saveType);
 606  
         }
 607  
     }
 608  
 
 609  
     /**
 610  
      * gets the value at index i
 611  
      *
 612  
      * @param i TODO: DOCUMENT ME!
 613  
      *
 614  
      * @return the Value object at index i
 615  
      *
 616  
      * @throws DataSetException TODO: DOCUMENT ME!
 617  
      */
 618  
     public Value getValue(int i)
 619  
             throws DataSetException
 620  
     {
 621  0
         if (i == 0)
 622  
         {
 623  0
             throw new DataSetException("Values are 1 based!");
 624  
         }
 625  0
         else if (i > size())
 626  
         {
 627  0
             throw new DataSetException("Only " + size() + " columns exist!");
 628  
         }
 629  0
         else if (values[i] == null)
 630  
         {
 631  0
             throw new DataSetException("No values for the requested column!");
 632  
         }
 633  
 
 634  0
         return values[i];
 635  
     }
 636  
 
 637  
     /**
 638  
      * TODO: DOCUMENT ME!
 639  
      *
 640  
      * @param columnName TODO: DOCUMENT ME!
 641  
      *
 642  
      * @return TODO: DOCUMENT ME!
 643  
      *
 644  
      * @throws DataSetException TODO: DOCUMENT ME!
 645  
      */
 646  
     public Value getValue(String columnName)
 647  
             throws DataSetException
 648  
     {
 649  0
         return getValue(schema().index(columnName));
 650  
     }
 651  
 
 652  
     /**
 653  
      * the number of columns in this object
 654  
      *
 655  
      * @return the number of columns in this object
 656  
      */
 657  
     public int size()
 658  
     {
 659  0
         return numberOfColumns;
 660  
     }
 661  
 
 662  
     /**
 663  
      * whether or not this Record is to be saved with an SQL insert statement
 664  
      *
 665  
      * @return true if saved with insert
 666  
      */
 667  
     public boolean toBeSavedWithInsert()
 668  
     {
 669  0
         return (this.saveType == Enums.INSERT) ? true : false;
 670  
     }
 671  
 
 672  
     /**
 673  
      * whether or not this Record is to be saved with an SQL update statement
 674  
      *
 675  
      * @return true if saved with update
 676  
      */
 677  
     public boolean toBeSavedWithUpdate()
 678  
     {
 679  0
         return (this.saveType == Enums.UPDATE) ? true : false;
 680  
     }
 681  
 
 682  
     /**
 683  
      * whether or not this Record is to be saved with an SQL delete statement
 684  
      *
 685  
      * @return true if saved with delete
 686  
      */
 687  
     public boolean toBeSavedWithDelete()
 688  
     {
 689  0
         return (this.saveType == Enums.DELETE) ? true : false;
 690  
     }
 691  
 
 692  
     /**
 693  
      * Marks all the values in this record as clean.
 694  
      *
 695  
      * @throws DataSetException TODO: DOCUMENT ME!
 696  
      */
 697  
     public void markRecordClean()
 698  
             throws DataSetException
 699  
     {
 700  0
         for (int i = 1; i <= size(); i++)
 701  
         {
 702  0
             markValueClean(i);
 703  
         }
 704  0
     }
 705  
 
 706  
     /**
 707  
      * Marks this record to be inserted when a save is executed.
 708  
      *
 709  
      * @throws DataSetException TODO: DOCUMENT ME!
 710  
      */
 711  
     public void markForInsert()
 712  
             throws DataSetException
 713  
     {
 714  0
         if (dataset() instanceof QueryDataSet)
 715  
         {
 716  0
             throw new DataSetException("You cannot mark a record in a QueryDataSet for insert");
 717  
         }
 718  
 
 719  0
         setSaveType(Enums.INSERT);
 720  0
     }
 721  
 
 722  
     /**
 723  
      * Marks this record to be updated when a save is executed.
 724  
      *
 725  
      * @throws DataSetException TODO: DOCUMENT ME!
 726  
      */
 727  
     public void markForUpdate()
 728  
             throws DataSetException
 729  
     {
 730  0
         if (dataset() instanceof QueryDataSet)
 731  
         {
 732  0
             throw new DataSetException("You cannot mark a record in a QueryDataSet for update");
 733  
         }
 734  
 
 735  0
         setSaveType(Enums.UPDATE);
 736  0
     }
 737  
 
 738  
     /**
 739  
      * Marks this record to be deleted when a save is executed.
 740  
      *
 741  
      * @return TODO: DOCUMENT ME!
 742  
      *
 743  
      * @throws DataSetException TODO: DOCUMENT ME!
 744  
      */
 745  
     public Record markToBeDeleted()
 746  
             throws DataSetException
 747  
     {
 748  0
         if (dataset() instanceof QueryDataSet)
 749  
         {
 750  0
             throw new DataSetException("You cannot mark a record in a QueryDataSet for deletion");
 751  
         }
 752  
 
 753  0
         setSaveType(Enums.DELETE);
 754  
 
 755  0
         return this;
 756  
     }
 757  
 
 758  
     /**
 759  
      * Unmarks a record that has been marked for deletion.
 760  
      *
 761  
      * <P>
 762  
      * WARNING: You must reset the save type before trying to save this record again.
 763  
      * </p>
 764  
      *
 765  
      * @return TODO: DOCUMENT ME!
 766  
      *
 767  
      * @throws DataSetException TODO: DOCUMENT ME!
 768  
      *
 769  
      * @see #markForUpdate()
 770  
      * @see #markForInsert()
 771  
      * @see #markToBeDeleted()
 772  
      */
 773  
     public Record unmarkToBeDeleted()
 774  
             throws DataSetException
 775  
     {
 776  0
         if (this.saveType == Enums.ZOMBIE)
 777  
         {
 778  0
             throw new DataSetException("This record has already been deleted!");
 779  
         }
 780  
 
 781  0
         setSaveType(Enums.UNKNOWN);
 782  
 
 783  0
         return this;
 784  
     }
 785  
 
 786  
     /**
 787  
      * marks a value at a given position as clean.
 788  
      *
 789  
      * @param pos TODO: DOCUMENT ME!
 790  
      *
 791  
      * @throws DataSetException TODO: DOCUMENT ME!
 792  
      */
 793  
     public void markValueClean(int pos)
 794  
             throws DataSetException
 795  
     {
 796  0
         if (pos == 0)
 797  
         {
 798  0
             throw new DataSetException("Value position must be greater than 0.");
 799  
         }
 800  0
         else if (pos > size())
 801  
         {
 802  0
             throw new DataSetException("Value position is greater than number of values.");
 803  
         }
 804  
 
 805  0
         this.isClean[pos] = true;
 806  0
     }
 807  
 
 808  
     /**
 809  
      * marks a value with a given column name as clean.
 810  
      *
 811  
      * @param columnName TODO: DOCUMENT ME!
 812  
      *
 813  
      * @throws DataSetException TODO: DOCUMENT ME!
 814  
      */
 815  
     public void markValueClean(String columnName)
 816  
             throws DataSetException
 817  
     {
 818  0
         markValueClean(schema().index(columnName));
 819  0
     }
 820  
 
 821  
     /**
 822  
      * marks a value at a given position as dirty.
 823  
      *
 824  
      * @param pos TODO: DOCUMENT ME!
 825  
      *
 826  
      * @throws DataSetException TODO: DOCUMENT ME!
 827  
      */
 828  
     public void markValueDirty(int pos)
 829  
             throws DataSetException
 830  
     {
 831  0
         if (pos == 0)
 832  
         {
 833  0
             throw new DataSetException("Value position must be greater than 0.");
 834  
         }
 835  0
         else if (pos > size())
 836  
         {
 837  0
             throw new DataSetException("Value position is greater than number of values.");
 838  
         }
 839  
 
 840  0
         this.isClean[pos] = false;
 841  0
     }
 842  
 
 843  
     /**
 844  
      * marks a value with a given column name as dirty.
 845  
      *
 846  
      * @param columnName TODO: DOCUMENT ME!
 847  
      *
 848  
      * @throws DataSetException TODO: DOCUMENT ME!
 849  
      */
 850  
     public void markValueDirty(String columnName)
 851  
             throws DataSetException
 852  
     {
 853  0
         markValueDirty(schema().index(columnName));
 854  0
     }
 855  
 
 856  
     /**
 857  
      * sets the internal save type as one of the defined privates (ie: ZOMBIE)
 858  
      *
 859  
      * @param type TODO: DOCUMENT ME!
 860  
      */
 861  
     void setSaveType(int type)
 862  
     {
 863  0
         this.saveType = type;
 864  0
     }
 865  
 
 866  
     /**
 867  
      * gets the internal save type as one of the defined privates (ie: ZOMBIE)
 868  
      *
 869  
      * @return TODO: DOCUMENT ME!
 870  
      */
 871  
     int getSaveType()
 872  
     {
 873  0
         return this.saveType;
 874  
     }
 875  
 
 876  
     /**
 877  
      * sets the value at pos with a BigDecimal
 878  
      *
 879  
      * @param pos TODO: DOCUMENT ME!
 880  
      * @param value TODO: DOCUMENT ME!
 881  
      *
 882  
      * @return TODO: DOCUMENT ME!
 883  
      *
 884  
      * @throws DataSetException TODO: DOCUMENT ME!
 885  
      */
 886  
     public Record setValue(int pos, BigDecimal value)
 887  
             throws DataSetException
 888  
     {
 889  0
         this.values[pos].setValue(value);
 890  0
         markValueDirty(pos);
 891  
 
 892  0
         return this;
 893  
     }
 894  
 
 895  
     /**
 896  
      * sets the value at pos with a boolean
 897  
      *
 898  
      * @param pos TODO: DOCUMENT ME!
 899  
      * @param value TODO: DOCUMENT ME!
 900  
      *
 901  
      * @return TODO: DOCUMENT ME!
 902  
      *
 903  
      * @throws DataSetException TODO: DOCUMENT ME!
 904  
      */
 905  
     public Record setValue(int pos, boolean value)
 906  
             throws DataSetException
 907  
     {
 908  0
         this.values[pos].setValue(new Boolean(value));
 909  0
         markValueDirty(pos);
 910  
 
 911  0
         return this;
 912  
     }
 913  
 
 914  
     /**
 915  
      * sets the value at pos with a byte[]
 916  
      *
 917  
      * @param pos TODO: DOCUMENT ME!
 918  
      * @param value TODO: DOCUMENT ME!
 919  
      *
 920  
      * @return TODO: DOCUMENT ME!
 921  
      *
 922  
      * @throws DataSetException TODO: DOCUMENT ME!
 923  
      */
 924  
     public Record setValue(int pos, byte [] value)
 925  
             throws DataSetException
 926  
     {
 927  0
         this.values[pos].setValue(value);
 928  0
         markValueDirty(pos);
 929  
 
 930  0
         return this;
 931  
     }
 932  
 
 933  
     /**
 934  
      * sets the value at pos with a java.util.Date
 935  
      *
 936  
      * @param pos TODO: DOCUMENT ME!
 937  
      * @param value TODO: DOCUMENT ME!
 938  
      *
 939  
      * @return TODO: DOCUMENT ME!
 940  
      *
 941  
      * @throws DataSetException TODO: DOCUMENT ME!
 942  
      */
 943  
     public Record setValue(int pos, java.util.Date value)
 944  
             throws DataSetException
 945  
     {
 946  0
         this.values[pos].setValue(value);
 947  0
         markValueDirty(pos);
 948  
 
 949  0
         return this;
 950  
     }
 951  
 
 952  
     /**
 953  
      * sets the value at pos with a java.sql.Date
 954  
      *
 955  
      * @param pos TODO: DOCUMENT ME!
 956  
      * @param value TODO: DOCUMENT ME!
 957  
      *
 958  
      * @return TODO: DOCUMENT ME!
 959  
      *
 960  
      * @throws DataSetException TODO: DOCUMENT ME!
 961  
      */
 962  
     public Record setValue(int pos, java.sql.Date value)
 963  
             throws DataSetException
 964  
     {
 965  0
         this.values[pos].setValue(value);
 966  0
         markValueDirty(pos);
 967  
 
 968  0
         return this;
 969  
     }
 970  
 
 971  
     /**
 972  
      * sets the value at pos with a double
 973  
      *
 974  
      * @param pos TODO: DOCUMENT ME!
 975  
      * @param value TODO: DOCUMENT ME!
 976  
      *
 977  
      * @return TODO: DOCUMENT ME!
 978  
      *
 979  
      * @throws DataSetException TODO: DOCUMENT ME!
 980  
      */
 981  
     public Record setValue(int pos, double value)
 982  
             throws DataSetException
 983  
     {
 984  0
         this.values[pos].setValue(new Double(value));
 985  0
         markValueDirty(pos);
 986  
 
 987  0
         return this;
 988  
     }
 989  
 
 990  
     /**
 991  
      * sets the value at pos with a float
 992  
      *
 993  
      * @param pos TODO: DOCUMENT ME!
 994  
      * @param value TODO: DOCUMENT ME!
 995  
      *
 996  
      * @return TODO: DOCUMENT ME!
 997  
      *
 998  
      * @throws DataSetException TODO: DOCUMENT ME!
 999  
      */
 1000  
     public Record setValue(int pos, float value)
 1001  
             throws DataSetException
 1002  
     {
 1003  0
         this.values[pos].setValue(new Float(value));
 1004  0
         markValueDirty(pos);
 1005  
 
 1006  0
         return this;
 1007  
     }
 1008  
 
 1009  
     /**
 1010  
      * sets the value at pos with a int
 1011  
      *
 1012  
      * @param pos TODO: DOCUMENT ME!
 1013  
      * @param value TODO: DOCUMENT ME!
 1014  
      *
 1015  
      * @return TODO: DOCUMENT ME!
 1016  
      *
 1017  
      * @throws DataSetException TODO: DOCUMENT ME!
 1018  
      */
 1019  
     public Record setValue(int pos, class="keyword">int value)
 1020  
             throws DataSetException
 1021  
     {
 1022  0
         this.values[pos].setValue(new Integer(value));
 1023  0
         markValueDirty(pos);
 1024  
 
 1025  0
         return this;
 1026  
     }
 1027  
 
 1028  
     /**
 1029  
      * sets the value at pos with a long
 1030  
      *
 1031  
      * @param pos TODO: DOCUMENT ME!
 1032  
      * @param value TODO: DOCUMENT ME!
 1033  
      *
 1034  
      * @return TODO: DOCUMENT ME!
 1035  
      *
 1036  
      * @throws DataSetException TODO: DOCUMENT ME!
 1037  
      */
 1038  
     public Record setValue(int pos, long value)
 1039  
             throws DataSetException
 1040  
     {
 1041  0
         this.values[pos].setValue(new Long(value));
 1042  0
         markValueDirty(pos);
 1043  
 
 1044  0
         return this;
 1045  
     }
 1046  
 
 1047  
     /**
 1048  
      * sets the value at pos with a String
 1049  
      *
 1050  
      * @param pos TODO: DOCUMENT ME!
 1051  
      * @param value TODO: DOCUMENT ME!
 1052  
      *
 1053  
      * @return TODO: DOCUMENT ME!
 1054  
      *
 1055  
      * @throws DataSetException TODO: DOCUMENT ME!
 1056  
      */
 1057  
     public Record setValue(int pos, String value)
 1058  
             throws DataSetException
 1059  
     {
 1060  0
         this.values[pos].setValue(value);
 1061  0
         markValueDirty(pos);
 1062  
 
 1063  0
         return this;
 1064  
     }
 1065  
 
 1066  
     /**
 1067  
      * sets the value at pos with a java.sql.Time
 1068  
      *
 1069  
      * @param pos TODO: DOCUMENT ME!
 1070  
      * @param value TODO: DOCUMENT ME!
 1071  
      *
 1072  
      * @return TODO: DOCUMENT ME!
 1073  
      *
 1074  
      * @throws DataSetException TODO: DOCUMENT ME!
 1075  
      */
 1076  
     public Record setValue(int pos, java.sql.Time value)
 1077  
             throws DataSetException
 1078  
     {
 1079  0
         this.values[pos].setValue(value);
 1080  0
         markValueDirty(pos);
 1081  
 
 1082  0
         return this;
 1083  
     }
 1084  
 
 1085  
     /**
 1086  
      * sets the value at pos with a java.sql.Timestamp
 1087  
      *
 1088  
      * @param pos TODO: DOCUMENT ME!
 1089  
      * @param value TODO: DOCUMENT ME!
 1090  
      *
 1091  
      * @return TODO: DOCUMENT ME!
 1092  
      *
 1093  
      * @throws DataSetException TODO: DOCUMENT ME!
 1094  
      */
 1095  
     public Record setValue(int pos, java.sql.Timestamp value)
 1096  
             throws DataSetException
 1097  
     {
 1098  0
         this.values[pos].setValue(value);
 1099  0
         markValueDirty(pos);
 1100  
 
 1101  0
         return this;
 1102  
     }
 1103  
 
 1104  
     /**
 1105  
      * sets the value at pos with a Value
 1106  
      *
 1107  
      * @param pos TODO: DOCUMENT ME!
 1108  
      * @param value TODO: DOCUMENT ME!
 1109  
      *
 1110  
      * @return TODO: DOCUMENT ME!
 1111  
      *
 1112  
      * @throws DataSetException TODO: DOCUMENT ME!
 1113  
      */
 1114  
     public Record setValue(int pos, Value value)
 1115  
             throws DataSetException
 1116  
     {
 1117  0
         this.values[pos].setValue(value.getValue());
 1118  0
         markValueDirty(pos);
 1119  
 
 1120  0
         return this;
 1121  
     }
 1122  
 
 1123  
     /**
 1124  
      * sets the value at column name with a BigDecimal
 1125  
      *
 1126  
      * @param columnName TODO: DOCUMENT ME!
 1127  
      * @param value TODO: DOCUMENT ME!
 1128  
      *
 1129  
      * @return TODO: DOCUMENT ME!
 1130  
      *
 1131  
      * @throws DataSetException TODO: DOCUMENT ME!
 1132  
      */
 1133  
     public Record setValue(String columnName, BigDecimal value)
 1134  
             throws DataSetException
 1135  
     {
 1136  0
         setValue(schema().index(columnName), value);
 1137  
 
 1138  0
         return this;
 1139  
     }
 1140  
 
 1141  
     /**
 1142  
      * sets the value at column name with a boolean
 1143  
      *
 1144  
      * @param columnName TODO: DOCUMENT ME!
 1145  
      * @param value TODO: DOCUMENT ME!
 1146  
      *
 1147  
      * @return TODO: DOCUMENT ME!
 1148  
      *
 1149  
      * @throws DataSetException TODO: DOCUMENT ME!
 1150  
      */
 1151  
     public Record setValue(String columnName, boolean value)
 1152  
             throws DataSetException
 1153  
     {
 1154  0
         setValue(schema().index(columnName), value);
 1155  
 
 1156  0
         return this;
 1157  
     }
 1158  
 
 1159  
     /**
 1160  
      * sets the value at column name with a byte[]
 1161  
      *
 1162  
      * @param columnName TODO: DOCUMENT ME!
 1163  
      * @param value TODO: DOCUMENT ME!
 1164  
      *
 1165  
      * @return TODO: DOCUMENT ME!
 1166  
      *
 1167  
      * @throws DataSetException TODO: DOCUMENT ME!
 1168  
      */
 1169  
     public Record setValue(String columnName, byte [] value)
 1170  
             throws DataSetException
 1171  
     {
 1172  0
         setValue(schema().index(columnName), value);
 1173  
 
 1174  0
         return this;
 1175  
     }
 1176  
 
 1177  
     /**
 1178  
      * sets the value at column name with a java.util.Date
 1179  
      *
 1180  
      * @param columnName TODO: DOCUMENT ME!
 1181  
      * @param value TODO: DOCUMENT ME!
 1182  
      *
 1183  
      * @return TODO: DOCUMENT ME!
 1184  
      *
 1185  
      * @throws DataSetException TODO: DOCUMENT ME!
 1186  
      */
 1187  
     public Record setValue(String columnName, java.util.Date value)
 1188  
             throws DataSetException
 1189  
     {
 1190  0
         setValue(schema().index(columnName), value);
 1191  
 
 1192  0
         return this;
 1193  
     }
 1194  
 
 1195  
     /**
 1196  
      * sets the value at column name with a java.sql.Date
 1197  
      *
 1198  
      * @param columnName TODO: DOCUMENT ME!
 1199  
      * @param value TODO: DOCUMENT ME!
 1200  
      *
 1201  
      * @return TODO: DOCUMENT ME!
 1202  
      *
 1203  
      * @throws DataSetException TODO: DOCUMENT ME!
 1204  
      */
 1205  
     public Record setValue(String columnName, java.sql.Date value)
 1206  
             throws DataSetException
 1207  
     {
 1208  0
         setValue(schema().index(columnName), value);
 1209  
 
 1210  0
         return this;
 1211  
     }
 1212  
 
 1213  
     /**
 1214  
      * sets the value at column name with a double
 1215  
      *
 1216  
      * @param columnName TODO: DOCUMENT ME!
 1217  
      * @param value TODO: DOCUMENT ME!
 1218  
      *
 1219  
      * @return TODO: DOCUMENT ME!
 1220  
      *
 1221  
      * @throws DataSetException TODO: DOCUMENT ME!
 1222  
      */
 1223  
     public Record setValue(String columnName, double value)
 1224  
             throws DataSetException
 1225  
     {
 1226  0
         setValue(schema().index(columnName), value);
 1227  
 
 1228  0
         return this;
 1229  
     }
 1230  
 
 1231  
     /**
 1232  
      * sets the value at column name with a float
 1233  
      *
 1234  
      * @param columnName TODO: DOCUMENT ME!
 1235  
      * @param value TODO: DOCUMENT ME!
 1236  
      *
 1237  
      * @return TODO: DOCUMENT ME!
 1238  
      *
 1239  
      * @throws DataSetException TODO: DOCUMENT ME!
 1240  
      */
 1241  
     public Record setValue(String columnName, float value)
 1242  
             throws DataSetException
 1243  
     {
 1244  0
         setValue(schema().index(columnName), value);
 1245  
 
 1246  0
         return this;
 1247  
     }
 1248  
 
 1249  
     /**
 1250  
      * sets the value at column name with a int
 1251  
      *
 1252  
      * @param columnName TODO: DOCUMENT ME!
 1253  
      * @param value TODO: DOCUMENT ME!
 1254  
      *
 1255  
      * @return TODO: DOCUMENT ME!
 1256  
      *
 1257  
      * @throws DataSetException TODO: DOCUMENT ME!
 1258  
      */
 1259  
     public Record setValue(String columnName, int value)
 1260  
             throws DataSetException
 1261  
     {
 1262  0
         setValue(schema().index(columnName), value);
 1263  
 
 1264  0
         return this;
 1265  
     }
 1266  
 
 1267  
     /**
 1268  
      * sets the value at column name with a long
 1269  
      *
 1270  
      * @param columnName TODO: DOCUMENT ME!
 1271  
      * @param value TODO: DOCUMENT ME!
 1272  
      *
 1273  
      * @return TODO: DOCUMENT ME!
 1274  
      *
 1275  
      * @throws DataSetException TODO: DOCUMENT ME!
 1276  
      */
 1277  
     public Record setValue(String columnName, long value)
 1278  
             throws DataSetException
 1279  
     {
 1280  0
         setValue(schema().index(columnName), value);
 1281  
 
 1282  0
         return this;
 1283  
     }
 1284  
 
 1285  
     /**
 1286  
      * sets the value at column name with a String
 1287  
      *
 1288  
      * @param columnName TODO: DOCUMENT ME!
 1289  
      * @param value TODO: DOCUMENT ME!
 1290  
      *
 1291  
      * @return TODO: DOCUMENT ME!
 1292  
      *
 1293  
      * @throws DataSetException TODO: DOCUMENT ME!
 1294  
      */
 1295  
     public Record setValue(String columnName, String value)
 1296  
             throws DataSetException
 1297  
     {
 1298  0
         setValue(schema().index(columnName), value);
 1299  
 
 1300  0
         return this;
 1301  
     }
 1302  
 
 1303  
     /**
 1304  
      * sets the value at column name with a java.sql.Time
 1305  
      *
 1306  
      * @param columnName TODO: DOCUMENT ME!
 1307  
      * @param value TODO: DOCUMENT ME!
 1308  
      *
 1309  
      * @return TODO: DOCUMENT ME!
 1310  
      *
 1311  
      * @throws DataSetException TODO: DOCUMENT ME!
 1312  
      */
 1313  
     public Record setValue(String columnName, java.sql.Time value)
 1314  
             throws DataSetException
 1315  
     {
 1316  0
         setValue(schema().index(columnName), value);
 1317  
 
 1318  0
         return this;
 1319  
     }
 1320  
 
 1321  
     /**
 1322  
      * sets the value at column name with a java.sql.Timestamp
 1323  
      *
 1324  
      * @param columnName TODO: DOCUMENT ME!
 1325  
      * @param value TODO: DOCUMENT ME!
 1326  
      *
 1327  
      * @return TODO: DOCUMENT ME!
 1328  
      *
 1329  
      * @throws DataSetException TODO: DOCUMENT ME!
 1330  
      */
 1331  
     public Record setValue(String columnName, java.sql.Timestamp value)
 1332  
             throws DataSetException
 1333  
     {
 1334  0
         setValue(schema().index(columnName), value);
 1335  
 
 1336  0
         return this;
 1337  
     }
 1338  
 
 1339  
     /**
 1340  
      * sets the value at column name with a Value
 1341  
      *
 1342  
      * @param columnName TODO: DOCUMENT ME!
 1343  
      * @param value TODO: DOCUMENT ME!
 1344  
      *
 1345  
      * @return TODO: DOCUMENT ME!
 1346  
      *
 1347  
      * @throws DataSetException TODO: DOCUMENT ME!
 1348  
      */
 1349  
     public Record setValue(String columnName, Value value)
 1350  
             throws DataSetException
 1351  
     {
 1352  0
         setValue(schema().index(columnName), value);
 1353  
 
 1354  0
         return this;
 1355  
     }
 1356  
 
 1357  
     /**
 1358  
      * sets the value at pos with a NULL
 1359  
      *
 1360  
      * @param pos TODO: DOCUMENT ME!
 1361  
      *
 1362  
      * @return TODO: DOCUMENT ME!
 1363  
      *
 1364  
      * @throws DataSetException TODO: DOCUMENT ME!
 1365  
      */
 1366  
     public Record setValueNull(int pos)
 1367  
             throws DataSetException
 1368  
     {
 1369  0
         if (pos == 0)
 1370  
         {
 1371  0
             throw new DataSetException("Value position must be greater than 0.");
 1372  
         }
 1373  0
         else if (pos > size())
 1374  
         {
 1375  0
             throw new DataSetException("Value position is greater than number of values.");
 1376  
         }
 1377  
 
 1378  0
         this.values[pos].setValue(null);
 1379  0
         markValueDirty(pos);
 1380  
 
 1381  0
         return this;
 1382  
     }
 1383  
 
 1384  
     /**
 1385  
      * sets the value at column name with a NULL
 1386  
      *
 1387  
      * @param columnName TODO: DOCUMENT ME!
 1388  
      *
 1389  
      * @return TODO: DOCUMENT ME!
 1390  
      *
 1391  
      * @throws DataSetException TODO: DOCUMENT ME!
 1392  
      */
 1393  
     public Record setValueNull(String columnName)
 1394  
             throws DataSetException
 1395  
     {
 1396  0
         if ((columnName == null) || (columnName.length() == 0))
 1397  
         {
 1398  0
             throw new DataSetException("You must specify a column name!");
 1399  
         }
 1400  
 
 1401  0
         setValueNull(schema().index(columnName));
 1402  
 
 1403  0
         return this;
 1404  
     }
 1405  
 
 1406  
     /**
 1407  
      * Determines if this record is a Zombie. A Zombie is a record that has been deleted from the database, but not yet removed
 1408  
      * from the DataSet.
 1409  
      *
 1410  
      * @return a boolean
 1411  
      */
 1412  
     public boolean isAZombie()
 1413  
     {
 1414  0
         return (this.saveType == Enums.ZOMBIE) ? true : false;
 1415  
     }
 1416  
 
 1417  
     /**
 1418  
      * If the record is not clean, needs to be saved with an Update, Delete or Insert, it returns true.
 1419  
      *
 1420  
      * @return boolean
 1421  
      */
 1422  
     public boolean needsToBeSaved()
 1423  
     {
 1424  0
         return !isAZombie() || !recordIsClean() || toBeSavedWithUpdate() || toBeSavedWithDelete() || toBeSavedWithInsert();
 1425  
     }
 1426  
 
 1427  
     /**
 1428  
      * Determines whether or not a value stored in the record is clean.
 1429  
      *
 1430  
      * @param i TODO: DOCUMENT ME!
 1431  
      *
 1432  
      * @return true if clean
 1433  
      */
 1434  
     public boolean valueIsClean(int i)
 1435  
     {
 1436  0
         return isClean[i];
 1437  
     }
 1438  
 
 1439  
     /**
 1440  
      * Determines whether or not a value stored in the record is clean.
 1441  
      *
 1442  
      * @param column TODO: DOCUMENT ME!
 1443  
      *
 1444  
      * @return true if clean
 1445  
      *
 1446  
      * @throws DataSetException TODO: DOCUMENT ME!
 1447  
      */
 1448  
     boolean valueIsClean(String column)
 1449  
             throws DataSetException
 1450  
     {
 1451  0
         return isClean[getValue(column).columnNumber()];
 1452  
     }
 1453  
 
 1454  
     /**
 1455  
      * Goes through all the values in the record to determine if it is clean or not.
 1456  
      *
 1457  
      * @return true if clean
 1458  
      */
 1459  
     public boolean recordIsClean()
 1460  
     {
 1461  0
         for (int i = 1; i <= size(); i++)
 1462  
         {
 1463  0
             if (!valueIsClean(i))
 1464  
             {
 1465  0
                 return false;
 1466  
             }
 1467  
         }
 1468  
 
 1469  0
         return true;
 1470  
     }
 1471  
 
 1472  
     /**
 1473  
      * This method refreshes this Record's Value's. It can only be performed on a Record that has not been modified and has been
 1474  
      * created with a TableDataSet and corresponding KeyDef.
 1475  
      *
 1476  
      * @param connection
 1477  
      *
 1478  
      * @exception DataSetException
 1479  
      * @exception SQLException
 1480  
      */
 1481  
     public void refresh(Connection connection)
 1482  
             throws DataSetException, SQLException
 1483  
     {
 1484  0
         if (toBeSavedWithDelete())
 1485  
         {
 1486  0
             return;
 1487  
         }
 1488  0
         else if (toBeSavedWithInsert())
 1489  
         {
 1490  0
             throw new DataSetException("There is no way to refresh a record which has been created with addRecord().");
 1491  
         }
 1492  0
         else if (dataset() instanceof QueryDataSet)
 1493  
         {
 1494  0
             throw new DataSetException("You can only perform a refresh on Records created with a TableDataSet.");
 1495  
         }
 1496  
 
 1497  0
         PreparedStatement stmt = null;
 1498  
 
 1499  
         try
 1500  
         {
 1501  0
             stmt = connection.prepareStatement(getRefreshQueryString());
 1502  
 
 1503  0
             int ps = 1;
 1504  
 
 1505  0
             for (int i = 1; i <= dataset().keydef().size(); i++)
 1506  
             {
 1507  0
                 Value val = getValue(dataset().keydef().getAttrib(i));
 1508  
 
 1509  0
                 if (val.isNull())
 1510  
                 {
 1511  0
                     throw new DataSetException("You cannot execute an update with a null value for a KeyDef.");
 1512  
                 }
 1513  
 
 1514  0
                 val.setPreparedStatementValue(stmt, ps++);
 1515  
             }
 1516  
 
 1517  0
             ResultSet rs = stmt.executeQuery();
 1518  0
             rs.next();
 1519  
 
 1520  0
             initializeRecord();
 1521  
 
 1522  0
             createValues(rs);
 1523  0
         }
 1524  0
         catch (SQLException e1)
 1525  
         {
 1526  0
             throw e1;
 1527  
         }
 1528  
         finally
 1529  
         {
 1530  0
             try
 1531  
             {
 1532  0
                 if (stmt != null)
 1533  
                 {
 1534  0
                     stmt.close();
 1535  
                 }
 1536  
             }
 1537  0
             catch (SQLException e2)
 1538  
             {
 1539  0
                 throw e2;
 1540  0
             }
 1541  0
         }
 1542  0
     }
 1543  
 
 1544  
     /**
 1545  
      * This builds the SELECT statement in order to refresh the contents of this Record. It depends on a valid KeyDef to exist and
 1546  
      * it must have been created with a TableDataSet.
 1547  
      *
 1548  
      * @return the SELECT string
 1549  
      *
 1550  
      * @exception DataSetException
 1551  
      */
 1552  
     public String getRefreshQueryString()
 1553  
             throws DataSetException
 1554  
     {
 1555  0
         if ((dataset().keydef() == null) || (dataset().keydef().size() == 0))
 1556  
         {
 1557  0
             throw new DataSetException(
 1558  
                 "You can only perform a getRefreshQueryString on a TableDataSet that was created with a KeyDef.");
 1559  
         }
 1560  0
         else if (dataset() instanceof QueryDataSet)
 1561  
         {
 1562  0
             throw new DataSetException("You can only perform a getRefreshQueryString on Records created with a TableDataSet.");
 1563  
         }
 1564  
 
 1565  0
         StringBuffer iss1 = new StringBuffer(256);
 1566  0
         StringBuffer iss2 = new StringBuffer(256);
 1567  0
         boolean comma = false;
 1568  
 
 1569  0
         for (int i = 1; i <= size(); i++)
 1570  
         {
 1571  0
             if (!comma)
 1572  
             {
 1573  0
                 iss1.append(schema().column(i).name());
 1574  0
                 comma = true;
 1575  
             }
 1576  
             else
 1577  
             {
 1578  0
                 iss1.append(", ");
 1579  0
                 iss1.append(schema().column(i).name());
 1580  
             }
 1581  
         }
 1582  
 
 1583  0
         comma = false;
 1584  
 
 1585  0
         for (int i = 1; i <= dataset().keydef().size(); i++)
 1586  
         {
 1587  0
             String attrib = dataset().keydef().getAttrib(i);
 1588  
 
 1589  0
             if (!valueIsClean(attrib))
 1590  
             {
 1591  0
                 throw new DataSetException("You cannot do a refresh from the database if the value "
 1592  
                     + "for a KeyDef column has been changed with a Record.setValue().");
 1593  
             }
 1594  
 
 1595  0
             if (!comma)
 1596  
             {
 1597  0
                 iss2.append(attrib);
 1598  0
                 iss2.append(" = ?");
 1599  0
                 comma = true;
 1600  
             }
 1601  
             else
 1602  
             {
 1603  0
                 iss2.append(" AND ");
 1604  0
                 iss2.append(attrib);
 1605  0
                 iss2.append(" = ?");
 1606  
             }
 1607  
         }
 1608  
 
 1609  0
         return "SELECT " + iss1.toString() + " FROM " + schema().tableName() + " WHERE " + iss2.toString();
 1610  
     }
 1611  
 
 1612  
     /**
 1613  
      * TODO: DOCUMENT ME!
 1614  
      *
 1615  
      * @throws DataSetException TODO: DOCUMENT ME!
 1616  
      */
 1617  
     public void saveWithoutStatusUpdate()
 1618  
             throws DataSetException
 1619  
     {
 1620  0
         throw new DataSetException("Record.saveWithoutStatusUpdate() is not yet implemented.");
 1621  
     }
 1622  
 
 1623  
     /**
 1624  
      * Gets the schema for the parent DataSet
 1625  
      *
 1626  
      * @return the schema for the parent DataSet
 1627  
      *
 1628  
      * @throws DataSetException TODO: DOCUMENT ME!
 1629  
      */
 1630  
     public Schema schema()
 1631  
             throws DataSetException
 1632  
     {
 1633  0
         if (dataset() != null)
 1634  
         {
 1635  0
             return this.schema;
 1636  
         }
 1637  
         else
 1638  
         {
 1639  0
             throw new DataSetException("Internal Error: Record DataSet is null");
 1640  
         }
 1641  
     }
 1642  
 
 1643  
     /**
 1644  
      * Gets the DataSet for this Record
 1645  
      *
 1646  
      * @return the DataSet for this Record
 1647  
      */
 1648  
     public DataSet dataset()
 1649  
     {
 1650  0
         return this.parentDataSet;
 1651  
     }
 1652  
 
 1653  
     /**
 1654  
      * Sets the parent DataSet for this record.
 1655  
      *
 1656  
      * @param ds TODO: DOCUMENT ME!
 1657  
      */
 1658  
     void setParentDataSet(DataSet ds)
 1659  
     {
 1660  0
         this.parentDataSet = ds;
 1661  0
     }
 1662  
 
 1663  
     /**
 1664  
      * return the value of each column as a string. Not yet implemented!
 1665  
      *
 1666  
      * @param valueseparator
 1667  
      * @param maxwidths
 1668  
      *
 1669  
      * @return the formatted string
 1670  
      *
 1671  
      * @exception DataSetException
 1672  
      */
 1673  
     public String asFormattedString(String valueseparator, int [] maxwidths)
 1674  
             throws DataSetException
 1675  
     {
 1676  0
         throw new DataSetException("Not yet implemented!");
 1677  
     }
 1678  
 
 1679  
     /**
 1680  
      * This returns a representation of this Record
 1681  
      *
 1682  
      * @return java.lang.String
 1683  
      */
 1684  
     public String toString()
 1685  
     {
 1686  
         try
 1687  
         {
 1688  0
             ByteArrayOutputStream bout = new ByteArrayOutputStream();
 1689  0
             PrintWriter out = new PrintWriter(bout);
 1690  0
             out.print("{");
 1691  
 
 1692  0
             for (int i = 1; i <= size(); i++)
 1693  
             {
 1694  0
                 out.print("'" + getValue(i).asString() + "'");
 1695  
 
 1696  0
                 if (i < size())
 1697  
                 {
 1698  0
                     out.print(',');
 1699  
                 }
 1700  
             }
 1701  
 
 1702  0
             out.print("}");
 1703  0
             out.flush();
 1704  
 
 1705  0
             return bout.toString();
 1706  
         }
 1707  0
         catch (DataSetException e)
 1708  
         {
 1709  0
             return "";
 1710  
         }
 1711  
     }
 1712  
 }

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