/*
 * ProcedimentoAbstrato.java
 *
 * Created on 15 de Novembro de 2005, 01:05
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package combd;

import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 *   Classe base para implementação das engines de procedures e queryes.
 *
 * @author Marcos V. S. Godinho
 */
public abstract class ProcedimentoAbstrato implements Procedimento{

    protected Statement statement;

    /**
     * Cria um nova instância de ProcedimentoAbstrato.
     * @param sttmt o Statement.
     */
    public ProcedimentoAbstrato(Statement sttmt){

        statement = sttmt;//Armazena o Statement fornecido.
    }//ProcedimentoPreparado


    /** Finalizador da instância da classe. */
    protected void finalize() throws Throwable{

        try{
            statement.close();
        }
        catch(SQLException ex){

            System.err.println("Ocorreu um erro na finalização de uma instância de Procedimento.");
            ex.printStackTrace();
        }

        statement = null;//Marca Para coleta de lixo.
        /* Este objeto é finalizado com o término do programa e não necessita
        chamar o método System.runFinalization()*/
    }//finalize


    /**
     * Retorna um ResultadoDeBusca após ser executado o procedimento.
     * @return ResultadoDeBusca, se existir.Senão, retorna null.
     */
    public ResultadoDeBusca getResultado(){

        ResultSet resultado;

        try{
            resultado = statement.getResultSet();

            return new ResultadoDeBusca(resultado);
        }
        catch(SQLException ex){}//Não existe resultado.
        return null;
    }//getResultado


    /**
     * Retorna um TabelaDeResultado após ser executado o procedimento.
     * @return ResultadoDeBusca, se existir.Senão, retorna null.
     */
    public TabelaDeResultado getTabelaDeResultado(){

        ResultadoDeBusca res = getResultado();

        return new TabelaDeResultado(res.getNomeColunas(),
                                     res.getNomeClasses(),
                                     res.getArrayDados());
    }//getTabelaDeResultado




    /**
     * Retorna um parametro OUT.
     * @param i o número da coluna. A primeira é a 0, a segunda é a 1, ...
     * @return o parametro OUT.
     */
    public Object getParamOUT(int i){

        ResultSet resultado;

        try{
            resultado = statement.getResultSet();

            if( resultado.first() )  return resultado.getObject(++i);//Primeira coluna é a 1.
        }
        catch(SQLException ex){

            System.err.println("Ocorreu um erro no retorno de um parametro OUT.");
            ex.printStackTrace();
        }
        return null;
    }//getParamOUT


    /**
     * Retorna o primeiro parametro OUT.
     * @return o parametro OUT.
     */
    public Object getParamOUT(){

        return getParamOUT(0);//O primeiro.
    }//getParamOUT


    /**
     * Retorna todos os parametros OUT do elemento inicio até o elemento fim.
     * @param inicio a partir de qual se retorna.
     * @param fim o último do intervalo aberto.
     * @return todos os parametros OUT.
     */
    public Object[] getTodosParamOUT(int inicio, int fim){

        ResultSet resultado;
        try{
            resultado = statement.getResultSet();
            //Se não houver resultado.
            if( !resultado.first() )  return null;

            //Caso for para retornar até o último.
            fim = ( fim == ULTIMO_PARAM_OUT ? resultado.getMetaData().getColumnCount() : fim );

            //Um array de tamanho igual ao número de colunas.
            Object[] obj = new Object[ fim - inicio ];
            //Obtem a linha. Obs.: A primeira coluna do ResultSet é de numero 1.
            for(int i=inicio; i < fim;)  obj[(i++) - inicio] = resultado.getObject(i);

            return obj;
        }
        catch(SQLException ex){

            System.err.println("Ocorreu um erro no retorno de um parametro OUT.");
            ex.printStackTrace();
        }
        return null;//houve erro.
    }//getTodosParamOUT


    /**
     * Retorna todos os parametros OUT do elemento inicio até o último.
     * @param inicio a partir de qual se retorna.
     * @return todos os parametros OUT.
     */
    public Object[] getTodosParamOUT(int inicio){

        return getTodosParamOUT(inicio, ULTIMO_PARAM_OUT);
    }//getTodosParamOUT


    /**
     * Retorna todos os parametros OUT.
     * @return todos os parametros OUT.
     */
    public Object[] getTodosParamOUT(){

        return getTodosParamOUT(0);
    }//getTodosParamOUT


    /**
     * Seta os parametros de um procedimento antes de sua execução.
     * @param param um array de parametros.
     */
    public abstract void setParamIN(Object[] param);


    /**
     * Executa um procedimento que não retorna um ResultSet.
     * @return o número de colunas afetadas. Retorna -1 se houver erro.
     */
    public  abstract int executeProcedimento();


    /**
     * Executa um procedimento que retorna um ResultSet, manipulado pela
     * classe <code>ResultadoDeBusca</code>.
     * @return o resultado da busca. Retorna <code>null</code> se houver erro.
     */
    public  abstract ResultadoDeBusca executeBusca();
}
