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 }