package hirondelle.web4j.database;

import java.sql.ResultSet;
import java.sql.SQLException;
import hirondelle.web4j.model.ModelCtorException;

/**
 Abstract Base Class for building Model Objects from a <tt>ResultSet</tt>.  
 
 <P>This class exists for two reasons : 
 <ul>
 <li>to translate exceptions
 <li>to allow the construction of both Model Objects and building block 
 objects such as <tt>Date</tt>, <tt>Integer</tt>, and so on. These two differ 
 since building block objects usually have multiple constructors with the same 
 number of arguments.
 </ul>
*/
abstract class ModelBuilder<E> {
  
  /**
   <b>Template Method</b> for parsing a single row into an arbitrary Object. 
   The returned <tt>Object</tt> often represents a Model Object, but can also 
   represent an <tt>Integer</tt> value, a <tt>BigDecimal</tt> value, a <tt>Map</tt>, 
   or any other object whatsoever.
  
   <P>This template method calls the abstract method {@link #build}. This 
   method exists only to translate any exceptions thrown by
   {@link #buildObject(ResultSet)} into a {@link DAOException}.
  
   @param aRow contains data which is to be parsed into an Object of type <tt>E</tt>.
  */
  final E buildObject(ResultSet aRow) throws DAOException {
    E result = null;
    try {
      result = build(aRow);
    }
    catch (SQLException ex){
      throw new DAOException("Database problem. Cannot parse row into Object. " + ex.getMessage(), ex);
    }
    catch(ModelCtorException ex){
      throw new DAOException("Constructor problem. Cannot parse into Object. "  + ex.getMessage(), ex);
    }
    return result;
  }
   
  /**
   Parse a single row into an arbitrary Object, throwing any exceptions.
  
   <P>The argument and return value satisfy the same conditions as in {@link #buildObject}.
  */
  abstract E build(ResultSet aRow) throws SQLException, ModelCtorException;
}
