package lu.tudor.santec.gecamed.esante.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;


/**
 * @author jens.ferring(at)tudor.lu
 * 
 * @version
 * <br>$Log: XmlHelper.java,v $
 * <br>Revision 1.3  2013-10-21 08:18:57  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.2  2013-10-16 13:03:47  ferring
 * <br>some small esante bugfixes
 * <br>
 * <br>Revision 1.1  2013-10-08 08:54:14  ferring
 * <br>class name refactoring and tree view implementation (first steps)
 * <br>
 * <br>Revision 1.2  2013-07-15 06:18:39  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.1  2013-06-10 08:22:14  ferring
 * <br>eSante POC
 * <br>
 */
public class XmlHelper
{
	/* ======================================== */
	// MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(XmlHelper.class.getName());
	
	private static DocumentBuilder	builder;
	private static OutputFormat		formatter	= new OutputFormat();
	private static byte[]			outputBuffer;
	
	
	
	/* ======================================== */
	// CLASS BODY
	/* ======================================== */
	
	// STATIC BLOCK
	static 
	{
		try
		{
			builder	= DocumentBuilderFactory.newInstance().newDocumentBuilder();
		}
		catch (ParserConfigurationException e)
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
		
		formatter	= new OutputFormat();
		formatter.setIndenting(true);
		formatter.setIndent(4);
		outputBuffer = new byte[2<<14];
	}
	
	
	
	/* ======================================== */
	// STATIC METHODS
	/* ======================================== */
	
	public static String formatPretty (InputStream xml) throws IOException, SAXException
	{
		try
		{
			return formatPretty(parseXml(xml));
		}
		catch (Exception e)
		{
			logger.warn("Couldn't pretty print the XML message", e);
			
			StringBuilder out = new StringBuilder(xml.available());
			synchronized (outputBuffer)
			{
				while (xml.read(outputBuffer) > 0)
					out.append(new String(outputBuffer));
			}
			
			return out.toString();
		}
		catch (Error e)
		{
			logger.error("Error while trying to pretty print message", e);
			return "";
		}
	}
	
	
	public static String formatPretty (String xml) throws SAXException, IOException
	{
		if (xml == null || xml.trim().length() == 0)
			return xml;
		try
		{
			return formatPretty(parseXml(xml));
		}
		catch (Exception e)
		{
			logger.warn("Couldn't pretty print the XML message", e);
			return xml;
		}
		catch (Error e)
		{
			logger.error("Error while trying to pretty print message", e);
			return "";
		}
	}
	
	
	public static String formatPretty (Document doc) throws IOException
	{
		String			prettyXml	= null;
		Writer			out;
		XMLSerializer	serializer;
		
		out			= new StringWriter();
		serializer	= new XMLSerializer(formatter);
		serializer.setOutputCharStream(out);
		serializer.serialize(doc);
		prettyXml	= out.toString();
		serializer.reset();
		
		return prettyXml;
	}
	
	
	public static Document parseXml (String xml) throws SAXException, IOException
	{
		return parseXml(new InputSource(new StringReader(xml)));
	}
	
	
	public static Document parseXml (InputStream xml) throws SAXException, IOException
	{
		Document	doc	= null;
		
		try
		{
			doc	= parseXml(new InputSource(xml));
		}
		finally
		{
			try
			{
				xml.close();
			}
			catch (IOException e)
			{
				logger.log(Level.ERROR, e.getMessage(), e);
			}
		}
		
		return doc;
	}
	
	
	public static Document parseXml (InputSource xml) throws SAXException, IOException
	{
		return builder.parse(xml);
	}
	
	
//	public static void main (String[] args) throws IOException
//	{
//		String	filename	= "WS-Security-Authentication.xml";
//		String	prettyXml	= formatPretty(XMLHelper.class.getResourceAsStream("../resources/requests/"+filename));
//		
//		OutputStream bos	= new BufferedOutputStream(new FileOutputStream("e:\\pretty.xml"));
//		bos.write(prettyXml.getBytes());
//		bos.close();
//	}
}
