package es.ejie.frmk.infraestructura.tablas;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.collections.CollectionUtils;

import es.ejie.frmk.Q70Factoria;
import es.ejie.frmk.Q70FactoriaConstantes;
import es.ejie.frmk.infraestructura.logs.incidencias.Q70LogIncidenciasInterface;
import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;
import es.ejie.frmk.infraestructura.traza.Q70Traza;
import es.ejie.frmk.infraestructura.utilidades.concurrencia.Q70Lock;


/**
 * Esta clase debe controlar el número máximo de tablas en memoria que pueden residir en la aplicación Geremua donde 
 * está configurada. Paraello, su comportamiento será el siguiente:
 * <ul>
 * <li>Preguntar al componente de servidor, almacenado en su variable ‘componenteServidor’, cuántas tablas en 
 * memoria puede almacenar </li>
 * <li>La clase Q70GestorTablasCodigosServidor debe almacenar el número máximo de tablas en memoria permitidas 
 * por aplicación </li>
 * <li>Si contiene más tablas de las permitidas, se tracea un error y se hace log sobre el log de incidencias</li>
 * <li>Se almacenarán las tablas en memoria mientras no se supere el número maximo permitido. El criterio para 
 * que dichas tablas estén en memoria es que cuando vaya a ser usada todavía no se haya superado dicho número máximo </li>
 * <li>Nuevo atributo en el fichero xml de configuración de servidor 'config/q70/frmkcore/configuracionTablas.xml' 
 * llamado <b>maximoEnMemoriaAplicacion</b> </li>
 * </ul>
 * @version 2.0   Fecha 20-feb-2006
 */
public class Q70GestorTablasCodigosAplicacion extends Q70GestorTablasCodigosBase{

	private static Q70GestorTablasCodigosAplicacion instancia = null;
	private static Q70Traza traza = Q70Traza.getSingleton();
	private Q70LogIncidenciasInterface logInc = Q70Factoria.getLogIncidencias();
	
	private Q70GestorTablasCodigosAplicacion() {
		super();
		setLock(new Q70Lock(Q70FactoriaConstantes.ID_GESTOR_TABLASCODIGOS));
	}
	
	/** 
	 * Método estático que devuelve la única instancia de la clase <code>Q70GestorTablasCodigosAplicacion</code>.
	 * @return Instancia de Q70GestorTablasCodigosAplicacion
	 */
	public static Q70GestorTablasCodigosAplicacion getSingleton() {
		if (instancia == null) {
			instancia = new Q70GestorTablasCodigosAplicacion();
		}
		return instancia;
	}
	
	/**
	 * @see es.ejie.frmk.infraestructura.tablas.Q70GestorTablasCodigosBase#doDestruir()
	 */
	protected void doDestruir() {
		instancia = null;
	}
	
	/**
	 * @see es.ejie.frmk.infraestructura.tablas.Q70GestorTablasCodigosServidorInterface#setCatalog(es.ejie.frmk.infraestructura.tablas.Q70Catalogo)
	 */
	public void setCatalog(Q70Catalogo catalogo) throws Q70GestorTablasException{
		try {
			Collection tablasDuplicadas = CollectionUtils.intersection(catalogo.getTablas().keySet(), Q70GestorTablasCodigosServidor.getSingleton().getCatalog().getTablas().keySet());
			String nombreTabla ="";
			for (Iterator iter = tablasDuplicadas.iterator(); iter.hasNext();) {
				nombreTabla = (String) iter.next();
				if (traza.isTraceActive()){
					traza.trace(Q70Constantes.ID_COMPONENTE, Q70TraceLevel.ERROR, "Se esta intentando añadir una tabla al catalogo con el nombre logico '"+nombreTabla+"', el cual ya existe en el catalogo de servidor");
				}		
				if (logInc.isEnabled())
					logInc.log(new Q70GestorTablasException(this.getClass().getName(), "setCatalog", "Se esta intentando añadir una tabla al catalogo con el nombre logico '"+nombreTabla+"', el cual ya existe en el catalogo de servidor",null));

				doRemoveTablaCatalogo(catalogo, nombreTabla);	
			}
			super.setCatalog(catalogo);
		} catch (Exception e) {
			if (traza.isTraceActive()){
				traza.trace(Q70Constantes.ID_COMPONENTE, Q70TraceLevel.ERROR, "Se esta producido un error en el método setCatalog de la clase Q70GestorTablasCodigosAplicacion");
			}
			throw new Q70GestorTablasException(this.getClass().toString(),"setCatalog","Se ha producido un error en el método setCatalog",e);
		}
	}

	/**
	 * @see es.ejie.frmk.infraestructura.tablas.Q70GestorTablasCodigosInterface#selectRecordsFromTable(java.lang.String, java.lang.String, java.lang.String, java.util.Vector)
	 */
	public ArrayList selectRecordsFromTable(String idTabla, String condicion, String idioma, Vector columns) throws Q70GestorTablasException, Exception {
		if (Q70GestorTablasCodigosServidor.getSingleton().tableExist(idTabla)){
			return Q70GestorTablasCodigosServidor.getSingleton().selectRecordsFromTable(idTabla, condicion, idioma, columns);
		}
		return super.selectRecordsFromTable(idTabla, condicion, idioma, columns);
	}
	
	/**
	 * @see es.ejie.frmk.infraestructura.tablas.Q70GestorTablasCodigosServidorInterface#tableExist(java.lang.String)
	 */
	public boolean tableExist(String nombreTabla) {
		if (super.tableExist(nombreTabla)){
			return true;
		}
		return Q70GestorTablasCodigosServidor.getSingleton().tableExist(nombreTabla);
	}

	/**
	 * @see es.ejie.frmk.infraestructura.tablas.Q70GestorTablasCodigosServidorInterface#getInfoTable(java.lang.String)
	 */
	public Map getInfoTable(String nombreTabla){
		if (Q70GestorTablasCodigosServidor.getSingleton().tableExist(nombreTabla)){
			return Q70GestorTablasCodigosServidor.getSingleton().getInfoTable(nombreTabla);
		}
		return super.getInfoTable(nombreTabla);
	}
	
	/**
	 * @see es.ejie.frmk.infraestructura.tablas.Q70GestorTablasCodigosBase#isSobrepasadoMaximoTablasEnMem()
	 */
	protected boolean isSobrepasadoMaximoTablasEnMem() {
		return (Q70GestorTablasCodigosServidor.getSingleton().getMaximoNumeroTablasEnMemoria() == getNumTablasCargadasEnMemoria());
	}
}