/*

 * Copyright 2001 by IENET, Inc.

 *

 * Private and Confidential

 * Code contained in this document is the property of IENET.

 * It is for the exclusive use of designated employees

 * and not for distribution without prior written

 * authorization.

 */

/*

 * DataBaseDAO.java

 *

 * Created on 31 de mayo de 2001, 10:21

 */



package q02b.exe.arquitectura.dataobjects;





// Java classes import

import java.math.BigDecimal;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.Date;

import java.sql.ResultSet;

import java.sql.Statement;



import q02b.exe.utils.Q02bConstantes;



import q02b.exe.utils.oracle.Q02bBDUtilidades;

import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;

import es.ejie.frmk.infraestructura.traza.Q70Traza;

import es.ejie.frmk.listeners.base.Q70ListenerUtils;

/**

 *

 * Un Data Access Object encargado de obtener objetos de una base de datos. Contiene un objeto connection <b>que no es 

 * serializable</b> y por tanto, se ha definido como transient.<p>

 * Debido a esto, el objeto connection se pierde al serializar este objeto ( lo cual no debería ser un problema, 

 * ya que la conexión debería de cerrarse entre jsps.

 * <p>

 * Implementa el interface OperacionesLoggable, por lo tanto, es susceptible de escribir en el log de operaciones.

 * @author  Antonio.Vieiro

 * @version 2.0

 */

public abstract class Q02bDataBaseDAO extends Q02bBaseDAO {

    

    protected java.util.ArrayList resultSets = new java.util.ArrayList();

    protected java.util.ArrayList statements = new java.util.ArrayList();

    protected static final String COMPONENTE = "DAO_ACCESO_DATOS";

   

    

    protected String Q02B_JNDI_DATASOURCE = Q70ListenerUtils.getApplicationProperty("CentrosDatabaseDAO",null,"Q02B_JNDI_DATASOURCE");

    protected static Q70Traza tr = Q70Traza.getSingleton();

    

    /** La conexión a BBDD que utilizará este DAO. No se serializa. */

    protected transient Connection connection;

    protected transient  CallableStatement cs;

  

    /** Crea un DAO que se utilizará para la obtención de información

     *  de una base de datos.

     *  Este DAO <B>NO</B> cerrará nunca la conexión.

     *  @param connection La conexión a la base de datos a utilizar.

     */

    public Q02bDataBaseDAO(Connection connection) {

        this.connection = connection;

    }



    /**

     * Constructor vacío utilizado por BaseDAO

     */

    public Q02bDataBaseDAO() {

    }

    

    /** Devuelve la conexión que utilizará este DAO.

     *  @return La conexión a BBDD que utiliza este DAO.

     */

    protected Connection getConnection() {

        return this.connection;

    }



    public void setConnection(Connection connection) {

    	this.connection = connection;

    }

    public CallableStatement getCs() {

		return this.cs;

	}



	public void setCs(CallableStatement cs) {

		this.cs = cs;

	}

    /** Cierra un ResultSet si se puede cerrar.

     *  @param resultSet El ResultSet a cerrar.

     */

    protected void freeResource( ResultSet resultSet ) {

        if ( resultSet != null ) {

            try {

                resultSet.close();

            }catch( java.sql.SQLException sqlE ) {

            	 if (tr.isTraceActive()){

                     tr.trace(COMPONENTE, Q70TraceLevel.ERROR, this.getClass().getName() + "DataBaseDAO  Failed: " + sqlE.getMessage() + ". freeResource.");

                 }               

            }

        }

    }

    /** Cierra un Statement si se puede cerrar.

     *  @param statement El Statement a cerrar.

     */

    protected void freeResource(java.sql.Statement statement) {

        if ( statement != null ) {

            try {

                statement.close();

            }

            catch( java.sql.SQLException sqlE ) {

                if (tr.isTraceActive()){

                    tr.trace(COMPONENTE, Q70TraceLevel.ERROR, this.getClass().getName() + "DataBaseDAO  Failed: " + sqlE.getMessage() + ". freeResource");

                }         

            }

        }

    }

    

    /** Cierra una conexión si se puede cerrar.

     * @param con  Conexión a cerrar

     */

    protected void freeResource( Connection con ) {

        if ( con != null ) {

            try {

               if (!con.isClosed()){ 

                con.close();
               }
            }

            catch( java.sql.SQLException sqlE ) {

            	if (tr.isTraceActive()){

                    tr.trace(COMPONENTE, Q70TraceLevel.ERROR, this.getClass().getName() + "DataBaseDAO  Failed: " + sqlE.getMessage() + ". freeResource");

                }                    

            }

        }

    }

    

    /** Método de utilidad para convertir un String a un número.

     * @return El número cuya representación se encuentra en texto o

     * el valor por defecto si la representación es null.

     * @param text

     * @param defecto Valor por defecto del número. Si el texto es null

     *        entonces se tomará este valor por defecto. */

    protected static final int str2int( String text, int defecto ) {

        try {

            return text == null ? defecto : Integer.parseInt(text.trim() );

        }

        catch( NumberFormatException nfe ) {

            return defecto;

        }

    }

    

    /** Devuelve true si el texto contiene la cadena "SI" en mayúsculas o

     * minúsculas. False en caso contrario.

     * @return true si el texto contiene la palabra "SI", "Si", "sI" o "si",

     * false en caso contrario.

     * @param text  */

    protected static final boolean isSI( String text ) {

        return text != null && text.equalsIgnoreCase("SI");

    }

    

    /**

     * Se encarga de cerrar la conexión, llamando a freeResource(conexion), los resultset y los statements

     */

    public void freeResources(){

        

        java.sql.Statement st=null;

        for (int i = 0;i < statements.size();i ++ ) {

            try{

                st = (Statement)statements.get(i);

                freeResource(st);

            }catch(Exception ex){}

        }

        

        statements.clear();

        

        

        ResultSet rs=null;

        for (int i = 0;i < resultSets.size();i ++ ) {

            try{

                rs = (ResultSet)resultSets.get(i);

                freeResource(rs);

            }catch(Exception ex){}

        }

        

        resultSets.clear();

        try{

            this.cs.close();

         }catch(Exception ex){}

        

        freeResource(connection);

    }

    

    

     /**

     * Se encarga de cerrar la conexión, llamando a freeResource(conexion), los resultset y los statements

     */

    public void freeResourcesNotConnection(){

        

        java.sql.Statement st=null;

        for (int i = 0;i < statements.size();i ++ ) {

            try{

                st = (Statement)statements.get(i);

                freeResource(st);

            }catch(Exception ex){}

        }

        

        statements.clear();

        

        

        ResultSet rs=null;

        for (int i = 0;i < resultSets.size();i ++ ) {

            try{

                rs = (ResultSet)resultSets.get(i);

                freeResource(rs);

            }catch(Exception ex){}

        }

        

        resultSets.clear();

        

        try{

           this.cs.close();

        }catch(Exception ex){}

       }

    

    /**

     * Añade un ResultSet a la lista de resultSets. 

     *@param rs  

     */

    public void addResultSet(ResultSet rs) {

        resultSets.add(rs);

    }

    

    /**

     * Borra un ResultSet de la lista de resultSets

     * @param rs ResultSet a borrar

     */

    public void removeResultSet(ResultSet rs) {

        resultSets.remove(rs);

    }

    

    /**

     * Añade un Statement a la lista de Statements. 

     *@param rs  

     */

    public void addStatement(Statement st) {

        statements.add(st);

    }

    

    /**

     * Borra un Statement de la lista de Statements

     * @param rs Statements a borrar

     */

    public void removeStatement(Statement st) {

        statements.remove(st);

    }

    

    public void executePL(String cadenaLlamadaPL, Object[] listaObjetosIn , String[] listaTiposO) throws Exception {

         final String METODO = ":executePL:";

    	

         this.cs = null;

        

        try {        

        	if (tr.isTraceActive()){

	   			tr.trace(COMPONENTE, Q70TraceLevel.INFO, this.getClass().getName() + METODO + " entrando");

	   		}

        	this.cs = this.connection.prepareCall(cadenaLlamadaPL);

            int pos = 0;

            

            // Cargamos los parametros de entrada IN

            for (int i=0; i < listaObjetosIn.length; i++){

            	Object paramIN = listaObjetosIn[i];

            	if(paramIN instanceof Integer){

            		this.cs.setInt(++pos,((Integer)paramIN).intValue());

            	}

            	else if(paramIN instanceof String){

            		this.cs.setString(++pos,(String)paramIN);

            	}

            	else if(paramIN instanceof Long){

            		this.cs.setLong(++pos,((Long)paramIN).longValue());

            	}

            	else if(paramIN instanceof Double){

            		this.cs.setDouble(++pos,((Double)paramIN).doubleValue());

            	}

            	else if(paramIN instanceof Date){

            		this.cs.setDate(++pos,((Date)paramIN));

            	}

            	else if(paramIN instanceof BigDecimal){

            		this.cs.setBigDecimal(++pos,((BigDecimal)paramIN));

            	}          	

            }

            //Registramos los parametro de salida OUT 

            for (int i=0; i < listaTiposO.length; i++){ 

            	if("XMLType".equals(listaTiposO[i])){

            		this.cs.registerOutParameter(++pos, Q02bBDUtilidades.getOracleType(listaTiposO[i]),"SYS.XMLTYPE"); 

            	}else{

            		this.cs.registerOutParameter(++pos, Q02bBDUtilidades.getOracleType(listaTiposO[i]));    

            	}

            }                     

            // Ejecutamos

            this.cs.execute();

            

        }catch(Exception ex){   	   

    		java.io.StringWriter sw = new java.io.StringWriter();

    		java.io.PrintWriter pw = new java.io.PrintWriter(sw);

    		ex.printStackTrace(pw);

    		tr.trace(COMPONENTE, Q70TraceLevel.ERROR, this.getClass().getName() + METODO + sw.getBuffer ().toString());

    		throw ex;

    	}finally{

    		

    		 if (tr.isTraceActive()){

				tr.trace(COMPONENTE, Q70TraceLevel.INFO, this.getClass().getName() + METODO + " saliendo");                

           }       	

    	}	     

      }

    

    public void executeFunctionPL(String cadenaLlamadaPL, Object[] listaObjetosIn , String[] listaTiposO) throws Exception {

        final String METODO = ":executeFunctionPL:";

   	

        this.cs = null;

       

       try {        

       		if (tr.isTraceActive()){

	   			tr.trace(COMPONENTE, Q70TraceLevel.INFO, this.getClass().getName() + METODO + " entrando");

	   		}

       		

       		this.cs = this.connection.prepareCall(cadenaLlamadaPL);

            int pos = 0;

           

            //Registramos los parametro de salida OUT 

            for (int i=0; i < listaTiposO.length; i++){ 

 	           	if("XMLType".equals(listaTiposO[i])){

 	           		this.cs.registerOutParameter(++pos, Q02bBDUtilidades.getOracleType(listaTiposO[i]),"SYS.XMLTYPE"); 

 	           	}else{

 	           		this.cs.registerOutParameter(++pos, Q02bBDUtilidades.getOracleType(listaTiposO[i]));    

 	           	}

            } 

          

           // Cargamos los parametros de entrada IN

           for (int i=0; i < listaObjetosIn.length; i++){

	           	Object paramIN = listaObjetosIn[i];

	           	if(paramIN instanceof Integer){

	           		this.cs.setInt(++pos,((Integer)paramIN).intValue());

	           	}

	           	else if(paramIN instanceof String){

	           		this.cs.setString(++pos,(String)paramIN);

	           	}

	           	else if(paramIN instanceof Long){

	           		this.cs.setLong(++pos,((Long)paramIN).longValue());

	           	}

	           	else if(paramIN instanceof Double){

	           		this.cs.setDouble(++pos,((Double)paramIN).doubleValue());

	           	}

	           	else if(paramIN instanceof Date){

	           		this.cs.setDate(++pos,((Date)paramIN));

	           	}

	           	else if(paramIN instanceof BigDecimal){

	           		this.cs.setBigDecimal(++pos,((BigDecimal)paramIN));

	           	}          	

           }

                              

           // Ejecutamos

           this.cs.execute();

           

       }catch(Exception ex){   	   

	   		java.io.StringWriter sw = new java.io.StringWriter();

	   		java.io.PrintWriter pw = new java.io.PrintWriter(sw);

	   		ex.printStackTrace(pw);

	   		tr.trace(COMPONENTE, Q70TraceLevel.ERROR, this.getClass().getName() + METODO + sw.getBuffer ().toString());

	   		throw ex;

	   	}finally{   

	   		

				if (tr.isTraceActive()){

					tr.trace(COMPONENTE, Q70TraceLevel.INFO, this.getClass().getName() + METODO + " saliendo");                

	          }       	

	   	}	     

     }

    

    public void executePLNull(String cadenaLlamadaPL, Object[] listaObjetosIn , String[] listaTiposO, String[] tipoDatoObjetosIn) throws Exception {

        

        this.cs = null;

       

       try {        

	       	if (tr.isTraceActive()){

		   			tr.trace(COMPONENTE, Q70TraceLevel.INFO, this.getClass().getName() + ":executePL: entrando");

		   		}

	       	this.cs = this.connection.prepareCall(cadenaLlamadaPL);

	           int pos = 0;

	           

	           // Cargamos los parametros de entrada IN

	           for (int i=0; i < listaObjetosIn.length; i++){

		           	Object 		paramIN 	= listaObjetosIn[i];

		           	String	 	tipoDato	= tipoDatoObjetosIn[i];

		           	if(paramIN == null)

		           	{

		           		if(Q02bConstantes.PL_NUMERICO.equals(tipoDato)){

		           			this.cs.setBigDecimal(++pos,null);

		           		} 

		           		else if(Q02bConstantes.PL_VARCHAR.equals(tipoDato)){

		           			this.cs.setString(++pos,null);

		           		}

		           		else if(Q02bConstantes.PL_DATE.equals(tipoDato)){

		           			this.cs.setDate(++pos,null);

		           		}

		           	}

		           	else

		           	{

			           	if(paramIN instanceof Integer){

			           		this.cs.setInt(++pos,((Integer)paramIN).intValue());

			           	}

			           	else if(paramIN instanceof String){

			           		this.cs.setString(++pos,(String)paramIN);

			           	}

			           	else if(paramIN instanceof Long){

			           		this.cs.setLong(++pos,((Long)paramIN).longValue());

			           	}

			           	else if(paramIN instanceof Double){

			           		this.cs.setDouble(++pos,((Double)paramIN).doubleValue());

			           	}

			           	else if(paramIN instanceof Date){

			           		this.cs.setDate(++pos,((Date)paramIN));

			           	}

			           	else if(paramIN instanceof BigDecimal){

			           		this.cs.setBigDecimal(++pos,((BigDecimal)paramIN));

			           	}    

		           	}

	           }

	           //Registramos los parametro de salida OUT 

	           for (int i=0; i < listaTiposO.length; i++){            	            	

	           	this.cs.registerOutParameter(++pos, Q02bBDUtilidades.getOracleType(listaTiposO[i]));            	            

	           }                     

	           // Ejecutamos

	           this.cs.execute();

	           

	       }catch(Exception ex){   	   

	   		java.io.StringWriter sw = new java.io.StringWriter();

	   		java.io.PrintWriter pw = new java.io.PrintWriter(sw);

	   		ex.printStackTrace(pw);

	   		tr.trace(COMPONENTE, Q70TraceLevel.ERROR, this.getClass().getName() + ":executePL: " + sw.getBuffer ().toString());

	   		throw ex;

	   	}finally{  

	   		

				if (tr.isTraceActive()){

					tr.trace(COMPONENTE, Q70TraceLevel.INFO, this.getClass().getName() + ":executePL: saliendo");                

	          }       	

	   	}	     

     }

}

