package com.ejie.ab04b.parse;

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

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

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

	private String packageName;

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

	/**
	 * Metodo que parse un XML a un objeto de negocio.
	 * 
	 *  message            String
	 *  O Clase a la que se intentará convertir el XML
	 *
	 * @param message the message
	 * @return the o
	 * @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;
		}
	}
}
