/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
*/
package fr.gouv.culture.sdx.utils.rdbms;

import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.exception.SDXExceptionCode;
import fr.gouv.culture.sdx.utils.AbstractSdxObject;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/*
 * Created by IntelliJ IDEA.
 * User: rpandey
 * Date: Feb 28, 2003
 * Time: 11:25:55 AM
 * To change this template use Options | File Templates.
 */

/**Abstract class defining some useful methods for database
 * manipulation
 *
 */
public abstract class JDBC extends AbstractSdxObject {


    protected String tableName = null;

    /** Returns a table name used to store the repository's data.
     * @return The table name should be appropriately escaped for table building.
     */
    protected String getTableName() {
        return handleUnsupportedTokens(this.tableName);
    }

    /** Returns an SQL query that could create the table.
     * <p>
     * This query should not have any parameter.
     * @return The query.
     *
     * see subclasses for implementation
     */
    protected abstract String getTableCreationQuery();

    /**
     * Creates the table.
     */
    protected void createTable(Connection conn) throws SDXException {
        try {
            Template template = new Template(conn, getTableCreationQuery());
            template.execute(new QueryExecutor() {
            }, Template.MODE_EXECUTE_UPDATE);
        } catch (SDXException e) {
            String[] args = new String[2];
            args[0] = this.getTableName();
            args[1] = e.getMessage();
            throw new SDXException(super.getLog(), SDXExceptionCode.ERROR_CREATE_TABLE, args, e);
        }
    }

    //TODO:refactor init() methods of some JDBCBacked objects here

    /**Should return a string after scanning
     * and handling any unsupported characters
     * an _identifier (i.e.table name, column name, etc.)
     *
     * @param name The name to prepare for use
     * @return
     */
    protected String handleUnsupportedTokens(String name) {
        //TODO:we should handle more cases here
        return name.replace('-', '_');
    }


    /**Init the LinkedHashMap _xmlizable_volatile_objects with the objects in order to describ them in XML
	 * Some objects need to be refresh each time a toSAX is called*/
	protected void initVolatileObjectsToSax() {
	
	}


	protected static class Template {

        public static final int MODE_NONE = -1;
        public static final int MODE_EXECUTE_QUERY = 0;
        public static final int MODE_EXECUTE_UPDATE = 1;
        protected Connection _conn;
        protected String _query;


        public Template(Connection conn, String query) {
            _conn = conn;
            _query = query;
        }

        public void execute(QueryExecutor qe, int mode) throws SDXException {
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                ps = _conn.prepareStatement(_query);
                if (qe == null) return;
                qe.prepare(ps);
                switch (mode) {
                    case MODE_EXECUTE_UPDATE://1
                        qe.collect(ps.executeUpdate());
                        break;
                    case MODE_EXECUTE_QUERY://0
                        qe.collect(ps.executeQuery());
                        break;
                    case MODE_NONE://-1 do nothing
                    default:
                        break;
                }
            } catch (SQLException e) {
            	String[] args = new String[3];
                args[0] = _query;
                args[1] = "";
                args[2] = e.getMessage();            	                          
                throw new SDXException(null, SDXExceptionCode.ERROR_EXECUTE_QUERY, args, e);
            } catch (IOException e) {
            	String[] args = new String[3];
                args[0] = _query;
                args[1] = "";
                args[2] = e.getMessage();            	                          
                throw new SDXException(null, SDXExceptionCode.ERROR_EXECUTE_QUERY, args, e);
            } finally {
                try {
                    if (rs != null) rs.close();
                } catch (SQLException e) {
                    throw new SDXException(null, SDXExceptionCode.ERROR_CLOSE_RESULT_SET, null, e);
                } finally {
                    try {
                        if (ps != null) ps.close();
                    } catch (SQLException e) {
                        throw new SDXException(null, SDXExceptionCode.ERROR_CLOSE_SQL_PREPARED_STATEMENT, null, e);
                    }
                }
            }


        }


    }

    public static class QueryExecutor {
        public void prepare(PreparedStatement ps) throws SQLException, SDXException {
        }

        public void collect(ResultSet rs) throws SQLException, IOException, SDXException {
        }

        public void collect(int value) throws SQLException {
        }

        public boolean exists() {
            return false;
        }

        public int value() {
            return -1;
        }

        public InputStream getInputStream() {
            return null;
        }

        public Object get() {
            return null;
        }
    }


}
