AbstractTableModel for UserLogData
[Previous] [Main] [Next]

AbstractTableModel for UserLogData

Each GUI generated is associated with at least one SQL table. Access to the SQL tables is contrulled using an AbstractTableModel that is specific to that table. These can be merged to generate code that joins two or more tables.

Here are some of the major parts of the UserLogDataAbstractTableModel class

·Constructor for class - AbstractTableModel - constructor - a database connection object and the model class object are passed in when the class is instantiated.  
·The class gets the type of database (e.g. postgres, msaccess, sqlserver, etc.) from the model class  
·Gets a copy of the logger object from model  
·Mofifies a dateformatter to use yyyy instead of yy,  
·Getter() method so that classes using the class can determine what database type is bing used.  
·Setter() method so that the database type can be changed (used to set type to TESTING when running TextCase. The TESTING database type always inserts a specific row into the table instead of using the auto-increment value to get a new and unique row id. This is done so that the testCase can then delete the row being used for testing.)  
·Getter() for columnNames in the table  
·Getter() for number of columns in the table  
·Getter() for the idNumber of the row that was just inserted. There is lots of special code for determining this ID number. It is specific to each SQL backend. For example PostgreSQL has a function you call before the insert. This funtion gives you back the next unqiue integer for the auto-incremented field. You can then manually insert a row with this number. MySQL has a function that is run after the insert. This function gives back the row number you just inserted.  
·GetValueAt() - this is one of the primary methods in an AbstractTableModel. In this case the code uses constants that are set up for each column and accesses the last resultSet generated directly. This saves passing through the data to create an ArrayList or Vector. See the next paragraph for a comment about accessing the resultset using column names instead of column numbers. Also note that resultSet row numbers start at one instead of zero like JTables.  
·queryTable(rowDeletedField) - This method queries the SQL table. When it is called a column name is optionsally passed in. This column is used to mark rows that are inActive (virtual delettion). The query will automattically add code the the WHERE clause to exclue these rows.  
* There are two setter() methods - setQueryString(string) and setColString(string) that are used before this method is called. If they are both presnet the query is buile as colString like QueryString. The system checks to see if the database being used handles "upper" and "lower" codes and uses these if it can.  
* If the colString is null and the qString is not null, the method assumes that it has been passed a valid whereclause and uses the qString as that clause.  
* If both qString and colString are null the system queries for all the rows in the table (barring the inActive ones if the rowDeletedFieldName is present).  
* After the query is finished a rowCount variable is set.  
* This method sets an array of ColumnNames[] which contains all of the table column names. These are used by the getValueAt() method. Since resultSets will return data based on row number and column name (as well as row number and column number), it is safer to use column name. This way two data bases that are identical except for the order of their columns will both work equally well. This type of mistake is easy to make at a remote site when a database is updated to match changes made in a master database.  
* Note the catch for SQL errors - this will log the errors on the virtual console and in the logger file. The SQL error catch also loops through errors until it has returned them all. The SQL catch statement will popup the showErrorOccurred() window in the upper right hand corner of the users screen to notify them that something unexpected happend.  
* After the catch for SQL errors there is another catch for general error. Then general error catch statement also invokes the showErrorOccured() method.  
AbstractTableModel - queryTable(rowDeletedField)  
·InsertTable method() - this method uses parameters instead of setters(). It could be modified easily enough.  
      * @param fields - comma delimited list of fields to be inserted  
      * @param values - comma delimited list of values to be inserted  
      * @param primaryKeyField - name of field being used as the primary key  
      * @param lastchangedDateField - name of field being used to mark last date/time a row was changed  
      * @param lastChangedDateText = value being inserted into row as date/time last changed  
      * @param lastChangedByField - name of field being used to mark who last changed a row  
      * @param lastCahgnedByText = value being inserted into row to indicate who last changed the row  
Since the columns designating which colums should be used to indicate who last changed a row and the date/time a row was last changed are optional there are several if statements handling different options.  
    This has special code to determine the value of the auto-incremented primary key  that was just added  - getLocId() returns this values.   If the SQL backend has a function to return this value then that function is used.  If the backend does not have such a function (like MS Access), a query is made using the lastchangeddate.  A row with extactly the date/time we just inserted should be the row we just added.  
Again, this method has a logging SQL error catch statement and a logging General catch statement. See the queryTable() method description above for more details.  
AbstractTableModel - insertTable()  
·updateTable() method - Again there are a number of parameters passed into this method  
    * @params String loc_id - value of the primary key for the row to update  
    * @params String values - comma delimited "column = value" list of calumns and values to update  
    * @params String primaryKeyField - name of the column used as primary key  
    * @params String lastChangedDateField - name of the column used to hold date/time-row-was-last-changed  
    * @params String oldChangedDate - date/time-row-was-last-changed when editing of row began.  
NOTE - multi-user code.  If the date/time in the row hasn't changed from the value recorded when editing started: then the row is updated.  It the value has changed - someone else edited the row and since the user started their edit and the update is rejected.  If the values of the last two params are null, null the datelastchanged logic is bypassed.   
If the values parameter contains the word DELETE, the row is deleted:   
   AbstractTableModel - updateTable()  
·   Several Getters() and Setters()  
     getResultSet() = Getter for main ResultSet   
     getMetaData() -  Getter for MetaData ResultSet   
     setColString() - Setter for colstring (column to look for a value in)   
     setQueryString() -Setter for qstring (value to be looked for)   
     setJTextArea() - Set a common text area that SQL commands are written to (virtual Console)  
     cleanUp()  - closes all table and result sets.  
   AbstractTableModel - several Getter() and Setter() methods  
·   Static int fields - JGuigen generates a list of static int fields which all uppercase columns numbers. The variable associated with column zero is set to zero, the variables associated with column 1 is set to 1 and so forth. This allows code to be writtern that looks like getValueAt(row, utm.LASTNAME) instead of geValueAt(row,17).  
   AbstractTableModel - static int fields to reduce developer errors  
Search for XXXX - You should search for XXXX in the generated code. These x's mark sponts hwere you may want to make changes or fill in descriptions more completly.  
Cut and Paste - When JGuiGen generates an AbstractTableModel file there is a section of code at the top that gives you instructions about cutting and pasting snippets of code intot the Model.java file. These snippets links the application together.  
Here is an example from the userlogdata class.. Note that there are keywords in the model file like "PLACE4" and "PLACE^" that you can search for. These mark where the inserts should go.  
// There are two sections to this Listing  
1.  A set of cut and paste lines that you insert  
    into the Model.java file in the com.jguigen.standard folder.  
2.  Code to create a new class.  This will either be in your package folder or in the same folder with the XML file depending upon your response to the "oweverwrite?" question.  
// ***   Model.Java Inserts  
// ***   Cut and Paste into Model.Java   
// ***  Place with the getters **  Find PLACE4   
* Description - Getter for table: userlogdata  
* @return - table model for userlogdata table  
 public com.halepringle.src.UserlogdataTableModel getUserlogdataTableModel() {  
  if (utm == null) {utm = new com.halepringle.src.UserlogdataTableModel(dbc, this);  
     return utm;  
* Description - Setter to set utm to null  
* @return - nothing  
 public void  setUserlogdataTableModelToNull() {  
    utm = null;  
// ***   Model.Java Inserts  
// ***   Cut and Paste into Model.Java   
// *** Place with the CleanUp Method - Find PLACE6    
if (utm != null) {utm.cleanUp();};  
// ***   Model.Java Inserts  
// ***   Cut and Paste into Model.Java   
// *** Place with the Field Definition section (bottom of program)  Find PLACE7    
private com.halepringle.src.UserlogdataTableModel utm;