001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: DbRowProcessor.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.database;
009:
010: import com.uwyn.rife.database.exceptions.DatabaseException;
011: import com.uwyn.rife.database.exceptions.RowProcessorErrorException;
012: import com.uwyn.rife.tools.ExceptionUtils;
013: import java.sql.ResultSet;
014: import java.sql.SQLException;
015: import java.util.logging.Logger;
016:
017: /**
018: * This abstract base class should be used to implement classes that process one
019: * row in a database query resulset. The <code>fetch</code> method of a
020: * <code>DbQueryManager</code> requires an instance of a
021: * <code>DbRowProcessor</code> and calls its <code>processRow</code>
022: * method each time it is called.
023: * <p>
024: * The <code>DbRowProcessor</code> instance can then work with the result set
025: * and extract all needed data. It is free to implement any logic to be
026: * able to return the retrieved data in an acceptable form to the user.
027: * <p>
028: * A class that extends <code>DbRowProcessor</code> can for example take a
029: * <code>Template</code> instance as the argument of its constructor and
030: * progressively fill in each resulting row in a HTML table. This, without
031: * having to maintain the query results in memory to be able to provide it to a
032: * seperate method which is responsible for the handling of the output. Using a
033: * <code>DbRowProcessor</code> thus allows for perfect seperation and
034: * abstraction of result processing without having to be burdened with possible
035: * large memory usage or large object allocation.
036: *
037: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
038: * @version $Revision: 3634 $
039: * @see #processRow(ResultSet resultSet)
040: * @see com.uwyn.rife.database.DbQueryManager
041: * @since 1.0
042: */
043: public abstract class DbRowProcessor implements Cloneable {
044: private boolean mSuccessful = false;
045:
046: /**
047: * This method has to be implemented by each class that extends the
048: * <code>DbRowProcessor</code> class. It has to contain all the logic that
049: * should be executed for each row of a resultset.
050: *
051: * @param resultSet the <code>ResultSet</code> instance that was provided to
052: * the <code>DbQueryManager</code>'s <code>fetch</code> method.
053: *
054: * @return <code>true</code> if the processing is considered successful; or
055: * <p>
056: * <code>false</code> if the processing is considered failed.
057: * <p>
058: * Note: this return value is purely indicative and unless the user does
059: * checks with the <code>wasSuccessful()</code> method, it will have no
060: * influence on anything.
061: *
062: * @throws SQLException when a database error occurs, it's thus not
063: * necessary to catch all the possible <code>SQLException</code>s inside
064: * this method. They'll be caught higher up and be transformed in
065: * <code>DatabaseException</code>s.
066: *
067: * @see DbQueryManager#fetch(ResultSet, DbRowProcessor)
068: * @see #wasSuccessful()
069: *
070: * @since 1.0
071: */
072: public abstract boolean processRow(ResultSet resultSet)
073: throws SQLException;
074:
075: /**
076: * Indicates whether the processing of the row was successful.
077: *
078: * @return <code>true</code> if the processing was successful; or
079: * <p>
080: * <code>false</code> if the processing was unsuccessful.
081: *
082: * @since 1.0
083: */
084: public final boolean wasSuccessful() {
085: return mSuccessful;
086: }
087:
088: /**
089: * This method wraps around the actual {@link #processRow(ResultSet)} method
090: * to ensure that the success status is reset at each iteration and that the
091: * possible <code>SQLException</code>s are caught correctly.
092: * <p>
093: * This is the method that's called internally by the <code>fetch()</code>
094: * method of a <code>DbQueryManager</code>. It is not meant to be used by
095: * the user.
096: *
097: * @param resultSet a <code>ResultSet</code> instance that was returned
098: * after a query's execution.
099: *
100: * @throws DatabaseException when a database access error occurred during
101: * the processing of the resultset row
102: *
103: * @see #processRow(ResultSet)
104: * @see DbQueryManager#fetch(ResultSet, DbRowProcessor)
105: *
106: * @since 1.0
107: */
108: final void processRowWrapper(ResultSet resultSet)
109: throws DatabaseException {
110: if (null == resultSet)
111: throw new IllegalArgumentException(
112: "resultSet can't be null.");
113:
114: mSuccessful = false;
115: try {
116: mSuccessful = processRow(resultSet);
117: } catch (SQLException e) {
118: mSuccessful = false;
119: throw new RowProcessorErrorException(e);
120: }
121: }
122:
123: /**
124: * Simply clones the instance with the default clone method since this
125: * class contains no object member variables.
126: *
127: * @since 1.0
128: */
129: public Object clone() {
130: try {
131: return super .clone();
132: } catch (CloneNotSupportedException e) {
133: // this should never happen
134: Logger.getLogger("com.uwyn.rife.database").severe(
135: ExceptionUtils.getExceptionStackTrace(e));
136: return null;
137: }
138: }
139: }
|