package es.ejie.frmk.infraestructura.utilidades.mapeador;

import java.io.InputStream;

import es.ejie.frmk.Q70Factoria;
import es.ejie.frmk.control.arranque.Q70Arrancable;
import es.ejie.frmk.control.arranque.Q70GestorArranqueConfiguracionServidor;
import es.ejie.frmk.control.excepciones.Q70FrameworkException;
import es.ejie.frmk.infraestructura.poolCache.Q70Constantes;
import es.ejie.frmk.infraestructura.poolCache.Q70GestorCacheServidorInterface;
import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;
import es.ejie.frmk.infraestructura.traza.Q70TrazaInterface;
import es.ejie.frmk.infraestructura.utilidades.constantes.Q70UtilidadesConstantes;
import es.ejie.frmk.infraestructura.utilidades.excepciones.Q70GenerarUtilidadesExcepcion;
import es.ejie.frmk.infraestructura.utilidades.excepciones.Q70UtilidadesErrores;
import es.ejie.frmk.infraestructura.utilidades.excepciones.Q70UtilidadesExcepcion;

/**
 * Este componente se encarga de construir y ejecutar mapeos.
 * <p>
 * Un mapeo es un proceso que permite transferir datos entre un origen y un destino.
 * Los mapeos son clases que cumplen la interfaz <b>Q70Mapa</b> 
 * y pueden llevar conversiones de tipos a través de clases que cumplen la interfaz <b>Converter</b>.
 * <p>
 * El nombre del dato en el origen puede ser distinto que en el destino. 
 * Estos orígenes y destinos pueden ser contextos u otros objetos.
 * Los mapeos se pueden definir de manera declarativa en XML 
 * y encuentran aplicaciones en distintos puntos de Geremua, 
 * contribuyendo a crear una manera de trabajar homogénea en el desarrollador minimizando la programación Java.
 * <p>
 * El Gestor de Mapeos es un componente de aplicación, 
 * por lo que sólo hay una instancia activa para cada aplicación con su correspondiente fichero de mapas.
 * <p>
 * El Gestor de Mapeos implementa la interfaz Arrancable y es arrancado por el Gestor de Arranque y Configuración.
 * <p>
 * Se usa a través del método <b>mapObjects</b>
 *
 * @version 1.0
 * @author UFRM005
 *    
 */
public class Q70GestorMapeador implements Q70Arrancable
{

	// variables miembro

	//private HashMap hashConverters = null;
	private String strFicheroXMLMapas = null;
	private String strFicheroXMLConfiguracion = null;
	private static final String COMPONENTE = "Q70GestorMapeador";
	
	// instanciar factoria	
	private Q70FactoriaMapas factoriaMapas = null;
		
	// métodos
	/**
	 * Constructor de la clase, private para generar el singleton
	 * */
	private Q70GestorMapeador()
	{
		super();
	}

	/**
	 * Método que devuelve la instancia de singleton
	 * @return instancia Q70GestorMapeador instancia de la clase singleton 
	 */
	public static Q70GestorMapeador getSingleton()
	{

		Q70GestorMapeador instancia = (Q70GestorMapeador)Q70GestorArranqueConfiguracionServidor.getAttribute(COMPONENTE);
		if (instancia == null)
		{
			instancia = new Q70GestorMapeador();
			Q70GestorArranqueConfiguracionServidor.setAttribute(COMPONENTE, instancia);

		}
		return instancia;

	}

	/**
	 * Método que el gestor de arranque y configuración ejecuta al crear la instancia de singletón
	 * @see es.ejie.frmk.control.Arrancable
	 * **/
	public void afterCreate(String newStrFicheroXMLConfiguracion) throws Q70FrameworkException
	{
		strFicheroXMLConfiguracion = newStrFicheroXMLConfiguracion;
		InputStream inputStreamFicheroXMLConfiguracion = Q70GestorArranqueConfiguracionServidor.getApplicationConfigAsStream(strFicheroXMLConfiguracion);
		Q70ConfiguradorMapeador clsConfiguradorMapeador = new Q70ConfiguradorMapeador(inputStreamFicheroXMLConfiguracion);

		try
		{
			clsConfiguradorMapeador.generateConfiguration();
			factoriaMapas = new Q70FactoriaMapas(strFicheroXMLMapas);
		}
		catch (Q70UtilidadesExcepcion ue)
		{
			Q70TrazaInterface clsTraza = Q70Factoria.getTraza();
			if (clsTraza.isTraceActive()){
				clsTraza.trace(COMPONENTE, Q70TraceLevel.ERROR, Q70UtilidadesErrores.UTILIDADES_MAPEADOR_CONFIGURACION);
			}
			throw new Q70FrameworkException(COMPONENTE,this.getClass().toString(),"afterCreate","Se ha producido un error en el método afterCreate.",ue);
		}
	}

	/**
	 * @see es.ejie.frmk.control.Arrancable
	 */
	public void beforeDestroy() throws Q70FrameworkException
	{
		Q70GestorCacheServidorInterface gestorCache = (Q70GestorCacheServidorInterface) Q70Factoria.getGestorCache();
		gestorCache.freeCached(Q70Constantes.CACHE_MAPAS);
	}

	/**
	 * Método que el gestor de arranque ejecuta para reconfigurar la instancia de singletón
	 * @see es.ejie.frmk.control.Arrancable
	 * */
	public void reConfigure() throws Q70FrameworkException
	{
		Q70GestorCacheServidorInterface gestorCache = (Q70GestorCacheServidorInterface) Q70Factoria.getGestorCache();
		gestorCache.freeCached(Q70Constantes.CACHE_MAPAS);
		
		afterCreate(strFicheroXMLConfiguracion);
	}

	/**
	 * Método para poner HashMap de pares (class converter , class destino)
	 * @param newHashConverteres HashMap de pares de class converter, class destino
	 */
//	public void setHashConverters(HashMap newHashConverters)
//	{
//		hashConverters = newHashConverters;
//	}

	/**
	 * Método para poner el path del fichero xml de mapas
	 * @param newStrXMLMapFile String path del fichero de mapas de gestor mapeador
	 */
	public void setStrXMLMapFile(String newStrXMLMapFile) 
	{
			strFicheroXMLMapas = newStrXMLMapFile;
	}

	/**
	 * Método que llama a la factoria de mapas con los parametros para realizar el mapeo.
	 * <p>
	 * Ejemplo: <b>Q70GestorMapeador.getSingleton().mapObjects(mapaInvocacion, contexto, informacionParametros);</b>
	 * @param strNombreMapa String con el nombre del mapa del xml de mapas o constantes
	 * @param  objContextoInicial Object inicial del mapeo (contexto o bean)
	 * @param  objContextoFinal Object final del mapeo (contexto, bean, argumento de invocación)
	 * */
	public void mapObjects(String strNombreMapa, Object objContextoInicial, Object objContextoFinal)
		throws Q70UtilidadesExcepcion
	{

		if ((strNombreMapa == null) || (objContextoInicial == null) || (objContextoFinal == null))
		{
			throw Q70GenerarUtilidadesExcepcion.createUtilityException(
				Q70UtilidadesConstantes.UTILIDADES_MAPEADOR,
				"Q70GestorMapeador",
				"mapObjects",
				Q70UtilidadesErrores.UTILIDADES_MAPEADOR_ARGUMENTOS_MAPEO);
		}
		else
		{
			// recuperar mapa
			Q70Mapa clsMapa = factoriaMapas.returnMap(strNombreMapa);
			// hacer mapeo
			clsMapa.makeMap(objContextoInicial, objContextoFinal);
		}
	}

}
