package pt.link.utils.xml;

import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

public class CastorUnmarshaller implements IXMLUnmarshaller {
	static Log log = LogFactory.getLog(CastorUnmarshaller.class);
	
	static Mapping mapping;
	
	private static void init() throws XMLMarshallException {
		mapping = new Mapping(CastorUnmarshaller.class.getClassLoader());
		InputStream mappingIS = CastorUnmarshaller.class.getResourceAsStream("/castor-mapping.xml");
		if(mappingIS == null){
			String messageError = "castor mapping file not found"; 
			log.error(messageError);
			throw new XMLMarshallException(messageError);
		}
		try {
			mapping.loadMapping(new InputSource(mappingIS));
		} catch (Exception e) {
			String messageError = "Exception caught while initializing " + CastorUnmarshaller.class.getName();
			log.error(messageError,e);
			throw new XMLMarshallException(messageError, e);
		}  
	}
	
	protected CastorUnmarshaller() throws XMLMarshallException{
		init();
	}
	
	private static CastorUnmarshaller _instance = null;
	public static CastorUnmarshaller getInstance() throws XMLMarshallException{
		if(_instance==null){
			_instance = new CastorUnmarshaller();
		}
		return _instance;
	}

	public Object unmarshall(Class arg, InputSource xmlInputSource) throws XMLMarshallException {
		try {
			Unmarshaller unmarshaller = new Unmarshaller(arg, this.getClass().getClassLoader());
			unmarshaller.setMapping(mapping);
			Object unmarshalled = unmarshaller.unmarshal(xmlInputSource);
			return unmarshalled;
		}
		catch (Exception e) {
			String messageError = "Exception caught while unmarshalling" + this.getClass().getName();
			log.error(messageError, e);
			throw new XMLMarshallException(messageError, e);
		}  
	}
	
	public Object unmarshall(Class arg, Node node) throws XMLMarshallException {
		try {
			Object unmarshalled = Unmarshaller.unmarshal(arg, node);
			return unmarshalled;
		}
		catch (Exception e) {
			String messageError = "Exception caught while unmarshalling" + this.getClass().getName();
			log.error(messageError, e);
			throw new XMLMarshallException(messageError, e);
		}  
	}

}
