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

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import es.ejie.frmk.Q70Factoria;
import es.ejie.frmk.control.arranque.Q70GestorArranqueConfiguracionServidor;
import es.ejie.frmk.infraestructura.poolCache.Q70Constantes;
import es.ejie.frmk.infraestructura.poolCache.Q70GestorCacheServidorInterface;
import es.ejie.frmk.infraestructura.utilidades.constantes.Q70UtilidadesConstantes;
import es.ejie.frmk.infraestructura.utilidades.excepciones.Q70UtilidadesExcepcion;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaBeanPropiedades;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaPropiedadArgumento;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaPropiedadContexto;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaPropiedadesBean;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaReferenciaMapa;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaSimple;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaTodas;
import es.ejie.frmk.infraestructura.utilidades.mapeador.mapas.Q70MapaTodasListaAtributos;
import es.ejie.frmk.infraestructura.utilidades.xml.Q70UtilidadesXML;

/**
 * Clase factoría que recibe parametros y devuelve un objeto de tipo mapa
 * adecuado.
 * @author UFRM005
 * @version 1.0
 */
public class Q70FactoriaMapas {

	private static final Q70MapaTodas mapaTodasInstancia = new Q70MapaTodas();
	private String strFicheroXMLMapas = null;
	private Document docMapas = null;
	private boolean bolFlagNombreDestinoEnContexto = false;
	private boolean bolFlagNombreOrigenEncontexto = false;
	private boolean bolFlagRef = false;
	private boolean bolFlagTipoBean = false;
	private boolean bolFlagTransferencias = false;
	private String strXMLMapas = Q70UtilidadesConstantes.ELEMENTO_MAPAS;
	private String strXMLMapa = Q70UtilidadesConstantes.ELEMENTO_MAPA;
	private String strXMLNombreMapa = Q70UtilidadesConstantes.ATRIBUTO_NOMBRE;
	private String strXMLNombreDestinoEnContexto = Q70UtilidadesConstantes.ATRIBUTO_NOMBREDESTINOCONTEXTO;
	private String strXMLNombreOrigenEnContexto = Q70UtilidadesConstantes.ATRIBUTO_NOMBREORIGENCONTEXTO;
	private String strXMLRef = Q70UtilidadesConstantes.ATRIBUTO_REF;
	private String strXMLTipoBean = Q70UtilidadesConstantes.ATRIBUTO_TIPOBEAN;

	/**
	 * Constructor de la clase
	 */
	public Q70FactoriaMapas() {
		super();
	}

	/**
	 * Constructor de la clase alternativo
	 * @param newStrFicheroXMLMapas String nombre y path completo del fichero de
	 *            mapas
	 */
	public Q70FactoriaMapas(String newStrFicheroXMLMapas) throws Q70UtilidadesExcepcion {

		super();

		try {
			// se guarda el path del fichero de mapas
			strFicheroXMLMapas = newStrFicheroXMLMapas;
			// se carga el documento xml de mapas
			docMapas = Q70UtilidadesXML.getDocumentXMLInputStream(Q70GestorArranqueConfiguracionServidor.getResourceAsStream(Q70GestorArranqueConfiguracionServidor.getPathAplicacion(strFicheroXMLMapas)));
		} catch (Q70UtilidadesExcepcion ue) {
			throw ue;
		}
	}

	/**
	 * Método que carga una clase de mapa u otra según los datos del xml de
	 * mapas
	 * @param strNombreMapa String nombre del mapa en el xml de mapas
	 * @param objContextoInicial Object objecto inicial del mapa
	 * @param objContextoFinal Object objecto final del mapa
	 * @return Q70Mapa instancia de una clase mapa que realiza el mapeo
	 * @throws Q70UtilidadesExcepcion
	 */
	public Q70Mapa returnMap(String strNombreMapa) throws Q70UtilidadesExcepcion {

		Q70Mapa mapa = null;

		if (strNombreMapa.equalsIgnoreCase(Q70UtilidadesConstantes.MAPA_TODAS_PROPIEDADES)) {
			mapa = mapaTodasInstancia;
		} else {
			if (strNombreMapa.equalsIgnoreCase(Q70UtilidadesConstantes.MAPA_TODAS_PROPIEDADES_LISTA)) {
				mapa = new Q70MapaTodasListaAtributos();
			} else {
				// se genera una clase mapa según las condiciones buscando en cache
				/** @version 2.0 Fecha: 01-mar-2006 */
				Q70GestorCacheServidorInterface gestorCache = (Q70GestorCacheServidorInterface) Q70Factoria.getGestorCache();
				mapa = (Q70Mapa) gestorCache.getElement(Q70Constantes.CACHE_MAPAS, strNombreMapa);

				if (mapa == null) {
					// se recupera el node con el mapa
					Node nodoMapa = Q70UtilidadesXML.searchDomNode(docMapas, "/" + strXMLMapas + "/" + strXMLMapa + "[@" + strXMLNombreMapa + "='" + strNombreMapa + "']");

					// se extraen los atributos del mapa
					bolFlagNombreDestinoEnContexto = Q70UtilidadesXML.bolAtributeExist(nodoMapa, strXMLNombreDestinoEnContexto);
					bolFlagNombreOrigenEncontexto = Q70UtilidadesXML.bolAtributeExist(nodoMapa, strXMLNombreOrigenEnContexto);
					bolFlagTipoBean = Q70UtilidadesXML.bolAtributeExist(nodoMapa, strXMLTipoBean);

					bolFlagRef = Q70UtilidadesXML.bolNodeExist(nodoMapa, strXMLMapa + "/@" + strXMLRef);
					bolFlagTransferencias = nodoMapa.hasChildNodes();

					// si el mapa no esta cacheado se crea
					if ((bolFlagNombreDestinoEnContexto == true) && (bolFlagTipoBean == true)) {
						// mapa propiedades a bean
						mapa = new Q70MapaPropiedadesBean(nodoMapa);
						gestorCache.addElement(Q70Constantes.CACHE_MAPAS, strNombreMapa, mapa);
					} else if (bolFlagNombreOrigenEncontexto == true) {
						// mapa bean a propiedades
						mapa = new Q70MapaBeanPropiedades(nodoMapa);
						gestorCache.addElement(Q70Constantes.CACHE_MAPAS, strNombreMapa, mapa);
					} else if (bolFlagRef == true) {
						// mapa referencia a mapa
						mapa = new Q70MapaReferenciaMapa(nodoMapa);
						gestorCache.addElement(Q70Constantes.CACHE_MAPAS, strNombreMapa, mapa);
					} else if ((bolFlagTransferencias == false) && (bolFlagNombreDestinoEnContexto == false)) {
						// mapa propiedad a argumento
						mapa = new Q70MapaPropiedadArgumento(nodoMapa);
						gestorCache.addElement(Q70Constantes.CACHE_MAPAS, strNombreMapa, mapa);
					} else if ((bolFlagTransferencias == false) && (bolFlagNombreDestinoEnContexto == true)) {
						// mapa objecto a propiedad en contexto
						mapa = new Q70MapaPropiedadContexto(nodoMapa);
						gestorCache.addElement(Q70Constantes.CACHE_MAPAS, strNombreMapa, mapa);
					} else {
						// mapa simple
						mapa = new Q70MapaSimple(nodoMapa);
						gestorCache.addElement(Q70Constantes.CACHE_MAPAS, strNombreMapa, mapa);
					}
				}
			}
		}
		return mapa;
	}
}
