/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.entity.jdbc;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.sql.Blob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

import javax.sql.rowset.serial.SerialBlob;

import org.ofbiz.base.util.Debug;

/**
 * An object that handles getting/setting column values in JDBC
 * <code>PreparedStatement</code> and <code>ResultSet</code> objects.
 *
 */
public abstract class JdbcValueHandler<T> {
    public static final String module = JdbcValueHandler.class.getName();
    private static final Map<String, JdbcValueHandler<?>> JdbcValueHandlerMap = createJdbcValueHandlerMap();
    private static final Map<String, Integer> SqlTypeMap = createSqlTypeMap();

    private static Map<String, JdbcValueHandler<?>> createJdbcValueHandlerMap() {
        /*
        This Map is used to select the correct JdbcValueHandler
        for the specified Java type. The JdbcValueHandler instances are
        initialized with the SQL type recommended by Sun/Oracle.
         */
        Map<String, JdbcValueHandler<?>> result = new HashMap<String, JdbcValueHandler<?>>();
        // JDBC 1
        result.put("byte[]", new ByteArrayJdbcValueHandler(Types.LONGVARBINARY));
        result.put("java.lang.Boolean", new BooleanJdbcValueHandler(Types.BOOLEAN));
        result.put("Boolean", new BooleanJdbcValueHandler(Types.BOOLEAN));
        result.put("java.lang.Double", new DoubleJdbcValueHandler(Types.DOUBLE));
        result.put("Double", new DoubleJdbcValueHandler(Types.DOUBLE));
        result.put("java.lang.Float", new FloatJdbcValueHandler(Types.FLOAT));
        result.put("Float", new FloatJdbcValueHandler(Types.FLOAT));
        result.put("java.lang.Integer", new IntegerJdbcValueHandler(Types.INTEGER));
        result.put("Integer", new IntegerJdbcValueHandler(Types.INTEGER));
        result.put("java.lang.Long", new LongJdbcValueHandler(Types.BIGINT));
        result.put("Long", new LongJdbcValueHandler(Types.BIGINT));
        result.put("java.lang.Short", new ShortJdbcValueHandler(Types.SMALLINT));
        result.put("Short", new ShortJdbcValueHandler(Types.SMALLINT));
        result.put("java.lang.String", new StringJdbcValueHandler(Types.CHAR));
        result.put("String", new StringJdbcValueHandler(Types.CHAR));
        result.put("java.sql.Date", new DateJdbcValueHandler(Types.DATE));
        result.put("Date", new DateJdbcValueHandler(Types.DATE));
        result.put("java.sql.Time", new TimeJdbcValueHandler(Types.TIME));
        result.put("Time", new TimeJdbcValueHandler(Types.TIME));
        result.put("java.sql.Timestamp", new TimestampJdbcValueHandler(Types.TIMESTAMP));
        result.put("Timestamp", new TimestampJdbcValueHandler(Types.TIMESTAMP));
        // JDBC 2
        result.put("java.math.BigDecimal", new BigDecimalJdbcValueHandler(Types.DECIMAL));
        result.put("BigDecimal", new BigDecimalJdbcValueHandler(Types.DECIMAL));
        result.put("java.sql.Blob", new BlobJdbcValueHandler(Types.BLOB));
        result.put("Blob", new BlobJdbcValueHandler(Types.BLOB));
        result.put("java.sql.Clob", new ClobJdbcValueHandler(Types.CLOB));
        result.put("Clob", new ClobJdbcValueHandler(Types.CLOB));
        // Non-JDBC Types
        result.put("java.lang.Object", new ObjectJdbcValueHandler(Types.BLOB));
        result.put("Object", new ObjectJdbcValueHandler(Types.BLOB));
        return result;
    }

    private static Map<String, Integer> createSqlTypeMap() {
        /*
        This Map is used to select the correct SQL data type
        for the PreparedStatement.setNull method. The setNull
        method must be called with the correct type, or an
        exception will be thrown.
         */
        Map<String, Integer> result = new HashMap<String, Integer>();
        // SQL 99 Data Types
        result.put("BIT", Types.BIT);
        result.put("BLOB", Types.BLOB);
        result.put("BOOLEAN", Types.BOOLEAN);
        result.put("CHAR", Types.CHAR);
        result.put("CHARACTER", Types.CHAR);
        result.put("CLOB", Types.CLOB);
        result.put("DATE", Types.DATE);
        result.put("DEC", Types.DECIMAL);
        result.put("DECIMAL", Types.DECIMAL);
        result.put("DOUBLE", Types.DOUBLE);
        result.put("DOUBLE PRECISION", Types.DOUBLE);
        result.put("FLOAT", Types.FLOAT);
        result.put("INT", Types.INTEGER);
        result.put("INTEGER", Types.INTEGER);
        result.put("NUMERIC", Types.NUMERIC);
        result.put("REAL", Types.REAL);
        result.put("SMALLINT", Types.SMALLINT);
        result.put("TIME", Types.TIME);
        result.put("TIMESTAMP", Types.TIMESTAMP);
        result.put("VARCHAR", Types.VARCHAR);
        result.put("CHAR VARYING", Types.VARCHAR);
        result.put("CHARACTER VARYING", Types.VARCHAR);
        // DB2, MS SQL Data Types
        // Note: Do NOT map the DATETIME SQL data type, the
        // java-type will be used to select the correct data type
        result.put("LONGVARCHAR", Types.LONGVARCHAR);
        result.put("LONG VARCHAR", Types.LONGVARCHAR);
        result.put("BIGINT", Types.BIGINT);
        result.put("TEXT", Types.LONGVARCHAR);
        result.put("IMAGE", Types.BLOB);
        result.put("BINARY", Types.BINARY);
        result.put("VARBINARY", Types.VARBINARY);
        result.put("LONGVARBINARY", Types.LONGVARBINARY);
        result.put("LONG VARBINARY", Types.LONGVARBINARY);
        // PostgreSQL SQL Data Types
        result.put("BYTEA", Types.BINARY);
        return result;
    }

    /** Returns the <code>JdbcValueHandler</code> that corresponds to a field
     * type.
     *  
     * @param javaType The Java type specified in fieldtype*.xml
     * @param sqlType The SQL type specified in fieldtype*.xml
     * @return A <code>JdbcValueHandler</code> instance
     */
    public static JdbcValueHandler<?> getInstance(String javaType, String sqlType) {
        JdbcValueHandler<?> handler = JdbcValueHandlerMap.get(javaType);
        if (handler != null) {
            String key = parseSqlType(sqlType);
            Integer sqlTypeInt = SqlTypeMap.get(key);
            if (sqlTypeInt != null) {
                handler = handler.create(sqlTypeInt);
            }
        }
        return handler;
    }

    protected static String parseSqlType(String sqlType) {
        String result = sqlType.toUpperCase();
        int pos = result.indexOf("(");
        if (pos != -1) {
            result = result.substring(0, pos);
        }
        return result;
    }

    protected static byte[] serializeObject(Object obj) throws SQLException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(os);
            oos.writeObject(obj);
            os.close();
        } catch (IOException e) {
            throw new SQLException(e);
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {}
            }
        }
        return os.toByteArray();
    }

    // The target database SQL type to be used for the
    // PreparedStatement.setNull method.
    private final int sqlType;

    protected JdbcValueHandler(int sqlType) {
        this.sqlType = sqlType;
    }

    /** Sets a value in a <code>PreparedStatement</code>. The
     * <code>obj</code> argument is converted to the correct data
     * type. Subclasses override this method to cast <code>obj</code>
     * to the correct data type and call the appropriate
     * <code>PreparedStatement.setXxx</code> method.
     * 
     * @param ps
     * @param parameterIndex
     * @param obj
     * @throws SQLException
     */
    protected abstract void castAndSetValue(PreparedStatement ps, int parameterIndex, T obj) throws SQLException;

    protected JdbcValueHandler<T> create(int sqlType) {
        if (sqlType == this.getSqlType()) {
            return this;
        }
        return newInstance(sqlType);
    }

    /**
     * Returns the SQL type for this handler.
     * @return return the SQL type
     * @see <code>java.sql.Types</code>
     */
    public int getSqlType() {
        return this.sqlType;
    }

    /** Returns a value from a <code>ResultSet</code>. The returned
     * object is converted to the Java data type specified in the fieldtype
     * file.
     * 
     * @param rs the ResultSet object
     * @param columnIndex the column index
     * @return get value from result set
     * @throws SQLException
     */
    public abstract T getValue(ResultSet rs, int columnIndex) throws SQLException;

    /**
     * Returns a new instance of the object - initialized with
     * the specified SQL type.
     * @param sqlType the sql type
     * @return returns a new instance
     */
    protected abstract JdbcValueHandler<T> newInstance(int sqlType);

    public abstract Class<T> getJavaClass();

    /** Sets a value in a <code>PreparedStatement</code>. The
     * <code>obj</code> argument is converted to the correct data
     * type.
     * 
     * @param ps
     * @param parameterIndex
     * @param obj
     * @throws SQLException
     */
    public void setValue(PreparedStatement ps, int parameterIndex, T obj) throws SQLException {
        if (obj == null) {
            ps.setNull(parameterIndex, this.getSqlType());
            return;
        }
        this.castAndSetValue(ps, parameterIndex, obj);
    }

    /**
     * A <code>java.math.BigDecimal</code> JDBC value handler.
     */
    protected static class BigDecimalJdbcValueHandler extends JdbcValueHandler<java.math.BigDecimal> {
        protected BigDecimalJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<java.math.BigDecimal> getJavaClass() {
            return java.math.BigDecimal.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, java.math.BigDecimal obj) throws SQLException {
            ps.setBigDecimal(parameterIndex, obj);
        }
        @Override
        public java.math.BigDecimal getValue(ResultSet rs, int columnIndex) throws SQLException {
            return rs.getBigDecimal(columnIndex);
        }
        @Override
        protected JdbcValueHandler<java.math.BigDecimal> newInstance(int sqlType) {
            return new BigDecimalJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.sql.Blob</code> JDBC value handler.
     */
    protected static class BlobJdbcValueHandler extends JdbcValueHandler<Object> {
        protected BlobJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Object> getJavaClass() {
            return Object.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Object obj) throws SQLException {
            ps.setBlob(parameterIndex, (Blob) obj);
        }
        @Override
        public Object getValue(ResultSet rs, int columnIndex) throws SQLException {
            Blob fieldBlob = rs.getBlob(columnIndex);
            if (fieldBlob != null) {
                return new SerialBlob(fieldBlob);
            }
            return null;
        }
        @Override
        protected JdbcValueHandler<Object> newInstance(int sqlType) {
            return new BlobJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.Boolean</code> JDBC value handler.
     */
    protected static class BooleanJdbcValueHandler extends JdbcValueHandler<Boolean> {
        protected BooleanJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Boolean> getJavaClass() {
            return Boolean.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Boolean obj) throws SQLException {
            ps.setBoolean(parameterIndex, obj);
        }
        @Override
        public Boolean getValue(ResultSet rs, int columnIndex) throws SQLException {
            boolean value = rs.getBoolean(columnIndex);
            return rs.wasNull() ? null : Boolean.valueOf(value);
        }
        @Override
        protected JdbcValueHandler<Boolean> newInstance(int sqlType) {
            return new BooleanJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>byte[]</code> JDBC value handler.
     */
    protected static class ByteArrayJdbcValueHandler extends JdbcValueHandler<byte[]> {
        protected ByteArrayJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<byte[]> getJavaClass() {
            return byte[].class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, byte[] obj) throws SQLException {
            ps.setBytes(parameterIndex, obj);
        }
        @Override
        public byte[] getValue(ResultSet rs, int columnIndex) throws SQLException {
            byte[] value = rs.getBytes(columnIndex);
            return rs.wasNull() ? null : value;
        }
        @Override
        protected JdbcValueHandler<byte[]> newInstance(int sqlType) {
            return new ByteArrayJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.sql.Clob</code> JDBC value handler.
     */
    protected static class ClobJdbcValueHandler extends JdbcValueHandler<Object> {
        protected ClobJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Object> getJavaClass() {
            return Object.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Object obj) throws SQLException {
            try {
                // FIXME: This is here for backwards compatibility. Client code
                // that uses a Clob java-type for a java.lang.String should use a
                // java.lang.String java-type instead.
                String str = (String) obj;
                Debug.logWarning("Clob java-type used for java.lang.String. Use java.lang.String java-type instead.", module);
                ps.setString(parameterIndex, str);
                return;
            } catch (ClassCastException e) {}
            ps.setClob(parameterIndex, (java.sql.Clob) obj);
            return;
        }
        @Override
        public Object getValue(ResultSet rs, int columnIndex) throws SQLException {
            java.sql.Clob clob = rs.getClob(columnIndex);
            if (clob == null || clob.length() == 0) {
                return null;
            }
            Reader clobReader = null;
            try {
                clobReader = clob.getCharacterStream();
                int clobLength = (int) clob.length();
                char[] charBuffer = new char[clobLength];
                int offset = 0;
                int charsRead = clobReader.read(charBuffer, offset, clobLength);
                while (charsRead > 0) {
                    offset += charsRead;
                    charsRead = clobReader.read(charBuffer, offset, clobLength);
                }
                // FIXME: This is here for backwards compatibility. Client code
                // that uses a Clob java-type for a java.lang.String should use a
                // java.lang.String java-type instead.
                return new String(charBuffer);
            } catch (IOException e) {
                throw new SQLException(e);
            }
            finally {
                if (clobReader != null) {
                    try {
                        clobReader.close();
                    } catch (IOException e) {}
                }
            }
        }
        @Override
        protected JdbcValueHandler<Object> newInstance(int sqlType) {
            return new ClobJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.sql.Date</code> JDBC value handler.
     */
    protected static class DateJdbcValueHandler extends JdbcValueHandler<java.sql.Date> {
        protected DateJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<java.sql.Date> getJavaClass() {
            return java.sql.Date.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, java.sql.Date obj) throws SQLException {
            ps.setDate(parameterIndex, obj);
        }
        @Override
        public java.sql.Date getValue(ResultSet rs, int columnIndex) throws SQLException {
            return rs.getDate(columnIndex);
        }
        @Override
        protected JdbcValueHandler<java.sql.Date> newInstance(int sqlType) {
            return new DateJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.Double</code> JDBC value handler.
     */
    protected static class DoubleJdbcValueHandler extends JdbcValueHandler<Double> {
        protected DoubleJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Double> getJavaClass() {
            return Double.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Double obj) throws SQLException {
            ps.setDouble(parameterIndex, obj);
        }
        @Override
        public Double getValue(ResultSet rs, int columnIndex) throws SQLException {
            double value = rs.getDouble(columnIndex);
            return rs.wasNull() ? null : Double.valueOf(value);
        }
        @Override
        protected JdbcValueHandler<Double> newInstance(int sqlType) {
            return new DoubleJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.Float</code> JDBC value handler.
     */
    protected static class FloatJdbcValueHandler extends JdbcValueHandler<Float> {
        protected FloatJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Float> getJavaClass() {
            return Float.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Float obj) throws SQLException {
            ps.setFloat(parameterIndex, obj);
        }
        @Override
        public Float getValue(ResultSet rs, int columnIndex) throws SQLException {
            float value = rs.getFloat(columnIndex);
            return rs.wasNull() ? null : Float.valueOf(value);
        }
        @Override
        protected JdbcValueHandler<Float> newInstance(int sqlType) {
            return new FloatJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.Integer</code> JDBC value handler.
     */
    protected static class IntegerJdbcValueHandler extends JdbcValueHandler<Integer> {
        protected IntegerJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Integer> getJavaClass() {
            return Integer.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Integer obj) throws SQLException {
            ps.setInt(parameterIndex, obj);
        }
        @Override
        public Integer getValue(ResultSet rs, int columnIndex) throws SQLException {
            int value = rs.getInt(columnIndex);
            return rs.wasNull() ? null : Integer.valueOf(value);
        }
        @Override
        protected JdbcValueHandler<Integer> newInstance(int sqlType) {
            return new IntegerJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.Long</code> JDBC value handler.
     */
    protected static class LongJdbcValueHandler extends JdbcValueHandler<Long> {
        protected LongJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Long> getJavaClass() {
            return Long.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Long obj) throws SQLException {
            ps.setLong(parameterIndex, obj);
        }
        @Override
        public Long getValue(ResultSet rs, int columnIndex) throws SQLException {
            long value = rs.getLong(columnIndex);
            return rs.wasNull() ? null : Long.valueOf(value);
        }
        @Override
        protected JdbcValueHandler<Long> newInstance(int sqlType) {
            return new LongJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.Object</code> JDBC value handler.
     */
    protected static class ObjectJdbcValueHandler extends JdbcValueHandler<Object> {
        protected ObjectJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Object> getJavaClass() {
            return Object.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Object obj) throws SQLException {
            ps.setBytes(parameterIndex, serializeObject(obj));
        }
        @Override
        public Object getValue(ResultSet rs, int columnIndex) throws SQLException {
            ObjectInputStream in = null;
            InputStream bis = null;
            try {
                bis = rs.getBinaryStream(columnIndex);
                if (bis == null) {
                    return null;
                }
                in = new ObjectInputStream(bis);
                return in.readObject();
            } catch (Exception e) {
                throw new SQLException(e);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {}
                }
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {}
                }
            }
        }
        @Override
        protected JdbcValueHandler<Object> newInstance(int sqlType) {
            return new ObjectJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.Short</code> JDBC value handler.
     */
    protected static class ShortJdbcValueHandler extends JdbcValueHandler<Short> {
        protected ShortJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<Short> getJavaClass() {
            return Short.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, Short obj) throws SQLException {
            ps.setShort(parameterIndex, obj);
        }
        @Override
        public Short getValue(ResultSet rs, int columnIndex) throws SQLException {
            short value = rs.getShort(columnIndex);
            return rs.wasNull() ? null : Short.valueOf(value);
        }
        @Override
        protected JdbcValueHandler<Short> newInstance(int sqlType) {
            return new ShortJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.lang.String</code> JDBC value handler.
     */
    protected static class StringJdbcValueHandler extends JdbcValueHandler<String> {
        protected StringJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<String> getJavaClass() {
            return String.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, String obj) throws SQLException {
            ps.setString(parameterIndex, obj);
        }
        @Override
        public String getValue(ResultSet rs, int columnIndex) throws SQLException {
            return rs.getString(columnIndex);
        }
        @Override
        protected JdbcValueHandler<String> newInstance(int sqlType) {
            return new StringJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.sql.Time</code> JDBC value handler.
     */
    protected static class TimeJdbcValueHandler extends JdbcValueHandler<java.sql.Time> {
        protected TimeJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<java.sql.Time> getJavaClass() {
            return java.sql.Time.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, java.sql.Time obj) throws SQLException {
            ps.setTime(parameterIndex, obj);
        }
        @Override
        public java.sql.Time getValue(ResultSet rs, int columnIndex) throws SQLException {
            return rs.getTime(columnIndex);
        }
        @Override
        protected JdbcValueHandler<java.sql.Time> newInstance(int sqlType) {
            return new TimeJdbcValueHandler(sqlType);
        }
    }

    /**
     * A <code>java.sql.Timestamp</code> JDBC value handler.
     * <p>This <code>JdbcValueHandler</code> accommodates databases that
     * don't support sub-second precision. If the date-time field type
     * is a <code>CHAR(30)</code> SQL type, <code>java.sql.Timestamp</code>s
     * will be stored as JDBC timestamp escape format strings
     * (<code>yyyy-mm-dd hh:mm:ss.fffffffff</code>), referenced to UTC.</p> 
     */
    protected static class TimestampJdbcValueHandler extends JdbcValueHandler<java.sql.Timestamp> {
        protected TimestampJdbcValueHandler(int jdbcType) {
            super(jdbcType);
        }
        @Override
        public Class<java.sql.Timestamp> getJavaClass() {
            return java.sql.Timestamp.class;
        }
        @Override
        protected void castAndSetValue(PreparedStatement ps, int parameterIndex, java.sql.Timestamp obj) throws SQLException {
            ps.setTimestamp(parameterIndex, obj);
        }
        @Override
        public java.sql.Timestamp getValue(ResultSet rs, int columnIndex) throws SQLException {
            return rs.getTimestamp(columnIndex);
        }
        @Override
        protected JdbcValueHandler<java.sql.Timestamp> newInstance(int sqlType) {
            if (sqlType == Types.CHAR) {
                return new TimestampJdbcValueHandler(sqlType) {
                    @Override
                    protected void castAndSetValue(PreparedStatement ps, int parameterIndex, java.sql.Timestamp obj) throws SQLException {
                        ps.setString(parameterIndex, obj.toString());
                    }
                    @Override
                    public java.sql.Timestamp getValue(ResultSet rs, int columnIndex) throws SQLException {
                        String str = rs.getString(columnIndex);
                        if (str == null) {
                            return null;
                        }
                        return Timestamp.valueOf(str);
                    }
                };
            } else {
                return new TimestampJdbcValueHandler(sqlType);
            }
        }
    }
}
