View Javadoc

1   /***
2    * Copyright (c) 2003 held jointly by the individual authors.
3    * 
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    * 
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12   * for more details.
13   * 
14   * You should have received a copy of the GNU Lesser General Public License
15   * along with this library; if not, write to the Free Software Foundation, Inc.,
16   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17   *  > http://www.gnu.org/copyleft/lesser.html >
18   * http://www.opensource.org/licenses/lgpl-license.php
19   */
20  package net.mlw.vlh.adapter.jdbc;
21  
22  import java.sql.Connection;
23  import java.sql.PreparedStatement;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.util.List;
27  
28  import javax.sql.DataSource;
29  
30  import net.mlw.vlh.DefaultListBackedValueList;
31  import net.mlw.vlh.ValueList;
32  import net.mlw.vlh.ValueListInfo;
33  import net.mlw.vlh.adapter.AbstractValueListAdapter;
34  import net.mlw.vlh.adapter.jdbc.objectWrapper.ResultSetDecorator;
35  import net.mlw.vlh.adapter.jdbc.util.ConnectionCreator;
36  import net.mlw.vlh.adapter.jdbc.util.JdbcUtil;
37  import net.mlw.vlh.adapter.jdbc.util.SqlPagingSupport;
38  import net.mlw.vlh.adapter.jdbc.util.StandardConnectionCreator;
39  import net.mlw.vlh.adapter.jdbc.util.StandardStatementBuilder;
40  import net.mlw.vlh.adapter.jdbc.util.StatementBuilder;
41  import net.mlw.vlh.adapter.util.ObjectValidator;
42  
43  import org.apache.commons.logging.Log;
44  import org.apache.commons.logging.LogFactory;
45  
46  /***
47   * This adapter handles the standard functionality of creating a query and
48   * execution it...
49   *
50   * If you set validator, it will use special ResultSetDecorator.
51   *
52   * @see net.mlw.vlh.adapter.jdbc.objectWrapper.ResultSetDecorator
53   * @author Matthew L. Wilson, Andrej Zachar
54   * @version $Revision: 1.27 $ $Date: 2006/04/18 17:15:05 $
55   */
56  public abstract class AbstractJdbcAdapter extends AbstractValueListAdapter
57  {
58     /*** Commons logger. */
59     private static final Log LOGGER = LogFactory.getLog(AbstractJdbcAdapter.class);
60  
61     /*** The sql to execute. */
62     private String sql;
63  
64     /*** Display generated sql on th standard output */
65     private boolean showSql = false;
66  
67     /*** The StatementBuilder to help generate a sql query. */
68     private StatementBuilder statementBuilder = new StandardStatementBuilder();
69  
70     /*** The ConnectionCreator to help SQL connection handling */
71     private ConnectionCreator connectionCreator = new StandardConnectionCreator();
72  
73     /***
74      * The validator for ResultSet's records.
75      */
76     private ObjectValidator _validator = null;
77  
78     /***
79      * Helper to provide true in-database paging.
80      */
81     private SqlPagingSupport sqlPagingSupport;
82  
83     public AbstractJdbcAdapter()
84     {}
85  
86     /***
87      * @see net.mlw.vlh.ValueListAdapter#getValueList(java.lang.String,
88      *      net.mlw.vlh.ValueListInfo)
89      */
90     public ValueList getValueList(String name, ValueListInfo info)
91     {
92        if (info.getSortingColumn() == null)
93        {
94           info.setPrimarySortColumn(getDefaultSortColumn());
95           info.setPrimarySortDirection(getDefaultSortDirectionInteger());
96        }
97  
98        int numberPerPage = info.getPagingNumberPer();
99  
100       if (numberPerPage == Integer.MAX_VALUE)
101       {
102          numberPerPage = getDefaultNumberPerPage();
103          info.setPagingNumberPer(numberPerPage);
104       }
105 
106       Connection connection = null;
107       PreparedStatement statement = null;
108       ResultSet result = null;
109 
110       try
111       {
112          boolean doSqlPaging = ((getAdapterType() & DO_PAGE) == 0);
113 
114          connection = connectionCreator.createConnection();
115 
116          StringBuffer query = (sqlPagingSupport != null) ? sqlPagingSupport.getPagedQuery(sql) : new StringBuffer(sql);
117          statement = statementBuilder.generate(connection, query, info.getFilters(), sqlPagingSupport == null && doSqlPaging);
118 
119          if (LOGGER.isDebugEnabled())
120          {
121             LOGGER.debug(query.toString());
122          }
123          if (showSql)
124          {
125             System.out.println("sql: " + query.toString());
126          }
127          result = getResultSet(statement, info);
128 
129          if (sqlPagingSupport != null)
130          {
131             PreparedStatement countStatement = null;
132             ResultSet countResult = null;
133 
134             try
135             {
136                StringBuffer countQuery = sqlPagingSupport.getCountQuery(sql);
137                countStatement = statementBuilder.generate(connection, countQuery, info.getFilters(), false);
138                if (showSql)
139                {
140                   System.out.println("count sql: " + countQuery.toString());
141                }
142                
143                countResult = countStatement.executeQuery();
144                if (countResult.next())
145                {
146                   info.setTotalNumberOfEntries(countResult.getInt(1));
147                }
148             }
149             finally
150             {
151                JdbcUtil.close(countResult, countStatement, null);
152             }
153 
154          }
155          else if (doSqlPaging)
156          {
157             result.last();
158             int totalRows = result.getRow();
159             info.setTotalNumberOfEntries(totalRows);
160 
161             if (numberPerPage == 0)
162             {
163                numberPerPage = getDefaultNumberPerPage();
164             }
165 
166             int pageNumber = info.getPagingPage();
167             if (pageNumber > 1)
168             {
169                if ((pageNumber - 1) * numberPerPage > totalRows)
170                {
171                   pageNumber = ((totalRows - 1) / numberPerPage) + 1;
172                   info.setPagingPage(pageNumber);
173                }
174             }
175 
176             if (pageNumber > 1)
177             {
178                result.absolute((pageNumber - 1) * numberPerPage);
179             }
180             else
181             {
182                result.beforeFirst();
183             }
184          }
185 
186          List list = processResultSet(name, result, (doSqlPaging) ? numberPerPage : Integer.MAX_VALUE, info);
187 
188          if (!doSqlPaging)
189          {
190             info.setTotalNumberOfEntries(list.size());
191          }
192 
193          return new DefaultListBackedValueList(list, info);
194 
195       }
196       catch (Exception e)
197       {
198          LOGGER.error(e);
199          throw new RuntimeException(e);
200       }
201       finally
202       {
203          connectionCreator.close(result, statement, connection);
204       }
205    }
206 
207    /***
208     * @param statement
209     * @param info This info will be set to validator.
210     * @return ResultSet (validator is null) or ResultSetDecorator (validator is
211     *         not null)
212     * @throws SQLException
213     * @see net.mlw.vlh.adapter.util.ObjectValidator
214     * @see net.mlw.vlh.adapter.jdbc.objectWrapper.ResultSetDecorator
215     */
216    private ResultSet getResultSet(PreparedStatement statement, ValueListInfo info) throws SQLException
217    {
218       if (_validator == null)
219       {
220          return statement.executeQuery();
221       }
222       else
223       {
224          _validator.setValueListInfo(info);
225          return new ResultSetDecorator(statement.executeQuery(), _validator);
226       }
227    }
228 
229    /***
230     * This method takes the result and puts the VOs in the List.
231     *
232     * @param result The ResultSet to interate through.
233     * @param info is ussually constant during this process, you can use it for
234     *            passing additional parameters from controler. (Like in
235     *            DefaultWrapperAdapter)
236     * @return The List of VOs.
237     */
238    public abstract List processResultSet(String name, ResultSet result, int numberPerPage, ValueListInfo info) throws SQLException;
239 
240    /***
241     * @return Returns the dataSource.
242     */
243    public DataSource getDataSource()
244    {
245       return connectionCreator.getDataSource();
246    }
247 
248    /***
249     * @param dataSource The dataSource to set.
250     */
251    public void setDataSource(DataSource dataSource)
252    {
253       connectionCreator.setDataSource(dataSource);
254    }
255 
256    /***
257     * @return Returns the sql.
258     */
259    public String getSql()
260    {
261       return sql;
262    }
263 
264    /***
265     * @param sql The sql to set.
266     */
267    public void setSql(String sql)
268    {
269       this.sql = sql;
270    }
271 
272    /***
273     * @return Returns the statementBuilder.
274     */
275    public StatementBuilder getStatementBuilder()
276    {
277       return statementBuilder;
278    }
279 
280    /***
281     * @param statementBuilder The statementBuilder to set.
282     */
283    public void setStatementBuilder(StatementBuilder statementBuilder)
284    {
285       this.statementBuilder = statementBuilder;
286    }
287 
288    /***
289     * @return Returns the showSql.
290     */
291    public boolean isShowSql()
292    {
293       return showSql;
294    }
295 
296    /***
297     * @param showSql The showSql to set.
298     */
299    public void setShowSql(boolean showSql)
300    {
301       this.showSql = showSql;
302    }
303 
304    /***
305     * @return Returns the objectValidator.
306     */
307    public ObjectValidator getValidator()
308    {
309       return _validator;
310    }
311 
312    /***
313     * <p>
314     * If is set to not null value, it uses a special
315     * <code>ResultsSetDecorator<code>, that enable or
316     * disable filtering objects in the final valuelist.
317     * </p>
318     * <h4>NOTE:</h4>
319     * <p>
320     * It respects the total count of entries that overlap your paged
321     * list. Simply spoken it supports features such as paging.
322     * </p>
323     * @param objectValidator The objectValidator to set.
324     * The null value means that validator is disabled.
325     * @see net.mlw.vlh.adapter.util.ObjectValidator
326     * @see net.mlw.vlh.adapter.jdbc.objectWrapper.ResultSetDecorator
327     */
328    public void setValidator(ObjectValidator objectValidator)
329    {
330       this._validator = objectValidator;
331    }
332 
333    /***
334     * @return Returns the connectionCreator.
335     */
336    public ConnectionCreator getConnectionCreator()
337    {
338       return connectionCreator;
339    }
340 
341    /***
342     * @param connectionCreator The connectionCreator to set.
343     */
344    public void setConnectionCreator(ConnectionCreator connectionCreator)
345    {
346       this.connectionCreator = connectionCreator;
347    }
348 
349    public SqlPagingSupport getSqlPagingSupport()
350    {
351       return sqlPagingSupport;
352    }
353 
354    public void setSqlPagingSupport(SqlPagingSupport sqlPagingSupport)
355    {
356       this.sqlPagingSupport = sqlPagingSupport;
357    }
358 }