package com.ejie.ad74a.jms.util;

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

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

/**
 * Clase que implementa el parser para los mensajes SOAP. Codifica desde UTF-8.
 * 
 * @author
 * 
 * @param <O> Clase a la que se intentará convertir el XML
 */
public class MessageParser<O> {

	private String packageName;

	/**
	 * Constructor de la clase
	 * 
	 * @param packageName String
	 */
	public MessageParser(String packageName) {
		this.packageName = packageName;
	}

	/**
	 * Metodo que parse un XML a un objeto de negocio
	 * 
	 * @param message String
	 * @return O Clase a la que se intentará convertir el XML
	 * @throws JAXBException                JAXBException
	 * @throws UnsupportedEncodingException UnsupportedEncodingException
	 */
	@SuppressWarnings(value = { "unchecked", "rawtypes" })
	public O parse(String message) throws JAXBException, UnsupportedEncodingException {
		if (message != null) {
			JAXBContext jc;
			// Paquete que contiene las clases generadas en la compilacion del
			// xsd
			jc = JAXBContext.newInstance(this.packageName);
			Unmarshaller unmarshaller = jc.createUnmarshaller();
			Object jaxbObject = null;

			// Le ponemos encoding a UTF-8 para que acepte
			// posibles caracteres extra�os
			jaxbObject = unmarshaller.unmarshal(new ByteArrayInputStream(message.getBytes("UTF-8")));

			/*
			 * Se realiza una comprobacion de que el elemento que devuelve la funcion
			 * 'unmarshal' sea de tipo JAXBElement. Si es asi, es necesario recuperar la
			 * clase que se quiere devolver de su atributo 'value'. La funcion unmarshal
			 * devuelve el objeto JAXBElement cuando encuentra algún problema con la
			 * anotacion 'xmlRootElement' de las clases a parsear.
			 */
			if (jaxbObject instanceof JAXBElement<?>) {
				return (O) ((JAXBElement) jaxbObject).getValue();
			} else {
				return (O) jaxbObject;
			}
		} else {// Si el mensaje es null devuelve null.
			return null;
		}
	}

	public String parse(Object object) throws Exception {

		if (object == null) {
			return null;
		}

		JAXBContext context = JAXBContext.newInstance(object.getClass());
		Marshaller marshaller = context.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		marshaller.setProperty(Marshaller.JAXB_ENCODING, "ISO-8859-1");

		StringWriter stringWriter = new StringWriter();

		marshaller.marshal(object, stringWriter);

		return stringWriter.getBuffer().toString();
	}
}
