/*-----------------------------------------------------------------------------
 *
 * Enhydra JdbcS
 * The Initial Developer of the Original Code is Lutris Technologies Inc.
 * Portions created by Lutris are Copyright 1997-2000 Lutris Technologies Inc.
 * All Rights Reserved.
 *
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * www.enhydra.org/license/epl.html
 *
 * Software distributed under the License is distributed on an "ASIS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * -----------------------------------------------------------------------------
 * $Id$
 * -----------------------------------------------------------------------------
 */
package org.enhydra.jdbc.core;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Map;

/**
 * A very simple implementation of PreparedStatement. When created
 * it is supplied with another PreparedStatement to which all
 * of this class' methods delegate their work. 
 */
public abstract class CorePreparedStatement implements PreparedStatement {
    
    public PreparedStatement	ps;	// the PreparedStatement which does most of the work.
    
   
    public void addBatch() throws SQLException {
	preInvoke();
	try {
	    ps.addBatch();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method addBatch
    
    public void clearParameters() throws SQLException {
	preInvoke();
	try {
	    ps.clearParameters();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method clearParameters
    
    public boolean execute() throws SQLException {
	preInvoke();
	try {
	    return ps.execute();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return false;
    } // method execute

    public ResultSet executeQuery() throws SQLException {
	preInvoke();
	try {
	    return ps.executeQuery();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return null;
    } // method executeQuery

    public int executeUpdate() throws SQLException {
	preInvoke();
	try {
	    return ps.executeUpdate();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method executeUpdate
    
    public ResultSetMetaData getMetaData() throws SQLException {
	preInvoke();
	try {
	    return ps.getMetaData();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return null;
    } // method getMetaData
	
    public void setArray(int i,Array x) throws SQLException {
	preInvoke();
	try {
	    ps.setArray(i,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setArray

    public void setAsciiStream(int parameterIndex,InputStream x,int length) throws SQLException {
	preInvoke();
	try {
	    ps.setAsciiStream(parameterIndex,x,length);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setAsciiStream
    
    public void setBigDecimal(int parameterIndex,BigDecimal x) throws SQLException {
	preInvoke();
	try {
	    ps.setBigDecimal(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setBigDecimal
    
    public void setBinaryStream(int parameterIndex,InputStream x,int length) throws SQLException {
	preInvoke();
	try {
	    ps.setBinaryStream(parameterIndex,x,length);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setBinaryStream
    
    public void setBlob(int i,Blob x) throws SQLException {
	preInvoke();
	try {
	    ps.setBlob(i,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setBlob
    
    public void setBoolean(int parameterIndex,boolean x) throws SQLException {
	preInvoke();
	try {
	    ps.setBoolean(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setBoolean
	
    public void setByte(int parameterIndex,byte x) throws SQLException {
	preInvoke();
	try {
	    ps.setByte(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setByte
    
    public void setBytes(int parameterIndex,byte x[]) throws SQLException {
	preInvoke();
	try {
	    ps.setBytes(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setBytes

    public void setCharacterStream(int parameterIndex,Reader reader,int length) throws SQLException {
	preInvoke();
	try {
	    ps.setCharacterStream(parameterIndex,reader,length);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setCharacterStream
	
    public void setClob(int i,Clob x) throws SQLException {
	preInvoke();
	try {
	    ps.setClob(i,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setClob
    
    public void setDate(int parameterIndex,Date x) throws SQLException {
	preInvoke();
	try {
	    ps.setDate(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setDate
    
    public void setDate(int parameterIndex,Date x,Calendar cal) throws SQLException {
	preInvoke();
	try {
	    ps.setDate(parameterIndex,x,cal);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setDate
    
    public void setDouble(int parameterIndex,double x) throws SQLException {
	preInvoke();
	try {
	    ps.setDouble(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setDouble
	
    public void setFloat(int parameterIndex,float x) throws SQLException {
	preInvoke();
	try {
	    ps.setFloat(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setFloat
	
    public void setInt(int parameterIndex,int x) throws SQLException {
	preInvoke();
	try {
	    ps.setInt(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setInt

    public void setLong(int parameterIndex,long x) throws SQLException {
	preInvoke();
	try {
	    ps.setLong(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setLong

    public void setNull(int parameterIndex,int sqlType) throws SQLException {
	preInvoke();
	try {
	    ps.setNull(parameterIndex,sqlType);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setNull

    public void setNull(int paramIndex,int sqlType,String typeName) throws SQLException {
	preInvoke();
	try {
	    ps.setNull(paramIndex,sqlType,typeName);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setNull
    
    public void setObject(int parameterIndex,Object x) throws SQLException {
	preInvoke();
	try {
	    ps.setObject(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setObject

    public void setObject(int parameterIndex,Object x,int targetSqlType) throws SQLException {
	preInvoke();
	try {
	    ps.setObject(parameterIndex,x,targetSqlType);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setObject

    public void setObject(int parameterIndex,Object x,int targetSqlType,int scale) throws SQLException {
	preInvoke();
	try {
	    ps.setObject(parameterIndex,x,targetSqlType,scale);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setObject
    
    public void setRef(int i,Ref x) throws SQLException {
	preInvoke();
	try {
	    ps.setRef(i,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setRef

    public void setShort(int parameterIndex,short x) throws SQLException {
	preInvoke();
	try {
	    ps.setShort(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setShort

    public void setString(int parameterIndex,String x) throws SQLException {
	preInvoke();
	try {
	    ps.setString(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setString
    
    public void setTime(int parameterIndex,Time x) throws SQLException {
	preInvoke();
	try {
	    ps.setTime(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method 
    
    public void setTime(int parameterIndex,Time x,Calendar cal) throws SQLException  {
	preInvoke();
	try {
	    ps.setTime(parameterIndex,x,cal);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setTime

    public void setTimestamp(int parameterIndex,Timestamp x) throws SQLException {
	preInvoke();
	try {
	    ps.setTimestamp(parameterIndex,x);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setTimestamp

    public void setTimestamp(int parameterIndex,Timestamp x,Calendar cal) throws SQLException {
	preInvoke();
	try {
	    ps.setTimestamp(parameterIndex,x,cal);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setTimestamp
    
    public void setUnicodeStream(int parameterIndex,InputStream x,int length) throws SQLException {
	preInvoke();
	try {
	    ps.setUnicodeStream(parameterIndex,x,length);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setUnicodeStream


    // From Statement

    public void close() throws SQLException {
	if (ps != null) {
	    ps.close();
	}
    } // method close
    
    public int[] executeBatch() throws SQLException {
	preInvoke();
	try {
	    return ps.executeBatch();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return null;
    } // method executeBatch

    public int getMaxFieldSize() throws SQLException {
	 preInvoke();
	 try {
	    return ps.getMaxFieldSize();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getMaxFieldSize

    public void setMaxFieldSize(int max) throws SQLException {
	preInvoke();
	try {
	    ps.setMaxFieldSize(max);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setMaxFieldSize

    public int getMaxRows() throws SQLException {
	 preInvoke();
	 try {
	    return ps.getMaxRows();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getMaxRows

    public void setMaxRows(int max) throws SQLException {
	preInvoke();
	try {
	    ps.setMaxRows(max);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setMaxRows

    public void setEscapeProcessing(boolean enable) throws SQLException {
	 preInvoke();
	 try {
	    ps.setEscapeProcessing(enable);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setEscapeProcessing

    public int getQueryTimeout() throws SQLException {
	 preInvoke();
	 try {
	    return ps.getQueryTimeout();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getQueryTimeout

    public void setQueryTimeout(int seconds) throws SQLException {
	preInvoke();
	try {
	    ps.setQueryTimeout(seconds);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setQueryTimeout
	
    public void cancel() throws SQLException {
	preInvoke();
	try {
	    ps.cancel();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method cancel
	
    public SQLWarning getWarnings() throws SQLException {
	preInvoke();
	try {
	    return ps.getWarnings();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return null;
    } // method getWarnings

    public void clearWarnings() throws SQLException {
	preInvoke();
	try {
	    ps.clearWarnings();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method clearWarnings

    public void setCursorName(String name) throws SQLException {
	preInvoke();
	try {
	    ps.setCursorName(name);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setCursorName
    
    public ResultSet getResultSet() throws SQLException {
	preInvoke();
	try {
	    return ps.getResultSet();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return null;
    } // method getResultSet

    public int getUpdateCount() throws SQLException {
	preInvoke();
	try {
	    return ps.getUpdateCount();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getUpdateCount

    public boolean getMoreResults() throws SQLException {
	preInvoke();
	try {
	    return ps.getMoreResults();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return false;
    } // method getMoreResults

    public void setFetchDirection(int direction) throws SQLException {
	preInvoke();
	try {
	    ps.setFetchDirection(direction);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setFetchDirection
    
    public int getFetchDirection() throws SQLException {
	preInvoke();
	try {
	    return ps.getFetchDirection();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getFetchDirection
	
    public void setFetchSize(int rows) throws SQLException {
	preInvoke();
	try {
	    ps.setFetchSize(rows);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method setFetchSize
	
    public int getFetchSize() throws SQLException {
	preInvoke();
	try {
	    return ps.getFetchSize();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getFetchSize
	
    public int getResultSetConcurrency() throws SQLException {
	preInvoke();
	try {
	    return ps.getResultSetConcurrency();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getResultSetConcurrency
	
    public int getResultSetType() throws SQLException {
	preInvoke();
	try {
	    return ps.getResultSetType();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method getResultSetType
	
    public Connection getConnection() throws SQLException {
	preInvoke();
	try {
	    return ps.getConnection();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return null;
    } // method getConnection
	
    public void clearBatch() throws SQLException {
	preInvoke();
	try {
	    ps.clearBatch();
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method clearBatch
	
    public void addBatch(String s) throws SQLException {
	preInvoke();
	try {
	    ps.addBatch(s);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
    } // method addBatch
	
    public boolean execute(String s) throws SQLException {
	preInvoke();
	try {
	    return ps.execute(s);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return false;
    } // method execute
    
    public ResultSet executeQuery(String s) throws SQLException {
	preInvoke();
	try {
	    return ps.executeQuery(s);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return null;
    } // method executeQuery
    
    public int executeUpdate(String s) throws SQLException {
	preInvoke();
	try {
	    return ps.executeUpdate(s);
	} catch (SQLException e) {
	    catchInvoke(e);
	}
	return 0;
    } // method executeUpdate

    /**
     * Methods used to do some works before and during the catch
     * clause, to prevent the pool that a connection is broken.
     */
    abstract public void preInvoke() throws SQLException;
    abstract public void catchInvoke(SQLException e) throws SQLException;

} // class CorePreparedStatement 
