001    package com.sptci.rwt.webui;
002    
003    import java.util.List;
004    
005    import com.sptci.echo2.Dimensions;
006    import com.sptci.echo2.table.ColumnMetaData;
007    import com.sptci.echo2.table.DefaultPageableTableModel;
008    
009    import com.sptci.rwt.Column;
010    import com.sptci.rwt.ConnectionManager;
011    import com.sptci.rwt.QueryExecutor;
012    import com.sptci.rwt.QueryException;
013    import com.sptci.rwt.Row;
014    import com.sptci.rwt.Rows;
015    
016    /**
017     * A custom table model used to display {@link com.sptci.rwt.Row} objects.
018     *
019     * <p>&copy; Copyright 2007 <a href='http://sptci.com/' target='_new'>Sans Pareil Technologies, Inc.</a></p>
020     * @author Rakesh Vidyadharan 2007-10-04
021     * @version $Id: RowTableModel.java 4123 2008-05-25 21:49:01Z rakesh $
022     */
023    public class RowTableModel extends DefaultPageableTableModel<Row>
024    {
025      /** The SQL statement that is to be executed to fetch the results. */
026      protected final String query;
027    
028      /** The maximum number of records to fetch from the database. */
029      protected final int maxRows;
030      
031      /**
032       * The maximum number of characters to display in a column.
033       * 
034       * @since Version 1.3
035       */
036      protected final int maxColumnLength;
037    
038      /** The connection manager to use to fetch database connections. */
039      protected final ConnectionManager manager;
040      
041      /**
042       * Default constructor.  No special actions required.
043       * 
044       * @since Version 1.2
045       */
046      protected RowTableModel()
047      {
048        query = null;
049        manager = null;
050        maxRows = 0;
051        maxColumnLength = 0;
052      }
053    
054      /**
055       * Create a new instance of the table model using the specified collection
056       * of {@link com.sptci.rwt.Row} objects.
057       *
058       * @see #fetchData
059       * @see #processColumns
060       * @param query The sql statement that is to be executed to fetch any
061       *   additional pages of data.
062       * @param maxRows The maximum number of rows to fetch from the
063       *   result set.
064       * @param maxColumnLength The maximum number of characters to display in
065       *   a column.
066       * @param manager The manager to use to fetch database connections.
067       * @throws QueryException If errors are encountered while executing
068       *   the {@link #query}.
069       */
070      public RowTableModel( final String query, final int maxRows,
071          final int maxColumnLength, final ConnectionManager manager )
072        throws QueryException
073      {
074        super();
075        this.query = query;
076        this.maxRows = maxRows;
077        this.maxColumnLength = maxColumnLength;
078        this.manager = manager;
079        setPageSize( Dimensions.getInt( this, "pageSize" ) );
080        processColumns();
081      }
082    
083      /**
084       * Fetch the data from the database by executing {@link #query}.
085       *
086       * @see nextapp.echo2.app.table.AbstractTableModel#fireTableDataChanged
087       * @see com.sptci.rwt.QueryExecutor
088       * @throws QueryException If errors are encountered while executing
089       *   the {@link #query}.
090       */
091      protected void fetchData() throws QueryException
092      {
093        try
094        {
095          QueryExecutor executor = new QueryExecutor( manager );
096    
097          final Rows rows = executor.execute(
098              getQuery(), maxRows, page, pageSize, maxColumnLength );
099          totalRows = rows.getTotalRows();
100          if ( ( maxRows > 0 ) && ( totalRows > maxRows ) )
101          {
102            totalRows = maxRows;
103          }
104    
105          data.clear();
106          data.addAll( rows.getRows() );
107          fireTableDataChanged();
108        }
109        catch ( Throwable t )
110        {
111          throw new QueryException( "Error fetching data for query", t );
112        }
113      }
114    
115      /**
116       * Over-ridden to set the proper column meta data using the column
117       * information from the row object.
118       */
119      @Override
120      protected void processColumns()
121      {
122        if ( data.size() == 0 ) return;
123        final Row row = data.get( 0 );
124    
125        final List<Column> columns = row.getColumns();
126        if ( columns.size() == 0 ) return;
127    
128        for ( Column column : columns )
129        {
130          final ColumnMetaData cmd =
131            new ColumnMetaData( column.getName(), String.class );
132          this.columns.add( cmd );
133        }
134      }
135    
136      /**
137       * Return the column name to display at the specified index.
138       *
139       * @param column The column index for which the name is required.
140       * @return The name of the column.
141       */
142      @Override
143      public String getColumnName( final int column )
144      {
145        return columns.get( column ).getName();
146      }
147    
148      /**
149       * Return the value to display at the coordinates specified.
150       *
151       * @param column The column index.
152       * @param row The row index.
153       * @return The value for the coordinates.
154       * @throws RuntimeException If the indices are invalid.
155       */
156      @Override
157      public Object getValueAt( final int column, final int row )
158      {
159        if ( column < 0 || column >= getColumnCount() )
160        {
161          throw new IllegalArgumentException( "Illegal column index: " + column );
162        }
163        if ( row < 0 || row >= getRowCount() )
164        {
165          throw new IllegalArgumentException( "Illegal row index: " + row );
166        }
167    
168        Row r = data.get( row );
169        Object value = r.getColumns().get( column ).getContent();
170    
171        return value;
172      }
173      
174      /**
175       * Returns {@link #query}.
176       *
177       * @return The value/reference of/to query.
178       */
179      public String getQuery()
180      {
181        return query;
182      }
183      
184      /**
185       * Returns {@link #maxRows}.
186       *
187       * @return The value/reference of/to maxRows.
188       */
189      public int getMaxRows()
190      {
191        return maxRows;
192      }
193      /**
194       * Returns {@link #maxColumnLength}.
195       *
196       * @since Version 1.3
197       * @return The value/reference of/to maxColumnLength.
198       */
199      public int getMaxColumnLength()
200      {
201        return maxColumnLength;
202      }
203      
204      /**
205       * Returns {@link #manager}.
206       *
207       * @return The value/reference of/to manager.
208       */
209      public ConnectionManager getManager()
210      {
211        return manager;
212      }
213      
214      /**
215       * Returns {@link #totalRows}.
216       *
217       * @return The value/reference of/to totalRows.
218       */
219      public long getTotalRows()
220      {
221        return totalRows;
222      }
223      
224      /**
225       * Set {@link #page}.
226       *
227       * @see #fetchData
228       * @param page The value to set.
229       */
230      public void setPage( final int page )
231      {
232        this.page = page;
233        fetchData();
234      }
235      
236      /**
237       * Set {@link #pageSize}.
238       *
239       * @see #fetchData
240       * @param pageSize The value to set.
241       */
242      public void setPageSize( final int pageSize )
243      {
244        this.pageSize = pageSize;
245        fetchData();
246      }
247    }