import java.io.FileReader;
import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.xml.transform.Source;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;

import java.util.Hashtable;
import java.util.Enumeration;

import org.apache.fop.apps.Driver;
import org.apache.fop.apps.Options;
import org.apache.xalan.processor.TransformerFactoryImpl;
import org.apache.log.*;


/**
 * @version 	1.0
 * @author		JohnPT
 */
public class PdfRenderer {
	private static Logger log = null;
	private Templates template = null;
	private String xslFile = null;

	public PdfRenderer(String xslFile) {
		super();
		
		setTemplate( xslFile );
	}

	public void setTemplate(String xslFile) {
		try
		{
			Hierarchy hierarchy = Hierarchy.getDefaultHierarchy();
			log = hierarchy.getLoggerFor("fop");
			log.setPriority(Priority.WARN);
			// Get stylesheet transformer
			TransformerFactory tf = new TransformerFactoryImpl();
			// template object is multi-threaded and should be cached
			template = tf.newTemplates( new StreamSource( xslFile ));


		} catch(TransformerException te) {
			DebugSupport.logException( te );
		}
	}

	public void run( Source in, OutputStream out ) throws java.io.IOException {
		run( in, out, null );
	}

	public void run( Source in, OutputStream out, Hashtable parameters ) throws java.io.IOException {
		if( template == null ) {
			System.out.println("You must assign a XSL stylesheet before calling run.");
			System.out.println("\tsetTemplate( stylesheetfilename )");
			return;
		}

		try {
			// use the same XSL template repeatedly
			Transformer transformer = template.newTransformer();

			// set parameters if they exist
			if( parameters != null ) {
				Enumeration enum = parameters.keys();
				while( enum.hasMoreElements() ) {
					String key = ""+ enum.nextElement();
					transformer.setParameter( key, parameters.get(key) );
				}
			}

			// Create FOP driver and set rendering mode, output stream and logger
			Driver driver = new Driver();
			driver.setLogger( log );
			driver.setRenderer(driver.RENDER_PDF);
			driver.setOutputStream( out );

			// Create SAXResult based on FOP Driver content handler 
			// which will accept SAX events and build FOP tree
			Result saxResult = new SAXResult( driver.getContentHandler() );

			// Use the Transformer to transform an XML Source and 
			// send the output to a Result object. Implicitely it will 
			// create the FOP tree by firing SAX events.
			transformer.transform( in, saxResult );

			// flush out the PDF!
			out.flush();
			out.close();
		} catch (TransformerException te) {
			te.printStackTrace();
		}
		
	}

	public void run( String inFileName, String outFileName ) throws java.io.IOException {
		// Get a Source for XML document

		Source source = new StreamSource( new FileReader( inFileName ) );
		OutputStream out = new FileOutputStream( outFileName );

		run( source, out );
	}
}
