package com.westgroup.morpheus.filters.dom;

import java.io.*;
import java.net.*;
import org.xml.sax.*;
import org.xml.sax.helpers.ParserFactory;
import com.westgroup.morpheus.util.*;
import java.util.Hashtable;
import org.w3c.dom.*;
import java.util.Enumeration;
import com.westgroup.morpheus.framework.*;
import com.westgroup.morpheus.xparser.parsers.*;
import com.westgroup.morpheus.xparser.inputrules.*;
import com.westgroup.morpheus.util.*;
import java.lang.reflect.*;
import java.lang.*;

/**
 * EntryPoint class which parses a given file and thus drives some
 * other SAXHandler.
 **/

public class XFilter implements FilterComponent, EntryPoint {

	 /**
	  * the ID of this component
 	  **/

	 private String ID;

	 /**
	  * the input source
 	  **/

	 private InputStream inputSource;

	 private DOMFilterBase nextHandler;

	 FilterConfiguration myConfiguration;
	 ApplicationContext myContext;

	 String parserID;
	 Hashtable rulesTable = new Hashtable ();


	 /**
	  * constructor
	  *
	  * @param	 ID_		unique ID
	  * @exception			FilterException
	  **/

	 public XFilter (String ID_) throws FilterException {
		  ID = ID_;
	 }

	 /**
	  * for debugging purposes
	  *
	  * @param	 message	string to log
 	  **/

	 private static void log (String message) {
		  //System.err.println (message);
	 }

	 /**
	  * standard configuration mechanism. Required parameters:
	  * input-file must be a path or URL to a valid XML
	  * file. output-component must be the ID of a SAXHandler.
	  *
	  * @param	 configuration	  configuration of this component
	  * @exception					  FilterException
 	  **/

	 public void configure (FilterConfiguration configuration)
		  throws FilterException {
		  try {
			  myConfiguration = configuration;
			  String output = myConfiguration.getParameter ("output-component");
			  myContext = myConfiguration.getContext ();
			  nextHandler
					= (DOMFilterBase) myContext.getObject (DOMFilterBase.class, output);
			  if (nextHandler == null) {
				 throw new FilterException ("no such DOMFilterBase with ID '"
													+ output + "'");
			  }

			  String input = myConfiguration.getParameter ("input-file");
		  	  if (input != null) {
			     try {
					 URL inputURL = URLUtil.resolvePath (myConfiguration.getBaseURL (),
																	 input);
					 inputSource = new FileInputStream (inputURL.toString ());
				 } catch (MalformedURLException exception) {
					 throw new FilterException ("illegal input-file URL \""
														 + input + "\"");
				 }
			  } else {
				inputSource = myContext.getInputStream ();
		  	  }
		   } catch (Exception e) {
		   	e.printStackTrace();
		   }
	 }

	 /**
	  * returns the unique ID
	  *
	  * @return	 String
	  **/

	 public String getID () {
		  return ID;
	 }

	 /**
	  * test for a legal URL
	  *
	  * @param	 path		string to test
	  * @return				boolean
	  **/

	 private boolean isLegalURL (String path) {
		  try {
				URL url = new URL (path);
				return true;
		  } catch (MalformedURLException exception) {
				return false;
		  }
	 }

	public void invoke () throws FilterException {
		XParser parser = null;

		// parse parser control
		DocumentHandler handler = new HandlerBase () {
      		public void startElement (String name, AttributeList attributes) {
        		if (name.equals ("parser")) {
          			parserID = attributes.getValue ("class");
        		} else if (name.equals("pair")) {
        			String pKey = attributes.getValue ("key");
        			String rules = new String();
        			String layout = new String();
        			try {
	        			rules = URLUtil.resolvePath (myConfiguration.getBaseURL (),
								attributes.getValue ("rules")).toString();
	        			layout = URLUtil.resolvePath (myConfiguration.getBaseURL (),
								attributes.getValue ("layout")).toString();
					} catch (Exception e) {
						e.printStackTrace();
						System.exit(1);
					}
					System.err.println ("adding InputRules to rulesTable...");
        			rulesTable.put (pKey,
						new RulesBuilder ().parseRulesFiles (rules, layout));
				    System.err.println ("Done.");
        		}
      		}
    	};

    	String dtdFile = new String();

    	try {
    		dtdFile = URLUtil.resolvePath (myConfiguration.getBaseURL (),
    		myConfiguration.getParameter ("dtd-file", "null")).toString();
    	} catch(Exception e) {
    		e.printStackTrace();
    	}

    	String controlFile = myConfiguration.getRequiredParameter ("control-file");
    	myConfiguration.parseExternalFile (controlFile, handler);


		// create RecordBuilder and set its params
		RecordBuilder builder = new RecordBuilder ();
		builder.setNextHandler(nextHandler);
		builder.setDTD(dtdFile);

		// create parser based on ID
		try {
			Class c = Class.forName(parserID);
			parser = (XParser)(c.newInstance());

    		parser.setContentHandler(builder);
    		parser.setRulesTable (rulesTable);
    		parser.parse (inputSource);
		} catch (Exception e) {
			e.printStackTrace();
		}
	 }
}

