/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.labo.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;

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

import lu.tudor.santec.gecamed.core.utils.Logger;

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

public class ResultParser
	{
	private InputStream	m_ResultStream;
	private Document	m_ResultDocument;

	private static Logger m_Logger = new Logger (ResultParser.class);
	
	private static File	  m_TempDirectory 		= new File (System.getProperty("java.io.tmpdir"));
	private static File	  m_UserHomeDirectory 	= new File (System.getProperty("user.home"));
	
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

	private static final int	c_BufferSize  = 4096;
	
	private static final String c_DTDFilename = "laboratory.dtd";
	
	private static final String c_DTDPath = "/lu/tudor/santec/gecamed/labo/repository/" + c_DTDFilename;
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public ResultParser (File p_ResultFile)
	{
    this.setupDTD();
	
	if ((p_ResultFile != null) && p_ResultFile.canRead())
		{
		try	{
			m_ResultStream = new FileInputStream (p_ResultFile);	
			}
		catch (FileNotFoundException p_Exception)
			{
			// Shouldn't occure because existence of file was checked beforehand	
			m_Logger.log(Level.ERROR, p_Exception.getMessage(), p_Exception);
			}
		}
	}

//---------------------------------------------------------------------------

public ResultParser (byte[]	p_ResultData)
	{
	this.setupDTD();	
	
	if (p_ResultData != null)
		{
		m_ResultStream = new ByteArrayInputStream (p_ResultData);
		}
	}
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

private void setupDTD ()
	{
	File				l_DTDFile;
	
	l_DTDFile = new File (m_TempDirectory.getPath() + File.separator + c_DTDFilename);
	if (!l_DTDFile.canRead()) this.copyDTDToTempDirectory(l_DTDFile);	
	}

//---------------------------------------------------------------------------

private void copyDTDToTempDirectory (File p_DTDFile)
	{
	InputStream			l_DTDResource;
	FileOutputStream	l_DTDStream;
	byte[]				l_Buffer;
	int					l_BytesRead;
					
	l_Buffer = new byte [c_BufferSize];

	try	{
		l_DTDResource = ResultParser.class.getResourceAsStream(c_DTDPath);
		l_DTDStream = new FileOutputStream (p_DTDFile.getPath());
		
		do	{
			l_BytesRead = l_DTDResource.read(l_Buffer, 0, c_BufferSize);
			if (l_BytesRead > 0) l_DTDStream.write(l_Buffer, 0, l_BytesRead);
			}
		while (l_BytesRead > 0);
		
		l_DTDStream.close();
		l_DTDResource.close();
		}
	catch (Exception p_Exception)
		{
		m_Logger.log(Level.FATAL, "Failed to copy into temp directory " + p_DTDFile.getPath(),p_Exception);
		}		
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public void parse ()
	{
	DocumentBuilderFactory	l_Factory;
	DocumentBuilder			l_Builder;
	StringBuffer			l_ResultXML = new StringBuffer();
	BufferedReader 			l_BufferedReader;
	
	if (m_ResultStream == null) return;
	
	try {
		// build the XML as string
		l_BufferedReader = new BufferedReader(new InputStreamReader(m_ResultStream, "UTF-8"));
		String line;
		while ((line = l_BufferedReader.readLine()) != null)
			l_ResultXML.append(line);
		} 
	catch (IOException p_Exception) 
		{
		m_Logger.log(Level.ERROR, p_Exception.getMessage(), p_Exception);
		}
	
	l_Factory = DocumentBuilderFactory.newInstance();
	
	try {
		l_Builder = l_Factory.newDocumentBuilder();
		try {
			// try to parse the XML string, using the temp directory
			m_ResultDocument = parseXMLString(l_Builder, l_ResultXML.toString(), m_TempDirectory);
			}
		catch (FileNotFoundException p_FNFException)
			{
			m_Logger.log(Level.WARN, "Couldn't read the DTD-file in the temp-folder. " +
					"There might be some problems accessing the temp-folder \""+m_TempDirectory+"\". " +
					"Trying to use the user's home folder instead.");
			
			// create the DTD-file in the home folder of the user
			File l_DTDFile = new File (m_UserHomeDirectory.getPath() + File.separator + c_DTDFilename);
			if (!l_DTDFile.canRead()) this.copyDTDToTempDirectory(l_DTDFile);
			try {
				// there are probably some problems with the temp directory, try the user's home folder
				m_ResultDocument = parseXMLString(l_Builder, l_ResultXML.toString(), m_UserHomeDirectory);
				}
			catch (FileNotFoundException p_FNFException2)
				{
				m_Logger.log(Level.ERROR, "Couldn't read the DTD-file in the home-folder. " +
						"There might be some problems accessing the home-folder \""+m_UserHomeDirectory+"\". ");
				m_Logger.log(Level.ERROR, p_FNFException2.getMessage(), 	p_FNFException2);
				}
			}
//		m_ResultDocument = (Document)l_Builder.parse(m_ResultStream, m_TempDirectory.getPath() + File.separator);
		}
	catch(Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR, p_Exception.getMessage(), p_Exception);
		}
	}


private static Document parseXMLString (DocumentBuilder p_Builder, String p_XMLString, File p_Directory) throws SAXException, IOException
	{
	InputSource l_InputSource = new InputSource(new StringReader(p_XMLString));
	l_InputSource.setSystemId(p_Directory.getPath() + File.separator);
	l_InputSource.setEncoding("UTF-8");
	return p_Builder.parse(l_InputSource);
	}

//---------------------------------------------------------------------------

public Document getDocument ()
	{
	return m_ResultDocument;	
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* End of Class                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
	}
