/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: DbRowProcessor.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.database; import com.uwyn.rife.database.exceptions.DatabaseException; import com.uwyn.rife.database.exceptions.RowProcessorErrorException; import com.uwyn.rife.tools.ExceptionUtils; import java.sql.ResultSet; import java.sql.SQLException; import java.util.logging.Logger; /** * This abstract base class should be used to implement classes that process one * row in a database query resulset. The <code>fetch</code> method of a * <code>DbQueryManager</code> requires an instance of a * <code>DbRowProcessor</code> and calls its <code>processRow</code> * method each time it is called. * <p> * The <code>DbRowProcessor</code> instance can then work with the result set * and extract all needed data. It is free to implement any logic to be * able to return the retrieved data in an acceptable form to the user. * <p> * A class that extends <code>DbRowProcessor</code> can for example take a * <code>Template</code> instance as the argument of its constructor and * progressively fill in each resulting row in a HTML table. This, without * having to maintain the query results in memory to be able to provide it to a * seperate method which is responsible for the handling of the output. Using a * <code>DbRowProcessor</code> thus allows for perfect seperation and * abstraction of result processing without having to be burdened with possible * large memory usage or large object allocation. * * @author Geert Bevin (gbevin[remove] at uwyn dot com) * @version $Revision: 3918 $ * @see #processRow(ResultSet resultSet) * @see com.uwyn.rife.database.DbQueryManager * @since 1.0 */ public abstract class DbRowProcessor implements Cloneable { private boolean mSuccessful = false; /** * This method has to be implemented by each class that extends the * <code>DbRowProcessor</code> class. It has to contain all the logic that * should be executed for each row of a resultset. * * @param resultSet the <code>ResultSet</code> instance that was provided to * the <code>DbQueryManager</code>'s <code>fetch</code> method. * * @return <code>true</code> if the processing is considered successful; or * <p> * <code>false</code> if the processing is considered failed. * <p> * Note: this return value is purely indicative and unless the user does * checks with the <code>wasSuccessful()</code> method, it will have no * influence on anything. * * @throws SQLException when a database error occurs, it's thus not * necessary to catch all the possible <code>SQLException</code>s inside * this method. They'll be caught higher up and be transformed in * <code>DatabaseException</code>s. * * @see DbQueryManager#fetch(ResultSet, DbRowProcessor) * @see #wasSuccessful() * * @since 1.0 */ public abstract boolean processRow(ResultSet resultSet) throws SQLException; /** * Indicates whether the processing of the row was successful. * * @return <code>true</code> if the processing was successful; or * <p> * <code>false</code> if the processing was unsuccessful. * * @since 1.0 */ public final boolean wasSuccessful() { return mSuccessful; } /** * This method wraps around the actual {@link #processRow(ResultSet)} method * to ensure that the success status is reset at each iteration and that the * possible <code>SQLException</code>s are caught correctly. * <p> * This is the method that's called internally by the <code>fetch()</code> * method of a <code>DbQueryManager</code>. It is not meant to be used by * the user. * * @param resultSet a <code>ResultSet</code> instance that was returned * after a query's execution. * * @throws DatabaseException when a database access error occurred during * the processing of the resultset row * * @see #processRow(ResultSet) * @see DbQueryManager#fetch(ResultSet, DbRowProcessor) * * @since 1.0 */ final void processRowWrapper(ResultSet resultSet) throws DatabaseException { if (null == resultSet) throw new IllegalArgumentException("resultSet can't be null."); mSuccessful = false; try { mSuccessful = processRow(resultSet); } catch (SQLException e) { mSuccessful = false; throw new RowProcessorErrorException(e); } } /** * Simply clones the instance with the default clone method since this * class contains no object member variables. * * @since 1.0 */ public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { // this should never happen Logger.getLogger("com.uwyn.rife.database").severe(ExceptionUtils.getExceptionStackTrace(e)); return null; } } }