/*
 * Creado el 22-mar-04
 *
 * Para cambiar la plantilla para este archivo generado vaya a
 * Ventana&gt;Preferencias&gt;Java&gt;Generación de código&gt;Código y comentarios
 */
package es.ejie.frmk.admon.logs;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import es.ejie.frmk.Q70Factoria;
import es.ejie.frmk.conectores.conectorJDBC.Q70ConectorJDBC;
import es.ejie.frmk.control.excepciones.Q70FrameworkException;
import es.ejie.frmk.control.excepciones.Q70GestorDeExcepcionesServidor;
import es.ejie.frmk.infraestructura.logs.base.Q70ConfiguracionLog;
import es.ejie.frmk.infraestructura.logs.base.Q70ConstantesLogs;
import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;
import es.ejie.frmk.infraestructura.traza.Q70TrazaInterface;

/**
 * Clase empleada para la búsqueda de Logs y Trazas en BBDD. Cada tipo de log (accesos, conectores, transacciones, 
 * navegación, incidencias y trazas), tendrá su correspondiente tabla en BBDD con sus registros correspondientes.
 * <ul>
 * <li> Configuración de Log o Traza</li>
 * <li> Columnas visualizables (atributos genéricos)</li>
 * <li> Nombre de Log</li>
 * </ul>
 * @version 2.0 Fecha: 22-05-06
 */
public class Q70BuscadorBDLog implements Q70Buscador{
	
	Q70ConfiguracionLog configuracionLog =null;
	
	String logName =null;
	List globalFields=null;
	List MessageFields=null;
	
	public Q70BuscadorBDLog(Q70ConfiguracionLog configuracionLog, String logName)
	{
		this.configuracionLog = configuracionLog;
		this.logName = logName;
		Q70ColumnParser cpGenericas = new Q70ColumnParser(configuracionLog.getProperty(Q70ConstantesLogs.ATRIBUTOS_GENERICOS));
		globalFields=cpGenericas.parseColumns();
		Q70ColumnParser cpMensensaje = new Q70ColumnParser(configuracionLog.getProperty(Q70ConstantesLogs.ATRIBUTOS_MENSAJE));
		MessageFields=cpMensensaje.parseColumns();
	}
	
	public Q70BuscadorBDLog()
	{
	}
	
	public void setConfiguracion(String logName,Q70ConfiguracionLog configuracionLog)
	{
		this.configuracionLog = configuracionLog;
		this.logName = logName;
		Q70ColumnParser cpGenericas = new Q70ColumnParser(configuracionLog.getProperty(Q70ConstantesLogs.ATRIBUTOS_GENERICOS));
		globalFields=cpGenericas.parseColumns();
		Q70ColumnParser cpMensensaje = new Q70ColumnParser(configuracionLog.getProperty(Q70ConstantesLogs.ATRIBUTOS_MENSAJE));
		MessageFields=cpMensensaje.parseColumns();
	}
	
	/**
	 * Método que devuelve la concatenación de los campos específicos correspondientes a cada tipo de Log.
	 * @return String con los campos para la select de Logs (separados por comas)
	 */
	private String recuperaCamposEspecificos (){
		if (this.logName.equals(Q70ConstantesLogs.LOG_ACCESOS)){
			return Q70ConstantesLogs.SELECT_COLUMNS_ACCESOS;
		}else if (this.logName.equals(Q70ConstantesLogs.LOG_INCIDENCIAS)){
			return Q70ConstantesLogs.SELECT_COLUMNS_INCIDENCIAS;
		}else if (this.logName.equals(Q70ConstantesLogs.LOG_NAVEGACION)){
			return Q70ConstantesLogs.SELECT_COLUMNS_NAVEGACION;
		}else if (this.logName.equals(Q70ConstantesLogs.LOG_TRANSACCIONES)){
			return Q70ConstantesLogs.SELECT_COLUMNS_TRANSACCIONES;
		}else if (this.logName.equals(Q70ConstantesLogs.LOG_CONECTORES)){
			return Q70ConstantesLogs.SELECT_COLUMNS_CONECTORES;
		}
		return "";
	}
	
	/**
	 * Retorna una lista con todas las líneas de logs y trazas que atiendan  a los criterios de selección
	 * especificados. Estas entradas de logs o trazas se extraerán de BBDD. Así, cada tipo diferente de Log
	 * tiene sus entradas en una tabla propia en BBDD con su información específica. 
	 * @param consultaLog - clase que contiene la información que será tenida en cuenta para conformar las líneas
	 * de log y trazas. Son los criterios de selección que se utilizarán para conformar la lista con aquellos que
	 * los cumplan.  
	 * @return List lista con los elementos de tipo Q70ApunteLog con los datos de cada entrada de log o traza
	 */
	public List ExecuteQuery(Q70Filtros consultaLog) throws Q70FrameworkException
	{
		int contAccesos = 0;
		int contNavegacion = 0;
		int contTransacciones = 0;
		int contConectores = 0;
		int contIncidencias = 0;
		int numRegistrosLog = consultaLog.getRegistrosLog();
		
		String dataSource = configuracionLog.getProperty(Q70ConstantesLogs.DATASOURCE);
		String table = configuracionLog.getProperty(Q70ConstantesLogs.TABLA);
		String formattedLog = getFormattedColumn(logName, Q70ConstantesLogs.LOG_NAME_SIZE);
		List results = new ArrayList();

		// construir la sql que devuelve los datos;
		SimpleDateFormat df = new SimpleDateFormat(Q70ConstantesLogs.DATE_FORMAT);
		String formatedDateFrom = df.format(consultaLog.getDateFrom());
		String formatedDateTo = df.format(consultaLog.getDateTo());

		String strCamposSelect = "";
		int numColumnasVisualizables = consultaLog.getSizeColumnasVisualizables();
		for (int i = 0; i < numColumnasVisualizables; i++) {
			strCamposSelect += consultaLog.getColumnaVisualizable(i);
			if (numColumnasVisualizables == 1) {
				break;
			} else if (i < numColumnasVisualizables - 1) {
				strCamposSelect += ", ";
			}
		}

		if (strCamposSelect.equals(""))
			strCamposSelect = "*";
		else
			strCamposSelect = Q70ConstantesLogs.TIMESTAMP + ", " + recuperaCamposEspecificos()+ ", " + strCamposSelect;

		String sql = "Select " + strCamposSelect + " from " + table;
		sql += " where TIMESTAMP >= '" + formatedDateFrom + "' ";
		sql += " AND TIMESTAMP <= '" + formatedDateTo + "' ";

		for (int i = 0; i < consultaLog.getSize(); i++) {
			sql += " AND " + consultaLog.getCondition(i).getField() + "='" + consultaLog.getCondition(i).getValue()
					+ "'";
		}

		sql += " ORDER BY TIMESTAMP";

		Connection conn = null;
		ResultSet rs = null;
		try {
			conn = Q70ConectorJDBC.getSingleton().getConnection(dataSource);
			Statement st = conn.createStatement();
			rs = st.executeQuery(sql);

			while (rs.next()) {
				if (logName.equals(Q70ConstantesLogs.LOG_ACCESOS)) {
					contAccesos ++;
				} else if (logName.equals(Q70ConstantesLogs.LOG_NAVEGACION)) {
					contNavegacion ++;
				} else if (logName.equals(Q70ConstantesLogs.LOG_CONECTORES)) {
					contConectores ++;
				} else if (logName.equals(Q70ConstantesLogs.LOG_TRANSACCIONES)) {
					contTransacciones ++;
				} else if (logName.equals(Q70ConstantesLogs.LOG_INCIDENCIAS)) {
					contIncidencias ++;
				}
				
				Q70ApunteLog apunteLog = new Q70ApunteLog();
				String line = "";
				apunteLog.setFecha(rs.getString(Q70ConstantesLogs.TIMESTAMP));
				String valorColumna = "";
				// Obtener las columnas genericas
				for (int i = 0; i < globalFields.size(); i++) {
					// Si la columna no está en la base de datos no sacarla
					try {
						Q70Columna columna = (Q70Columna) globalFields.get(i);
						valorColumna = rs.getString(columna.getNombre());
						line += valorColumna + " ";
					} catch (SQLException sqle) {
					}

				}
				// obtener las columnas de mensaje
				for (int i = 0; i < MessageFields.size(); i++) {
					try {
						Q70Columna columna = (Q70Columna) MessageFields.get(i);
						valorColumna = rs.getString(columna.getNombre());
						line += valorColumna + " ";
					} catch (SQLException sqle) {
					}
				}

				// quedarse con la primera linea
				if (line.indexOf("\r") != -1) {
					apunteLog.setLinea(line.substring(0, line.indexOf("\n", 1)));
					apunteLog.setDetalle(line);
				} else {
					apunteLog.setLinea(line);
					apunteLog.setDetalle(line);
				}

				apunteLog.setLog(formattedLog);
				if (((logName.equals(Q70ConstantesLogs.LOG_ACCESOS)) && (contAccesos <= numRegistrosLog)) ||
						((logName.equals(Q70ConstantesLogs.LOG_CONECTORES)) && (contConectores <= numRegistrosLog)) ||
						((logName.equals(Q70ConstantesLogs.LOG_INCIDENCIAS)) && (contIncidencias <= numRegistrosLog)) ||
						((logName.equals(Q70ConstantesLogs.LOG_TRANSACCIONES)) && (contTransacciones <= numRegistrosLog)) ||
						((logName.equals(Q70ConstantesLogs.LOG_NAVEGACION)) && (contNavegacion <= numRegistrosLog))) {
							results.add(apunteLog);
				}
			}
		} catch (Exception e) {
			Q70TrazaInterface traza = Q70Factoria.getTraza();
			if (traza.isTraceActive()){
				traza.trace(Q70ConstantesLogs.LOG, Q70TraceLevel.ERROR, "Se ha producido un error en el método ExecuteQuery de la clase Q70BuscadorBDLog");
			}
			throw new Q70FrameworkException(Q70ConstantesLogs.LOG,this.getClass().toString(),"ExecuteQuery","Se ha producido un error en el método ExecuteQuery.",e);
		} finally {

			if (rs != null)
				try {
					rs.close();
				} catch (SQLException e) {
					Q70GestorDeExcepcionesServidor.getSingleton().recogerThrowable(e);
				}

			try {
				if (conn != null && !conn.isClosed())
					conn.close();
			} catch (SQLException e) {
				Q70GestorDeExcepcionesServidor.getSingleton().recogerThrowable(e);
			}
		}

		return results;
	}

	public Date getDate(String fecha)
	{
		Date date = null;
		try {
			date = new SimpleDateFormat(Q70ConstantesLogs.DATE_FORMAT).parse(fecha);
		} catch (ParseException e) {
		}

		return date;
	}
	private String addSpaces(int spacesNumber)
	{
		StringBuffer s = new StringBuffer();
		for (int i = 0; i < spacesNumber; i++)
		{
			s.append(" ");
		}
		return s.toString();
	}

	private String getFormattedColumn(String value, int size)
	{
		//si el valor es mayor que el maximo entonces truncar
		String ret = null;
		if (size == 0)
			return value;
		if (value == null)
			ret = addSpaces(size);
		else
		{
			int longitud = value.length();
			if (longitud > size)
				ret = value.substring(0, size);
			else
				if (longitud == size)
					ret = value;
				else
					ret = value + addSpaces(size - longitud);
		}
		return ret;
	}
}
