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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import lu.tudor.santec.gecamed.address.ejb.entity.beans.Zip;
import lu.tudor.santec.gecamed.core.utils.Logger;

import org.apache.log4j.Level;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.helpers.DefaultHandler;

public class SGGAHandler extends DefaultHandler implements ContentHandler
	{
	private Collection <Zip> m_Zips;
	private Zip				 m_CurrentZip;
	private String			 m_Property;

	private Logger 			m_Logger = null;

	private Hashtable <String,Zip> m_PrimaryZips;
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

	public static final String c_Street		= "street";
	public static final String c_Zip		= "zip";
	public static final String c_Parity		= "parity";
	public static final String c_First		= "first";
	public static final String c_Last		= "last";
	public static final String c_PrimaryKey	= "na_primarykey";
	public static final String c_ForeignKey	= "na_foreignkey";
	public static final String c_Type		= "na_type";
	public static final String c_Appelation	= "na_appelation";
	public static final String c_Locality	= "na_locality";
	public static final String c_Country	= "na_country";
	
	public static final String c_TypePRC	= "PRC";
	public static final String c_TypeTRC	= "TRC";
	public static final String c_TypeHIS	= "HIS";
	public static final String c_TypeSYN	= "SYN";
	public static final String c_TypeUSA	= "USA";
	
	public static final String c_ParityEven = "P";
	public static final String c_ParityOdd  = "I";
		
	private static final String c_RowsetElement	 = "ROWSET";
	private static final String c_RowElement	 = "ROW";
	
	private static final String c_PrimkeyElement = "PRIMKEY";
	private static final String c_PrckeyElement  = "PRCKEY";
	private static final String c_TypdenElement  = "TYPDEN";
	private static final String c_LibtadElement  = "LIBTAD";
	private static final String c_CodtapElement  = "CODTAP";
	private static final String c_LibtapElement  = "LIBTAP";
	private static final String c_DenrueElement  = "DENRUE";
	private static final String c_MdiElement 	  = "MDI";
	private static final String c_PrefpayElement = "PRFPAY";
	private static final String c_CodcdpElement  = "CODCDP";
	private static final String c_LibcptElement  = "LIBCPT";
	private static final String c_LibpayElement  = "LIBPAY";
	private static final String c_PaiimpElement  = "PAIIMP";
	private static final String c_DebutElement   = "DEBUT";
	private static final String c_FinElement     = "FIN";
	private static final String c_DatecreElement = "DATECRE";
	private static final String c_DateupdElement = "DATEUPD";
	
	private static final int	c_Rowset	= 0;	
	private static final int	c_Row	    = 1;	
	private static final int	c_Primkey   = 2;	
	private static final int	c_Prckey	= 3;
	private static final int	c_Typden	= 4;
	private static final int	c_Libtad	= 5;
	private static final int	c_Codtap	= 6;
	private static final int	c_Libtap	= 7;
	private static final int	c_Denrue	= 8;
	private static final int	c_Mdi		= 9;
	private static final int	c_Prefpay	= 19;
	private static final int	c_Codcdp	= 11;
	private static final int	c_Libcpt	= 12;
	private static final int	c_Libpay	= 13;
	private static final int	c_Paiimp	= 14;
	private static final int	c_Debut		= 15;
	private static final int	c_Fin		= 16;
	private static final int	c_Datecre	= 17;
	private static final int	c_Dateupd	= 18;
	
    private static final Hashtable <String,Integer> m_Elements = new Hashtable <String,Integer> ();
    
    static 	{
			m_Elements.put( SGGAHandler.c_RowsetElement , 	Integer.valueOf(SGGAHandler.c_Rowset));
			m_Elements.put( SGGAHandler.c_RowElement , 		Integer.valueOf(SGGAHandler.c_Row));
			m_Elements.put( SGGAHandler.c_PrimkeyElement , 	Integer.valueOf(SGGAHandler.c_Primkey));
			m_Elements.put( SGGAHandler.c_PrckeyElement , 	Integer.valueOf(SGGAHandler.c_Prckey));
			m_Elements.put( SGGAHandler.c_TypdenElement , 	Integer.valueOf(SGGAHandler.c_Typden));
			m_Elements.put( SGGAHandler.c_LibtadElement , 	Integer.valueOf(SGGAHandler.c_Libtad));
			m_Elements.put( SGGAHandler.c_CodtapElement , 	Integer.valueOf(SGGAHandler.c_Codtap));
			m_Elements.put( SGGAHandler.c_LibtapElement , 	Integer.valueOf(SGGAHandler.c_Libtap));
			m_Elements.put( SGGAHandler.c_DenrueElement , 	Integer.valueOf(SGGAHandler.c_Denrue));
			m_Elements.put( SGGAHandler.c_MdiElement , 		Integer.valueOf(SGGAHandler.c_Mdi));
			m_Elements.put( SGGAHandler.c_PrefpayElement , 	Integer.valueOf(SGGAHandler.c_Prefpay));
			m_Elements.put( SGGAHandler.c_CodcdpElement , 	Integer.valueOf(SGGAHandler.c_Codcdp));
			m_Elements.put( SGGAHandler.c_LibcptElement , 	Integer.valueOf(SGGAHandler.c_Libcpt));
			m_Elements.put( SGGAHandler.c_LibpayElement , 	Integer.valueOf(SGGAHandler.c_Libpay));
			m_Elements.put( SGGAHandler.c_PaiimpElement , 	Integer.valueOf(SGGAHandler.c_Paiimp));
			m_Elements.put( SGGAHandler.c_DebutElement , 	Integer.valueOf(SGGAHandler.c_Debut));
			m_Elements.put( SGGAHandler.c_FinElement , 		Integer.valueOf(SGGAHandler.c_Fin));
			m_Elements.put( SGGAHandler.c_DatecreElement , 	Integer.valueOf(SGGAHandler.c_Datecre));
			m_Elements.put( SGGAHandler.c_DateupdElement , 	Integer.valueOf(SGGAHandler.c_Dateupd));
     		}
	
    private static Pattern 
    
    c_ContentPattern = Pattern.compile ("^\\s*?(\\w+)\\s*?$",Pattern.CASE_INSENSITIVE);
   
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public SGGAHandler ()
	{
	super ();
	
	m_Logger = new Logger (this.getClass());
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * writes the specified message with the specified log level into the log
 * file.
 * @param p_Level specifies the log level the specified message should have.
 * @param p_Message specifies the message to be written to log file.
 */
//---------------------------------------------------------------------------

protected void log (Level p_Level, String p_Message)
	{
	m_Logger.log (p_Level,p_Message,null);
	}

//---------------------------------------------------------------------------
/**
 * writes the specified message with the specified log level into the log
 * file. The stack trace of the specified exception will be logged to.
 * @param p_Level specifies the log level the specified message should have.
 * @param p_Message specifies the message to be written to log file.
 * @param p_Exception specifies the exception to log stack trace of.
 */
//---------------------------------------------------------------------------

protected void log (Level p_Level, String p_Message, Exception p_Exception)
	{
	m_Logger.log (p_Level, p_Message, p_Exception);
	}

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

private Zip getPrimaryZip (String p_PrimaryKey)
	{	
	if ((m_PrimaryZips != null) && m_PrimaryZips.containsKey(p_PrimaryKey))
		 return m_PrimaryZips.get(p_PrimaryKey);
	else return null;
	}

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

public void startDocument() 
	{
	m_PrimaryZips = new Hashtable <String,Zip> ();
	}

//---------------------------------------------------------------------------
public void startElement (String p_URI, String p_LocalName, String p_QualifiedName, Attributes p_Attributes) 
	{
	int	l_Element;
	
	if (m_Elements.containsKey(p_QualifiedName))
		{
		l_Element = m_Elements.get(p_QualifiedName);
		
		switch (l_Element)
			{	
			case c_Rowset 	: m_Zips = new ArrayList <Zip> ();
							  break;
			case c_Row	  	: m_CurrentZip = new Zip ();
							  break;
			case c_Primkey	: m_Property = SGGAHandler.c_PrimaryKey;			
			  				  break;			
			case c_Prckey	: m_Property = SGGAHandler.c_ForeignKey;			
			  				  break;
			case c_Typden	: m_Property = SGGAHandler.c_Type;	
			  				  break;
			case c_Libtap   : m_Property = SGGAHandler.c_Appelation;
							  break;
			case c_Denrue	: m_Property = SGGAHandler.c_Street;
							  break;
			case c_Prefpay	: m_Property = SGGAHandler.c_Country;
							  break;
			case c_Codcdp   : m_Property = SGGAHandler.c_Zip;
							  break;
			case c_Libcpt	: m_Property = SGGAHandler.c_Locality;
							  break;
			case c_Libpay	: m_Property = SGGAHandler.c_Country;
							  break;
			case c_Paiimp	: m_Property = SGGAHandler.c_Parity;
							  break;
			case c_Debut	: m_Property = SGGAHandler.c_First;
			  				  break;
			case c_Fin		: m_Property = SGGAHandler.c_Last;
			  				  break;
			default			: m_Property = "";
							  break;
			}
		}
	}

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

public void characters (char[] p_Chars, int p_Start, int p_Length) 
	{
	String	l_Value;
	Matcher	l_Matcher;
	
	if ((m_CurrentZip != null) && (m_Property != null) && (m_Property.length() > 0))
		{
		l_Value = new String (p_Chars,p_Start,p_Length);		
		l_Matcher = c_ContentPattern.matcher(l_Value);
		
		if (l_Matcher.matches())
			{
			m_CurrentZip.setProperty (m_Property, l_Matcher.group(1));
			}
		}
	}

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

public void endElement (String p_URI, String p_LocalName, String p_QualifiedName) 
	{
	int				l_Element;
	String			l_Type;
	String			l_PrimaryKey;
	String			l_Appelation;
	StringBuffer	l_Street;
	
	if (m_Elements.containsKey(p_QualifiedName))
		{
		l_Element = m_Elements.get(p_QualifiedName);
		
		switch (l_Element)
			{	
			case c_Row 	    : if ((m_Zips != null) && (m_CurrentZip != null))
							      {
								  if (m_CurrentZip.containsNonAssignable(c_Appelation))
								  	{
									l_Appelation = (String) m_CurrentZip.getNonAssignable(c_Appelation);  
								  	if ((l_Appelation != null) && (l_Appelation.length() > 0))
								  		{
								  		l_Street = new StringBuffer (l_Appelation);
								  		l_Street.append(" ").append(m_CurrentZip.getStreet());
								  		m_CurrentZip.setStreet(l_Street.toString());
								  		// m_CurrentZip.removeNonAssignable(c_Appelation);
								  		}
								  	}
				
								  m_Zips.add(m_CurrentZip);
								  
							      if (m_CurrentZip.containsNonAssignable(c_Type))
							      	{
							    	l_Type = (String) m_CurrentZip.getNonAssignable(c_Type);
							      	if (c_TypePRC.equals(l_Type))
							      		{
							      		l_PrimaryKey = (String) m_CurrentZip.getNonAssignable(c_PrimaryKey);
							      		if (l_PrimaryKey != null) m_PrimaryZips.put(l_PrimaryKey, m_CurrentZip);
							      		}
							      	}
							      }
							  break;
			
			case c_Paiimp	: if (m_CurrentZip != null)
								{
								if (c_ParityEven.equals(m_CurrentZip.getParity())) m_CurrentZip.setParity(Zip.EVEN); 
								else if (c_ParityOdd.equals(m_CurrentZip.getParity())) m_CurrentZip.setParity(Zip.ODD); 
								else m_CurrentZip.setParity(Zip.NONE);
								}
			}
		}
	}

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

public void endDocument() 
	{
	}

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

public Collection <Zip>	getZips ()
	{
	return m_Zips;
	}
	
//---------------------------------------------------------------------------

public void resolveDependencies ()
	{
	Iterator <Zip>	l_ZipIterator;
	Zip				l_Zip;
	String			l_ForeignKey;
	Zip				l_PrimaryZip;
	
	if (m_Zips != null)
		{
		l_ZipIterator = m_Zips.iterator();
		if (l_ZipIterator.hasNext())
			{
			l_Zip = l_ZipIterator.next();
			if (l_Zip.containsNonAssignable(c_ForeignKey))
				{
				l_ForeignKey = (String) l_Zip.getNonAssignable (c_ForeignKey);
				l_PrimaryZip = this.getPrimaryZip(l_ForeignKey);
				if (l_PrimaryZip != null)
					{
					l_Zip.setZip(l_PrimaryZip.getZip());
					}
				}
			}		
		}
	}
	
//---------------------------------------------------------------------------
//***************************************************************************
//* End of Class                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
	}
