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

import org.apache.commons.beanutils.DynaBean;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

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;
import es.ejie.frmk.infraestructura.utilidades.mapeador.Q70ArgumentoAdaptadorInvocacion;
import es.ejie.frmk.infraestructura.utilidades.mapeador.Q70GestorMapeador;
import es.ejie.frmk.infraestructura.utilidades.mapeador.Q70Mapa;
import es.ejie.frmk.infraestructura.utilidades.mapeador.Q70ObjetoContextoInicial;
import es.ejie.frmk.infraestructura.utilidades.xml.Q70UtilidadesXML;
import es.ejie.frmk.negocio.operacioninterna.Q70InformacionInvocacion;

/**
 * Clase que realiza el mapeo de submapeos a n niveles
 */
public class Q70MapaReferenciaMapa implements Q70Mapa{
	
	// variables miembro
	
	private Node nodoMapa = null;
	private String strXMLMapas = Q70UtilidadesConstantes.ELEMENTO_MAPAS;	
	private String strXMLMapa = Q70UtilidadesConstantes.ELEMENTO_MAPA;
	private String strXMLRef = Q70UtilidadesConstantes.ATRIBUTO_REF;
	private String strXMLNombre = Q70UtilidadesConstantes.ATRIBUTO_NOMBRE;
	private String strXMLTipoArgumento = Q70UtilidadesConstantes.ATRIBUTO_TIPOARGUMENTO;
	private String strXMLNombreArgumento = Q70UtilidadesConstantes.ATRIBUTO_NOMBREARGUMENTO;
	private String strXMLTipoBean = Q70UtilidadesConstantes.ATRIBUTO_TIPOBEAN;
	private String strMapaRef = null;
	
	
	// métodos miembro
	
	/**
	 * Constructor de la clase
	 */
	public Q70MapaReferenciaMapa() {
		super();
	}
	/**
	 * Constructor de la clase alternativo
	 */
	public Q70MapaReferenciaMapa(Node newNodoMapa) {
		super();
		this.nodoMapa = newNodoMapa;
	}

	public void makeMap(Object objContextoInicial, Object objContextoFinal) throws Q70UtilidadesExcepcion{
		
		try {
		
		// recuperar nodelist de mapas del mapa de mapas y instanciar argumento
		NodeList nodListMapas = Q70UtilidadesXML.searchDomNodeList(nodoMapa, strXMLMapa );
		int num = nodListMapas.getLength();
		Q70ArgumentoAdaptadorInvocacion argumentoAdaptadorInvocacion = new Q70ArgumentoAdaptadorInvocacion(nodListMapas);
		int count = 0;
			
				
			for(count = 0 ; count < num ; count++){
				
				boolean bolTipoArgumento = false;
				boolean bolNombreArgumento = false;
				boolean bolTipoBean = false;
				boolean bolTransferencias = false;
			
				strMapaRef = Q70UtilidadesXML.searchNodeAtribute(nodListMapas.item(count),strXMLRef);
				Node nodoMapaRef = Q70UtilidadesXML.searchDomNode(nodoMapa.getOwnerDocument(),"/"+strXMLMapas+"/"+
																strXMLMapa+"[@"+strXMLNombre+"='"+strMapaRef+"']");
				
				// recoger los distintos casos de submapeos EJB
				
				bolTipoArgumento = Q70UtilidadesXML.bolAtributeExist(nodoMapaRef,strXMLTipoArgumento);						 
				bolNombreArgumento = Q70UtilidadesXML.bolAtributeExist(nodoMapaRef,strXMLNombreArgumento);
				bolTipoBean = Q70UtilidadesXML.bolAtributeExist(nodoMapaRef,strXMLTipoBean);
				bolTransferencias = nodoMapaRef.hasChildNodes();
				
				// determinar si el segundo argumento es un InformacionInvocación e instanciar Contexto Inicio
				
				DynaBean dynContextoInicial = new Q70ObjetoContextoInicial(objContextoInicial).getInicialDynaBean();
											
				if ( objContextoFinal instanceof Q70InformacionInvocacion ){
				// caso de contexto a argumento adaptador invocacion	
					
					Object objBeanContextoInicial = null;
					Object objBeanArgumentoFinal = null;

					if( bolTransferencias == false){
						// de propiedad del contexto a argumento adaptador invocación
						Q70GestorMapeador gestorMapeador = Q70GestorMapeador.getSingleton();
						gestorMapeador.mapObjects(strMapaRef, objContextoInicial, argumentoAdaptadorInvocacion);
						
						
					} else {
					
						if ( (bolTipoArgumento == true) && (bolNombreArgumento == true) ){
						// de bean del contexto a bean		
							objBeanContextoInicial =  dynContextoInicial.get(Q70UtilidadesXML.searchNodeAtribute(nodoMapaRef, strXMLNombreArgumento));
					 		objBeanArgumentoFinal = (Object)(Thread.currentThread().getContextClassLoader()).loadClass(Q70UtilidadesXML.searchNodeAtribute(nodoMapaRef, strXMLTipoArgumento)).newInstance();
							Q70GestorMapeador gestorMapeador =  Q70GestorMapeador.getSingleton();
							gestorMapeador.mapObjects(strMapaRef, objBeanContextoInicial, objBeanArgumentoFinal);

						} else if ( (bolTipoArgumento == true) && (bolTipoBean == true) ){
						// de contexto a bean creado dinámicamente	
							objBeanContextoInicial = objContextoInicial;
							objBeanArgumentoFinal = (Object)(Thread.currentThread().getContextClassLoader()).loadClass(Q70UtilidadesXML.searchNodeAtribute(nodoMapaRef, strXMLTipoBean)).newInstance();	 	
							Q70GestorMapeador gestorMapeador = Q70GestorMapeador.getSingleton();
							gestorMapeador.mapObjects(strMapaRef, objBeanContextoInicial, objBeanArgumentoFinal);
					
						} else if ( (bolTipoArgumento == true) && (bolNombreArgumento == false ) && (bolTipoBean == false) ) {
						// de contexto a bean creado dinámicamente	
							objBeanContextoInicial = objContextoInicial;
							objBeanArgumentoFinal = (Object)(Thread.currentThread().getContextClassLoader()).loadClass(Q70UtilidadesXML.searchNodeAtribute(nodoMapaRef, strXMLTipoArgumento)).newInstance();	 	
							Q70GestorMapeador gestorMapeador = Q70GestorMapeador.getSingleton();
							gestorMapeador.mapObjects(strMapaRef, objBeanContextoInicial, objBeanArgumentoFinal);
						
						}
					
						argumentoAdaptadorInvocacion.addElement(objBeanArgumentoFinal, objBeanArgumentoFinal.getClass());

					}
						
								 
				} else {
					throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_MAPEADOR,
					"Q70MapaReferenciaMapa","makeMap",Q70UtilidadesErrores.UTILIDADES_MAPEADOR_ARGUMENTO_ADAPTADOR_INVOCACION);										
				}
			
			}	
		
		Q70InformacionInvocacion infInvObjContextoFinal = (Q70InformacionInvocacion) objContextoFinal ;
		infInvObjContextoFinal.setParametros(argumentoAdaptadorInvocacion.getParametros());
		infInvObjContextoFinal.setTipoParametros(argumentoAdaptadorInvocacion.getTipoParametros());
								
		} catch (Q70UtilidadesExcepcion ue){
			throw ue;
		} catch ( Exception e){
			throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_MAPEADOR,
			"Q70MapaReferenciaMapa","makeMap",Q70UtilidadesErrores.UTILIDADES_MAPEADOR_GENERICO);													
		}
		
	}

}
