package com.ejie.ab79.comun;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Utilidades para manejo de DOM
 * 
 *  
 */
public final class UtilsDOM {

	/**
	 * UtilDOM
	 */
	private UtilsDOM() {
	}

	/**
	 * Crea un objeto de la clase Document a partir del String XML que recibe
	 * como parámetro
	 * 
	 * @param xml
	 *            String que contiene el XML UTF-8
	 * @return Document Objeto de la clase Document
	 * @throws Exception
	 *             Exception excepcion
	 */
	public static Document createDocUTF8(String xml) throws Exception {
		try {
			return (UtilsDOM.buildDocument(xml, "UTF-8"));
		} catch (UnsupportedEncodingException e) {
			throw new Exception("Error createDocUTF8", e);
		} catch (SAXException e) {
			throw new Exception("Error createDocUTF8", e);
		} catch (IOException e) {
			throw new Exception("Error createDocUTF8", e);
		} catch (ParserConfigurationException e) {
			throw new Exception("Error createDocUTF8", e);
		}
	}

	/**
	 * Crea un objeto document a partir de XML con la codificación enviada
	 * 
	 * @param strPfXML
	 *            String con el XML
	 * @param strPfEnconding
	 *            Codificacion enviada
	 * @return Document Objeto de la clase Document
	 * @throws ParserConfigurationException
	 *             excepcion de parseo
	 * @throws UnsupportedEncodingException
	 *             encode excepcion
	 * @throws IOException
	 *             IO excepcion
	 * @throws SAXException
	 *             error de sax
	 */
	private static Document buildDocument(String strPfXML, String strPfEnconding)
			throws ParserConfigurationException, UnsupportedEncodingException, IOException, SAXException {
		Document doc = null;
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
		doc = documentBuilder.parse(new ByteArrayInputStream(strPfXML.getBytes(strPfEnconding)));
		return (doc);
	}

	/**
	 * Devuelve el String a partir de un Document
	 * 
	 * @param doc
	 *            Documento que contiene el XML
	 * @return String que contiene el XML
	 * @throws NegocioException
	 *             Exception excepcion
	 */
	public static String getStringDoc(Document doc) throws Exception {
		try {
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StringWriter sw = new StringWriter();
			StreamResult result = new StreamResult(sw);
			transformer.transform(source, result);
			String xmlString = sw.toString();
			return (xmlString);
		} catch (TransformerConfigurationException e) {
			throw new Exception("Error getStringDoc", e);
		} catch (TransformerException e) {
			throw new Exception("Error getStringDoc", e);
		}

	}

	/**
	 * Funcion Convierte String a Document
	 * 
	 * @param textoXML
	 *            String textoXML
	 * 
	 * @return Document valor devuelto
	 * 
	 * @throws NegocioException
	 *             Exception excepcion
	 */
	public static Document stringToDocument(String textoXML) throws Exception {
		Document document = null;
		try {
			DocumentBuilderFactory factory = null;
			DocumentBuilder builder = null;

			factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(false);
			factory.setIgnoringElementContentWhitespace(true);
			builder = factory.newDocumentBuilder();
			StringReader stringIn = new StringReader(textoXML);
			document = builder.parse(new InputSource(stringIn));
			// crear y añadir la pi
			ProcessingInstruction pi = document.createProcessingInstruction("xml",
					"version=\"1.0\" encoding=\"ISO-8859-1\"");
			document.appendChild(pi);
		} catch (Exception ex) {
			throw new Exception("Excepcion en stringToDocument:", ex);
		}
		return document;
	}

	/**
	 * Funcion que devuelte un Texto dado un XPath
	 * 
	 * @param docDom
	 *            Document valor
	 * @param strPath
	 *            String strPath
	 * 
	 * @return String valor devuelto
	 */
	public static String buscarDomString(Document docDom, String strPath) {
		NodeList nodeLiResultado = null;
		String strValor = "";
		try {
			nodeLiResultado = (NodeList) XPathFactory.newInstance().newXPath().evaluate(strPath, docDom,
					XPathConstants.NODESET);
			if (nodeLiResultado.getLength() != 0) {
				strValor = nodeLiResultado.item(0).getNodeValue();
			} else {
				strValor = "";
			}
		} catch (Exception ex) {
			return strValor;
		}
		return strValor;
	}
}
