/**
 * 
 */
package com.ejie.y42b.utils.jaxb;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <hr/>
 * <p>
 * Utilidades de soporte para trabajar con objetos JAXB en METAPOSTA
 * </p>
 * <p>
 * Proporciona las siguientes funcionalidades sobre objetos JAXB:
 * </p>
 * <ul>
 * <li><b>Marshalling</b> (Serializaci�n de objetos JAXBa XML)</li>
 * <li><b>Marshalling con formateado de salida</b> (Serializaci�n de objetos
 * JAXBa XML con formato)</li>
 * <li><b>Unmarshalling</b> (Des-serializaci�n de XML a objeto JAXB)</li>
 * <li><b>Unmarshalling con Validation</b> (Des-serializaci�n de XML a objeto
 * JAXB validando previamente el XML contra el esquema (XSD) que define los
 * objetos JAXB).</li>
 * </ul>
 * <p>
 * <b>IMPORTANTE:</b> <i>En la creaci�n de los paquetes (.jar) de objetos JAXB
 * en METAPOSTA, autom�ticametne se incluye el esquema que define los objetos
 * JAXB en el raiz del classPath del paquete. Trabajando con otros paquetes, el
 * desarrollador, deber� incluir estos esquemas en el classpath de la aplicaci�n
 * manualmente.</i>
 * </p>
 * 
 *  
 * 
 */
public class Y42bJAXBFactory {

	private static final Logger logger = LoggerFactory
			.getLogger(Y42bJAXBFactory.class);

	/**
	 * Constructor.
	 */
	private Y42bJAXBFactory() {
	}

	/**
	 * Serializa a XML un objeto JAXB.
	 * 
	 * @param jaxbObject
	 *            Objeto JAXB a serializar en XML.
	 * @return Cadena de texto con el XML serializado del objeto JAXB.
	 * @throws Exception Exception
	 */
	public static String marshal(Object jaxbObject) throws Exception {

		String output = null;

		try {

			JAXBContext context = Y42bJAXBFactory.getContext();
			Marshaller marshaller = context.createMarshaller();
			StringWriter sw = new StringWriter();

			marshaller.marshal(jaxbObject, sw);
			output = sw.toString();
			Y42bJAXBFactory.logger.debug("OutputJAXB: " + output);
		} catch (JAXBException e) {

			throw new Exception("JAXB marchal exception");
		}

		return output;
	}

	/**
	 * Des-serializa XML a objetos JAXB.
	 * 
	 * @param jaxbClass
	 *            Clase que representa el objeto JAXB.
	 * @param xmlObjectRepresentation
	 *            XML que representa el objeto JAXB.
	 * @return Objeto JAXB resultado de la des-serializaci�n del XML.
	 * @throws Exception Exception
	 */
	public static Object unmarshal(Class<?> jaxbClass,
			String xmlObjectRepresentation) throws Exception {

		Object output = null;

		try {

			Unmarshaller unmarshaller = Y42bJAXBFactory.getContext()
					.createUnmarshaller();

			InputStream is = new ByteArrayInputStream(
					xmlObjectRepresentation.getBytes("UTF-8"));

			output = unmarshaller.unmarshal(is);

		} catch (JAXBException e) {

			throw new Exception("JAXB unmarchal exception");

		} catch (UnsupportedEncodingException e) {

			throw new Exception("JAXB unmarchal unsupported encoding exception");
		}

		return output;
	}

	/**
	 * Crea un contexto JAXB para las clases involucradas en el proyecto.
	 * 
	 * @return Contexto JAXB configurado para las clases empleadas en el
	 *         proyecto.
	 * @throws JAXBException
	 *             En caso de no poder crear el contexto JAXB.
	 */
	private static JAXBContext getContext() throws JAXBException {

		JAXBContext context = JAXBContext.newInstance(new Class[] {
				com.ejie.y42b.model.CodesField.class,
				com.ejie.y42b.model.CodesEntity.class,
				com.ejie.y42b.model.CodesEntities.class,
				com.ejie.y42b.model.CodesContact.class,
				com.ejie.y42b.model.CodesContacts.class });

		return context;
	}

	/**
	 * Metodo Main
	 * @param args String[]
	 * @throws Exception Exception
	 */
/*	
	public static void main(String[] args) throws Exception {

		CodesEntities ces = new CodesEntities();
		CodesContacts ccs = new CodesContacts();

		CodesEntity e1 = new CodesEntity();
		e1.setCode("E1");
		e1.setCampo1(new CodesField("att1", "att1value"));
		e1.setCampo2(new CodesField("att2", "att2value"));
		e1.setCampo3(new CodesField("att3", "att3value"));
		e1.setCampo4(new CodesField("att4", "att4value"));
		e1.setCampo5(new CodesField("att5", "att5value"));
		e1.setCampo6(new CodesField("att6", "att6value"));
		e1.setCampo7(new CodesField("att7", "att7value"));
		e1.setCampo8(new CodesField("att8", "att8value"));
		e1.setCampo9(new CodesField("att9", "att9value"));
		e1.setCampo10(new CodesField("att10", "att10value"));

		CodesEntity e2 = new CodesEntity();
		e2.setCode("E2");
		e2.setCampo1(new CodesField("att1", "att1value"));
		e2.setCampo2(new CodesField("att2", "att2value"));
		e2.setCampo3(new CodesField("att3", "att3value"));
		e2.setCampo4(new CodesField("att4", "att4value"));
		e2.setCampo5(new CodesField("att5", "att5value"));
		e2.setCampo6(new CodesField("att6", "att6value"));
		e2.setCampo7(new CodesField("att7", "att7value"));
		e2.setCampo8(new CodesField("att8", "att8value"));
		e2.setCampo9(new CodesField("att9", "att9value"));
		e2.setCampo10(new CodesField("att10", "att10value"));

		ces.getEntidades().add(e1);
		ces.getEntidades().add(e2);

		Y42bJAXBFactory.logger.debug(Y42bJAXBFactory.marshal(ces));

		CodesContact c1 = new CodesContact();
		c1.setCode("C1");
		c1.setCampo1(new CodesField("att1", "att1value"));
		c1.setCampo2(new CodesField("att2", "att2value"));
		c1.setCampo3(new CodesField("att3", "att3value"));
		c1.setCampo4(new CodesField("att4", "att4value"));
		c1.setCampo5(new CodesField("att5", "att5value"));
		c1.setCampo6(new CodesField("att6", "att6value"));
		c1.setCampo7(new CodesField("att7", "att7value"));
		c1.setCampo8(new CodesField("att8", "att8value"));
		c1.setCampo9(new CodesField("att9", "att9value"));
		c1.setCampo10(new CodesField("att10", "att10value"));

		CodesContact c2 = new CodesContact();
		c2.setCode("C2");
		c2.setCampo1(new CodesField("att1", "att1value"));
		c2.setCampo2(new CodesField("att2", "att2value"));
		c2.setCampo3(new CodesField("att3", "att3value"));
		c2.setCampo4(new CodesField("att4", "att4value"));
		c2.setCampo5(new CodesField("att5", "att5value"));
		c2.setCampo6(new CodesField("att6", "att6value"));
		c2.setCampo7(new CodesField("att7", "att7value"));
		c2.setCampo8(new CodesField("att8", "att8value"));
		c2.setCampo9(new CodesField("att9", "att9value"));
		c2.setCampo10(new CodesField("att10", "att10value"));

		ccs.getContactos().add(c1);
		ccs.getContactos().add(c2);

		Y42bJAXBFactory.logger.debug(Y42bJAXBFactory.marshal(ccs));

	}
*/
}
