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

import java.io.File;
import java.io.InputStream;
import java.io.StringReader;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

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;

/**
 * Proporciona la configuración a los componentes que cumplan la interfaz <b>Q70Configurable</b>.
 * <p>
 * El <b>Configurador</b> es un componente de utilidad  instanciado por los componentes arrancables.
 * Se encarga de proporcionar al resto de componentes de Geremua su información de configuración. 
 * Estos componentes se denominan componentes configurables.
 * <p>
 * El configurador accede a esa información que está en ficheros XML y la procesa, 
 * de manera que al entregársela a los componentes les evita este trabajo común a todos ellos de procesado 
 * (lectura SAX del fichero XML).
 * <p>
 * Un componente configurable es un componente que implementa la interfaz <b>Q70Configurable</b>
 * que permita que se configure (por primera vez) y reconfigure (en caliente) mediante el proceso descrito.
 * 
 * @author UFRM005
 * @version 1.0 
 */

public class Q70Configurador {
	
	// variables miembro
	private String codigoAplicacion = null;
	private Q70Configurable objComponente = null;
	private String strFichero = null;
	private StringBuffer bufTextoXML = null;
	private File filFicheroXML = null; 
	private InputStream inputStreamXML = null;	
	protected static final String COMPONENTE = "Q70Configurador";
	private boolean aplicarIndireccion = true;
		
	// métodos
	
	/**
	 * Constructor de la Clase 
	 */
	public Q70Configurador() {
		super();
	}
	
	/**
	 * Constructor de la Clase alternativo
	 * @param newObjComponent Object Object de la clase componente 
	 * @param newStrFile String Path del fichero XML
	 */
	public Q70Configurador( Q70Configurable newObjComponent, String newStrFile ) {
		super();
		this.objComponente = newObjComponent;
		this.strFichero = newStrFile;
	}
	
	/**
	 * Constructor de la Clase alternativo
	 * @param objComponent Object Object de la clase componente 
	 * @param newBufFile StringBuffer Buffer del texto XML
	 */
	public Q70Configurador( Q70Configurable newObjComponent, StringBuffer newBufFile ) {
		super();
		this.objComponente = newObjComponent;
		this.bufTextoXML = newBufFile;
	}
	/**
	  * Constructor de la Clase alternativo
	  * @param objComponent Object Object de la clase componente 
	  * @param newFilFileXML File Fichero del texto XML
	  */
	public Q70Configurador( Q70Configurable newObjComponent, File newFilFileXML ) {
		super();
		this.objComponente = newObjComponent;
		this.filFicheroXML = newFilFileXML;
	}
	
	/**
	  * Constructor de la Clase alternativo
	  * @param objComponent Object Object de la clase componente 
	  * @param newInputStreamXML InputStream del texto XML
	  */
	public Q70Configurador( Q70Configurable newObjComponent, InputStream newInputStreamXML ) {
		super();
		this.objComponente = newObjComponent;
		this.inputStreamXML = newInputStreamXML;
	}

	/**
	  * Constructor de la Clase alternativo
	  * @param objComponent Object Object de la clase componente 
	  * @param newInputStreamXML InputStream del texto XML
	  */
	public Q70Configurador( Q70Configurable newObjComponent, InputStream newInputStreamXML, String aplicacionCodigo ) {
		super();
		this.objComponente = newObjComponent;
		this.inputStreamXML = newInputStreamXML;
		this.codigoAplicacion = aplicacionCodigo;
	}
	
	/**
	  * Constructor de la Clase alternativo
	  * @param objComponent Object Object de la clase componente 
	  * @param newInputStreamXML InputStream del texto XML
	  */
	public Q70Configurador( Q70Configurable newObjComponent, InputStream newInputStreamXML, boolean aplicarIndireccion ) {
		this(newObjComponent,newInputStreamXML);
		this.aplicarIndireccion = aplicarIndireccion;
	}	
	
	/**
	 * Constructor de la Clase alternativo
	 * @param objComponent Object Object de la clase componente 
	 * @param newBufFile StringBuffer Buffer del texto XML
	 * @param aplicarIndireccion boolean para aplicar o no indirección
	 */
	public Q70Configurador( Q70Configurable newObjComponent, StringBuffer newBufFile, boolean aplicarIndireccion ) {
		this(newObjComponent, newBufFile);
		this.aplicarIndireccion = aplicarIndireccion;
	}
		
	/**
	 * Método set de Object del componente
	 * @param newObjComponent
	 */
	public void setObjComponent( Q70Configurable newObjComponent ){
		objComponente = newObjComponent;
	}
	/**
	 * Método set de String del fichero
	 * @param newStrFile
	 */
	public void setStrFile( String newStrFile ){
		strFichero = newStrFile;
	}
	
	/**
	 * Método set de Buffer del texto XML
	 * @param newBufTextoXML
	 */
    public void setBufTextXML( StringBuffer newBufTextXML ){
			bufTextoXML = newBufTextXML;
	}
	
	/**
	 * Método set de File del texto XML
	 * @param newFilFicheroXML
	 */
	public void setFilFileXML( File newFilFileXML ){
			filFicheroXML = newFilFileXML;
	}
	
	/**
	 * Método set de InputStream del texto XML
	 * @param newInputStreamXML
	 */
	public void setInputStreamXML( InputStream newInputStreamXML ){
				inputStreamXML = newInputStreamXML;
	}
	
	/**
	 * Método que lee la configuración y se la pasa a la clase
	 * @param newObjComponent Object Objeto que representa el componente
	 * @param newStrFile String Path del fichero de configuración del componente
	 */
	
	public void generateConfiguration(Q70Configurable newObjComponent, String newStrFile) throws Q70UtilidadesExcepcion{
		objComponente = newObjComponent;
		strFichero = newStrFile;
		generateConfiguration();
	}
	
	/**
	 * Método que lee la configuración y se la pasa a la clase
	 * @param newObjComponent Object Objeto que representa el componente
	 * @param newBufTextXML String Path del fichero de configuración del componente
	 * @throws Q70UtilidadesExcepcion
	 */
	
	public void generateConfiguration(Q70Configurable newObjComponent, StringBuffer newBufTextXML) throws Q70UtilidadesExcepcion{
		objComponente = newObjComponent;
		bufTextoXML = newBufTextXML;
		generateConfiguration();
	}
	
	/**
	 * Método que lee la configuración y se la pasa a la clase
	 * @param newObjComponent Object Objeto que representa el componente
	 * @param newFilFileXML File File del fichero de configuración del componente
	 * @throws Q70UtilidadesExcepcion
	 */
	
	public void generateConfiguration(Q70Configurable newObjComponent, File newFilFileXML) throws Q70UtilidadesExcepcion{
		objComponente = newObjComponent;
		filFicheroXML = newFilFileXML;
		generateConfiguration();
	}
	
	/**
	 * Método que lee la configuración y se la pasa a la clase
	 * @param newObjComponent Object Objeto que representa el componente
	 * @param newInputStreamXML InputStream del fichero de configuración del componente
	 * @throws Q70UtilidadesExcepcion
	 */
	
	public void generateConfiguration(Q70Configurable newObjComponent, InputStream newInputStreamXML) throws Q70UtilidadesExcepcion{
		objComponente = newObjComponent;
		inputStreamXML = newInputStreamXML;
		generateConfiguration();
	}
	
	
	/**
	 * Método que lee la configuración xml y se la pasa a la clase
	 * @throws Q70UtilidadesExcepcion
	 */
	
	public void generateConfiguration() throws Q70UtilidadesExcepcion {
		
		// instanciar factory sax por defecto
		SAXParserFactory factory = SAXParserFactory.newInstance();
		
		// crear el manejador base 
		Q70ManejadorBaseConfiguracion ManejadorBase = new Q70ManejadorBaseConfiguracion(objComponente,aplicarIndireccion,codigoAplicacion);
		
		try{
	
		SAXParser saxParser = factory.newSAXParser();
		
			// determinar la fuente de xml según coste de recursos
			if ( !( ((Object)bufTextoXML) == null) ){
				// fuente buffer
				StringReader strReader = new StringReader(bufTextoXML.toString());
				saxParser.parse( new InputSource(strReader),ManejadorBase);
				return;
			} else if (!( ((Object)filFicheroXML) == null) ) {
				// fuente File
				saxParser.parse(filFicheroXML,ManejadorBase);	
			    return;
			} else if (!( ((Object)strFichero) == null ) ){
				// fuente Path
				File filFichero = new File(strFichero);
				saxParser.parse( filFichero,ManejadorBase);
				return;
			} else if (!( ((Object)inputStreamXML) == null ) ){
				// fuente InputStream
				saxParser.parse( inputStreamXML,ManejadorBase);
				return;
			}
					
		} catch (java.io.IOException ioe){
				throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_CONFIGURADOR,
																  "Q70Configurador", "generarConfiguracion()", 
																   Q70UtilidadesErrores.UTILIDADES_CONFIGURADOR_FICHERO_EXISTE ,ioe );
		} catch (java.lang.IllegalArgumentException  iae){
				throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_CONFIGURADOR,
															  "Q70Configurador", "generarConfiguracion()", 
															   Q70UtilidadesErrores.UTILIDADES_CONFIGURADOR_ARGUMENTO_INCORRECTO ,iae );
		} catch (SAXException se){
				throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_CONFIGURADOR,
														  "Q70Configurador", "generarConfiguracion()", 
														   Q70UtilidadesErrores.UTILIDADES_CONFIGURADOR_FICHERO_VALIDADO ,se );
		} catch (ParserConfigurationException se){
					throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_CONFIGURADOR,
															  "Q70Configurador", "generarConfiguracion()", 
															   Q70UtilidadesErrores.UTILIDADES_MAPEADOR_CONVERTER_NO_EXISTE ,se );
		}
	
	}

}
