package cat.aoc.pci.utils;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBIntrospector;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
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 org.apache.geronimo.mail.util.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
 
/**
 * 
 * @author aciffone@aoc.cat
 *
 */
public class Util {

	/**
	 * Retorna el bean java corresponent al XML que es troba al par�metre dom. La classe T s'ha
	 * de correspondre amb el XML que es vol encarnar 
	 * @param <T>
	 * @param dom
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	public static <T> T unserializeXML(DOMSource dom,Class<T> clazz) throws Exception {
		
		// inicialitzem el context jaxb passant la classe del objecte a serialitzar
		JAXBContext jc = JAXBContext.newInstance(clazz);
		
		// creem el unsmarshaller
		Unmarshaller unmarshaller = jc.createUnmarshaller();
		return (T)unmarshaller.unmarshal(dom);		
	}
	
	/**
	 * Serialitza la petici� del objecte java a XML i l'escriu al DOM passat
	 * per paràmetre
	 * @param obj
	 * 		Objecte a serialitzar
	 * @param os
	 * 		Document on s'escriur� el XML resultant
	 * @throws Exception
	 */
	public static void serializeXML(Object obj, Document doc) throws Exception {

		// inicialitzem el context jaxb passant la classe del objecte a serialitzar
		JAXBContext jc = JAXBContext.newInstance(obj.getClass());
		JAXBIntrospector introspector = jc.createJAXBIntrospector();
		// creem el marshaller
		Marshaller marshaller = jc.createMarshaller();
		// 		pretty-print
		//		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,new Boolean(false));
		marshaller.setProperty(Marshaller.JAXB_FRAGMENT,new Boolean(true));
		if(null == introspector.getElementName(obj)) {
			// creem el jaxb element amb el que serialitzarem el objecte
			JAXBElement jaxbElement = new JAXBElement(null ,obj.getClass(), obj);
			marshaller.marshal(jaxbElement, doc);
		} else {
			marshaller.marshal(obj, doc);
		}
	}
	
	/**
	 * Transforma el element DOM a un string amb el contingut del XML
	 * @param node
	 * @return
	 */
	public static String xmlToString(Node node) {
		try {
			DOMSource source = new DOMSource(node);
			StringWriter stringWriter = new StringWriter();
			StreamResult result = new StreamResult(stringWriter);
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer();
			transformer.transform(source, result);
			return stringWriter.getBuffer().toString();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	// Read of a Binary file from disk
	public static byte[] readBinaryFile(String filename){
		byte buf[] = null;
		try {
			FileInputStream fis = new FileInputStream(filename);
			buf = new byte[fis.available()];
			DataInputStream dis = new DataInputStream(fis);
			dis.read(buf);
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		return buf;
	}
	
	// Read of a Binary file from disk and encodes to Base64
	public static byte[] readBinaryFileB64(String filename) throws UnsupportedEncodingException {

		return Base64.encode(readBinaryFile(filename));
	}
	
	
}

