package mit.sql.ui ;

public class SQLComponent
extends mit.swing.xJComponent
implements	mit.comm.event.DisplayResultRaiser
	,	mit.rmi.event.InvokeMethodRaiser
	,	mit.event.Listener
{
	private static final Class[] noargsTypes = new Class[ 0 ] ;
	private static final Object[] noargs = new Object[ 0 ] ;
	private static final String sqlId = "SQL" ;

	private mit.event.RaiserAdapter raiserAdapter = new mit.event.RaiserAdapter( this ) ;
	public mit.event.RaiserAdapter getRaiserAdapter() { return this.raiserAdapter ; }
	public void setRaiserAdapter( mit.event.RaiserAdapter raiserAdapter ) { this.raiserAdapter = raiserAdapter ; }

	private mit.event.ListenerAdapter listenerAdapter = new mit.event.ListenerAdapter( this ) ;
	public mit.event.ListenerAdapter getListenerAdapter() { return this.listenerAdapter ; }
	public void setListenerAdapter( mit.event.ListenerAdapter listenerAdapter ) { this.listenerAdapter = listenerAdapter ; }

	private sql.Connection connection = null ;
	private sql.SqlFactory factory = null ;

	private String database = null ;
	public String getDatabase() { return this.database ; }
	public void setDatabase( String database ) { this.database = database ; }

	private String username = null ;
	public String getUsername() { return this.username ; }
	public void setUsername( String username ) { this.username = username ; }

	private String password = null ;
	private String getPassword() { return this.password ; }
	public void setPassword( String password ) { this.password = password ; }

	private java.io.Serializable object = null ;
	public java.io.Serializable getObject() { return this.object ; }
	public void setObject( java.io.Serializable object ) { this.object = object ; }

	private String methodName = null ;
	public String getMethodName() { return this.methodName ; }
	public void setMethodName( String methodName ) { this.methodName = methodName ; }

	private sql.Table methodResponse = null ;
	public sql.Table getMethodResponse() { return this.methodResponse ; }
	public void setMethodResponse( sql.Table methodResponse ) { this.methodResponse = methodResponse ; }

	private sql.Table procedureColumnsResponse = null ;
	public sql.Table getProcedureColumnsResponse() { return this.procedureColumnsResponse ; }
	public void setProcedureColumnsResponse( sql.Table procedureColumnsResponse ) { this.procedureColumnsResponse = procedureColumnsResponse ; }

	private Class[] argTypes = null ;
	public Class[] getArgTypes() { return this.argTypes ; }
	public void setArgTypes( Class[] argTypes ) { this.argTypes = argTypes ; }

	private Object[] args = null ;
	public Object[] getArgs() { return this.args ; }
	public void setArgs( Object[] args ) { this.args = args ; }

	private String status = null ;
	public String getStatus() { return this.status ; }
	public void setStatus( String status ) { this.status = status ; }

	private String statusMessage = null ;
	public String getStatusMessage() { return this.statusMessage ; }
	public void setStatusMessage( String statusMessage ) { this.statusMessage = statusMessage ; }

	private javax.swing.JComponent resultsComponent = null ;
	public javax.swing.JComponent getResultsComponent() { return this.resultsComponent ; }
	public void setResultsComponent( javax.swing.JComponent resultsComponent ) { this.resultsComponent = resultsComponent ; }

	private java.util.Vector criteriaComponents = null ;
	public java.util.Vector getCriteriaComponents() { return this.criteriaComponents ; }
	public void setCriteriaComponents( java.util.Vector criteriaComponents ) { this.criteriaComponents = criteriaComponents ; }

	private mit.swing.xJButton[] actionButtons = null ;
	public mit.swing.xJButton[] getActionButtons() { return this.actionButtons ; }
	public void setActionButtons( mit.swing.xJButton[] actionButtons ) { this.actionButtons = actionButtons ; }

	private mit.sql.ui.Table table = null ;
	public mit.sql.ui.Table getTable() { return this.table ; }
	public void setTable( mit.sql.ui.Table table ) { this.table = table ; }

	private String storedProcedureName = null ;
	public String getStoredProcedureName() { return this.storedProcedureName ; }
	public void setStoredProcedureName( String storedProcedureName ) { this.storedProcedureName = storedProcedureName ; }

	private String tableName = null ;
	public String getTableName() { return this.tableName ; }
	public void setTableName( String tableName ) { this.tableName = tableName ; }

	public void eventRaised( mit.event.Event e )
	{
		try
		{
			if( e instanceof mit.sql.event.TableEvent )
			{
				HandleTableEvent( ( mit.sql.event.TableEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.GetProceduresEvent )
			{
				HandleGetProceduresEvent( ( mit.sql.event.GetProceduresEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.GetTablesEvent )
			{
				HandleGetTablesEvent( ( mit.sql.event.GetTablesEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.ExecuteEvent )
			{
				HandleExecuteEvent( ( mit.sql.event.ExecuteEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.QueryEvent )
			{
				HandleQueryEvent( ( mit.sql.event.QueryEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.UpdateEvent )
			{
				HandleUpdateEvent( ( mit.sql.event.UpdateEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.UsernameEvent )
			{
				HandleUsernameEvent( ( mit.sql.event.UsernameEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.PasswordEvent )
			{
				HandlePasswordEvent( ( mit.sql.event.PasswordEvent ) e ) ;
			}
			else if( e instanceof mit.sql.event.DatabaseNameEvent )
			{
				HandleDatabaseNameEvent( ( mit.sql.event.DatabaseNameEvent ) e ) ;
			}
			else if( e instanceof mit.rmi.event.MethodResponseEvent )
			{
				HandleMethodResponseEvent( ( mit.rmi.event.MethodResponseEvent ) e ) ;
			}
		}
		catch( Throwable ex )
		{
			ex.printStackTrace() ;
		}
	}

	private synchronized void HandleMethodResponseEvent( mit.rmi.event.MethodResponseEvent e )
		throws Exception
	{
		mit.rmi.event.MethodResponseRaiser r = ( mit.rmi.event.MethodResponseRaiser ) e.getSource() ;
		HandleResponse( r.getMethodName() , r.getMethodResponse() ) ;
	}

	private void HandleResponse( String methodName , Object methodResponse )
		throws Exception
	{
System.out.println( "SQLComponent.HandleResponse: " + methodName + ", " + methodResponse ) ;
		if( null != methodResponse )
		{
			if( "getDefaultSqlFactory".equals( methodName ) )
			{
				this.factory = ( sql.SqlFactory ) methodResponse ;
System.out.println( "SQLComponent.HandleResponse (should be non-null) getDefaultSqlFactory: " + methodResponse ) ;
				return ;
			}
			if( "newConnection".equals( methodName ) )
			{
				this.connection = ( sql.Connection ) methodResponse ;
System.out.println( "SQLComponent.HandleResponse newConnection: " + methodResponse ) ;
				return ;
			}
			if( methodResponse instanceof sql.Table )
			{
				setMethodResponse( ( sql.Table ) methodResponse ) ;
			}
			if( "getProcedureColumns".equals( methodName ) )
			{
				setProcedureColumnsResponse( getMethodResponse() ) ;
			}
			if( ( "getProcedures".equals( methodName ) )
			||  ( "getProcedureColumns".equals( methodName ) )
			||  ( "getTables".equals( methodName ) )
			||  ( "executeQuery".equals( methodName ) )
			||  ( "executeUpdate".equals( methodName ) )
			||  ( "callProcedure".equals( methodName ) )
 			)
			{
				sql.Table table = ( sql.Table ) getMethodResponse() ;
				if( null != table )
				{
					setResultsComponent( createResultsComponent( table ) ) ;
					if( "getProcedureColumns".equals( methodName ) )
					{
						setCriteriaComponents( createCriteriaComponents( table ) ) ;
					}
					setActionButtons( createActionButtons( methodName ) ) ;
					( new mit.comm.event.DisplayResultEvent( this ) ).raise() ;
				}
			}
		}
	}

	private javax.swing.JComponent createResultsComponent( sql.Table table )
		throws Exception
	{
		if( null != table )
		{
			java.util.Vector rowsV = new java.util.Vector() ;;
			sql.Rows rows = table.getRows() ;
			while( rows.hasMoreRows() )
			{
				rowsV.addElement( rows.nextRow() ) ;
			}
			Object[] dataV = rowsV.toArray() ;
			Object[][] data = new Object[ dataV.length ][ rows.getRowsMetaData().getColumnCount() ] ;
			for( int i = 0 ; data.length != i ; i ++ )
			{
				data[ i ] = ( Object[] ) dataV[ i ] ;
			}
			mit.sql.ui.Table uiTable = new mit.sql.ui.Table() ;
			String[] columnNames = rows.getColumnNames() ;
			columnNames = cleanColumnNames( columnNames ) ;
			uiTable.setColNames( rows.getColumnNames() ) ;
			data = cleanData( data ) ;
			uiTable.setTableData( data ) ;
			return new mit.swing.xJScrollPane( this , uiTable ) ;
		}
		return null ;
	}

	private String[] cleanColumnNames( String[] names )
	{
		if( null != names )
		{
			for( int i = 0 ; names.length != i ; i ++ )
			{
				if( null == names[ i ] )
				{
					names[ i ] = "" ;
				}
			}
		}
		return names ;
	}

	private Object[][] cleanData( Object[][] data )
	{
		if( null != data )
		{
			for( int i = 0 ; data.length != i ; i ++ )
			{
				for( int j = 0 ; data[ i ].length != j ; j ++ )
				{
					if( null == ( data[ i ][ j ] ) )
					{
						data[ i ][ j ] = "" ;
					}
				}
			}
		}
		return data ;
	}

	private java.util.Vector createCriteriaComponents( sql.Table table )
		throws Exception
	{
		if( ( "getProcedureColumns".equals( methodName ) )
		||  ( "callProcedure".equals( methodName ) )
		)
		{
			if( null != table )
			{
				java.util.Vector components = new java.util.Vector() ;
				int i = 0 ;
				sql.Rows rows = table.getRows() ;
				while( rows.hasMoreRows() )
				{
					Object[] row = rows.nextRow() ;
					int dataType = ( ( Number ) row[ mit.sql.ui.Param.DATATYPE_COLUMN ] ).intValue() ;
					if( mit.sql.ui.Param.OUTPUT != dataType )
					{
						mit.sql.ui.Param param = new mit.sql.ui.Param() ;
						param.setLabel( ( String ) row[ mit.sql.ui.Param.NAME_COLUMN ] ) ;
						param.setDataType( dataType ) ;
						param.setType( ( String ) row[ mit.sql.ui.Param.TYPENAME_COLUMN ] ) ;
						param.setNumber( i ++ ) ;
						components.addElement( param ) ;
					}
				}
				return components ;
			}
		}
		return null ;
	}

	private mit.swing.xJButton[] createActionButtons( String methodName )
	{
		mit.swing.xJButton[] actionButtons = null ;
		if( ( "getProcedureColumns".equals( methodName ) )
		||  ( "callProcedure".equals( methodName ) )
		)
		{
			actionButtons = new mit.swing.xJButton[ 3 ] ;
			actionButtons[ 0 ] = new mit.sql.ui.GetProceduresButton() ;
			actionButtons[ 1 ] = new mit.sql.ui.GetTablesButton() ;
			actionButtons[ 2 ] = new mit.sql.ui.ExecuteButton() ;
		}
		else
		{
			actionButtons = new mit.swing.xJButton[ 2 ] ;
			actionButtons[ 0 ] = new mit.sql.ui.GetProceduresButton() ;
			actionButtons[ 1 ] = new mit.sql.ui.GetTablesButton() ;
		}
		return actionButtons ;
	}

	private void HandleExecuteEvent( mit.sql.event.ExecuteEvent e )
		throws Exception
	{
		initConnection() ;
		java.util.Vector criteria = getCriteriaComponents() ;
		if( ( null != connection )
		&&  ( null != criteria )
		)
		{
			if( null != getProcedureColumnsResponse() )
			{
				sql.Rows rows = getProcedureColumnsResponse().getRows() ;
				java.util.Vector rowsV = new java.util.Vector() ;
				while( rows.hasMoreRows() )
				{
					rowsV.addElement( rows.nextRow() ) ;
				}
				Object[] params = new Object[ rowsV.size() ] ;
				int[] columnTypes = new int[ rowsV.size() ] ;
				int[] dataTypes = new int[ rowsV.size() ] ;
				java.util.Enumeration enum = criteria.elements() ;
				sql.ColumnMetaData[] columnsMetaData
					= rows.getRowsMetaData().getColumnsMetaData() ;
				for( int i = 0 ; rowsV.size() != i ; i ++ )
				{
					Object[] row = ( Object[] ) rowsV.elementAt( i ) ;
					columnTypes[ i ] = getColumnType( columnsMetaData , row ) ;
					dataTypes[ i ] = getDataType( columnsMetaData , row ) ;
					params[ i ] = Void.class ;
					switch( columnTypes[ i ] )
					{
						case java.sql.DatabaseMetaData.procedureColumnIn:
						case java.sql.DatabaseMetaData.procedureColumnInOut:
						if( enum.hasMoreElements() )
						{
							javax.swing.JComponent comp = ( javax.swing.JComponent ) enum.nextElement() ;
							if( comp instanceof mit.swing.ui.LabeledTextField )
							{
								params[ i ] = ( ( mit.swing.ui.LabeledTextField ) comp ).getText() ;
							}
							else if( comp instanceof javax.swing.JTextField )
							{
								params[ i ] = ( ( javax.swing.JTextField ) comp ).getText() ;
							}
						}
					}
				}
				setObject( this.connection ) ;
				setMethodName( "callProcedure" ) ;
				Class[] argTypes = new Class[ 5 ] ;
				argTypes[ 0 ] = String.class ;
				argTypes[ 1 ] = sql.Table.class ;
				argTypes[ 2 ] = Object[].class ;
				argTypes[ 3 ] = int[].class ;
				argTypes[ 4 ] = int[].class ;
				setArgTypes( argTypes ) ;
				Object[] args = new Object[ 5 ] ;
				args[ 0 ] = getStoredProcedureName() ;
				args[ 1 ] = getProcedureColumnsResponse() ;
				args[ 2 ] = params ;
				args[ 3 ] = columnTypes ;
				args[ 4 ] = dataTypes ;
				setArgs( args ) ;
				try
				{
					( new mit.rmi.event.InvokeMethodEvent( this ) ).raise() ;
				}
				catch( Exception ex )
				{
					this.connection = null ;
					throw ex ;
				}
			}
		}
	}

	private int getColumnType
		( sql.ColumnMetaData[] columnsMetaData
		, Object[] row
		)
		throws Exception
	{
		for( int i = 0 ; columnsMetaData.length != i ; i ++ )
		{
			if( "COLUMN_TYPE".equals( columnsMetaData[ i ] ) )
			{
				return Integer.parseInt( ( String ) row[ i ] ) ;
			}
		}
		throw new sql.ConnectionException
			( sql.ConnectionException.INVALIDARGUMENTS ) ;
	}

	private int getDataType
		( sql.ColumnMetaData[] columnsMetaData
		, Object[] row
		)
		throws Exception
	{
		for( int i = 0 ; columnsMetaData.length != i ; i ++ )
		{
			if( "DATA_TYPE".equals( columnsMetaData[ i ] ) )
			{
				return Integer.parseInt( ( String ) row[ i ] ) ;
			}
		}
		throw new sql.ConnectionException
			( sql.ConnectionException.INVALIDARGUMENTS ) ;
	}

	private void initConnection()
	throws Exception
	{
System.out.println( "SQLComponent.initConnection" ) ;
		Class[] argTypes = null ;
		Object[] args = null ;
		if( null == factory )
		{
			setObject( sql.SqlFactory.class ) ;
			setMethodName( "getDefaultSqlFactory" ) ;
			argTypes = new Class[ 0 ] ;
			setArgTypes( argTypes ) ;
			args = new Object[ 0 ] ;
			setArgs( args ) ;
			( new mit.rmi.event.InvokeMethodEvent( this ) ).raise() ;
System.out.println( "SQLComponent.initConnection factory: " + factory ) ;
		}
		if( null != factory )
		{
System.out.println( "SQLComponent.initConnection connection: " + connection ) ;
			if( null == connection )
			{
				if( ( null != getDatabase() )
				&&  ( null != getUsername() )
				&&  ( null != getPassword() )
				)
				{
System.out.println( "SQLComponent.initConnection database: " + getDatabase() ) ;
System.out.println( "SQLComponent.initConnection username: " + getUsername() ) ;
System.out.println( "SQLComponent.initConnection password: " + getPassword() ) ;
					setObject( this.factory ) ;
					setMethodName( "newConnection" ) ;
					argTypes = new Class[ 4 ] ;
					argTypes[ 0 ] = String.class ;
					argTypes[ 1 ] = String.class ;
					argTypes[ 2 ] = String.class ;
					argTypes[ 3 ] = Object.class ;
					setArgTypes( argTypes ) ;
					args = new Object[ 4 ] ;
					args[ 0 ] = getDatabase() ;
					args[ 1 ] = getUsername() ;
					args[ 2 ] = getPassword() ;
					args[ 3 ] = sqlId ;
					setArgs( args ) ;
					( new mit.rmi.event.InvokeMethodEvent( this ) ).raise() ;
					return ;
				}
System.out.println( "SQLComponent.initConnection null connection" ) ;
			}
		}
	}

	private void HandleQueryEvent( mit.sql.event.QueryEvent e )
	throws Exception
	{
System.out.println( "SQLComponent.HandleQueryEvent" ) ;
		initConnection() ;
	}

	private void HandleUpdateEvent( mit.sql.event.UpdateEvent e )
	throws Exception
	{
System.out.println( "SQLComponent.HandleUpdateEvent" ) ;
		initConnection() ;
	}

	private void HandleGetProceduresEvent( mit.sql.event.GetProceduresEvent e )
	throws Exception
	{
		initConnection() ;
		if( null != connection )
		{
			Class[] argsTypes = new Class[ 3 ] ;
			argsTypes[ 0 ] = String.class ;
			argsTypes[ 1 ] = String.class ;
			argsTypes[ 2 ] = String.class ;
			Object[] args = new Object[ 3 ] ;
			args[ 0 ] = null ;
			args[ 1 ] = null ;
			args[ 2 ] = null ;
			setObject( connection ) ;
			setMethodName( "getProcedures" ) ;
			setArgTypes( argsTypes ) ;
			setArgs( args ) ;
			( new mit.rmi.event.InvokeMethodEvent( this ) ).raise() ;
		}
	}

	private void HandleGetTablesEvent( mit.sql.event.GetTablesEvent e )
	throws Exception
	{
		initConnection() ;
		if( null != connection )
		{
			setObject( connection ) ;
			setMethodName( "getTables" ) ;
			setArgTypes( noargsTypes ) ;
			setArgs( noargs ) ;
			( new mit.rmi.event.InvokeMethodEvent( this ) ).raise() ;
		}
	}

	private void HandleTableEvent( mit.sql.event.TableEvent e )
	throws Exception
	{
System.out.println( "SQLComponent.HandleGetTablesEvent" ) ;
		mit.sql.event.TableRaiser r = ( mit.sql.event.TableRaiser ) e.getSource() ;
		initConnection() ;
		if( null != connection )
		{
			setObject( connection ) ;
			Class[] classes = new Class[ 1 ] ;
			Object[] objects = new Object[ 1 ] ;
			if( "PROCEDURE_NAME".equals( r.getColumnName() ) )
			{
				classes = new Class[ 4 ] ;
				objects = new Object[ 4 ] ;
System.out.println( "SQLComponent.HandleGetTablesEvent PROCEDURE_NAME" ) ;
				setStoredProcedureName( r.getCell() ) ;
				setMethodName( "getProcedureColumns" ) ;
				objects[ 0 ] = null ;
				objects[ 1 ] = null ;
				objects[ 2 ] = r.getCell() ;
				objects[ 3 ] = null ;
				classes[ 0 ] = String.class ;
				classes[ 1 ] = String.class ;
				classes[ 2 ] = r.getCell().getClass() ;
				classes[ 3 ] = String.class ;
				setArgTypes( classes ) ;
				setArgs( objects ) ;
				( new mit.rmi.event.InvokeMethodEvent( this ) ).raise() ;
			}
			else if( "TABLE_NAME".equals( r.getColumnName() ) )
			{
System.out.println( "SQLComponent.HandleGetTablesEvent TABLE_NAME" ) ;
				setTableName( r.getCell() ) ;
System.out.println( "... " + getTableName() + " ..." ) ;
				setMethodName( "executeQuery" ) ;
				objects[ 0 ] = new String( "select * from " + getTableName() ) ;
				classes[ 0 ] = objects[ 0 ].getClass() ;
				setArgTypes( classes ) ;
				setArgs( objects ) ;
				( new mit.rmi.event.InvokeMethodEvent( this ) ).raise() ;
			}
		}
	}

	private void HandleUsernameEvent( mit.sql.event.UsernameEvent e )
	{
		mit.sql.event.UsernameRaiser r = ( mit.sql.event.UsernameRaiser ) e.getSource() ;
		setUsername( r.getUsername() ) ;
	}

	private void HandlePasswordEvent( mit.sql.event.PasswordEvent e )
	{
		mit.sql.event.PasswordRaiser r = ( mit.sql.event.PasswordRaiser ) e.getSource() ;
		setPassword( new String( r.getPassword() ) ) ;
	}

	private void HandleDatabaseNameEvent( mit.sql.event.DatabaseNameEvent e )
	{
		mit.sql.event.DatabaseNameRaiser r = ( mit.sql.event.DatabaseNameRaiser ) e.getSource() ;
		setDatabase( r.getDatabaseName() ) ;
	}

	public void addNotify()
	{
		super.addNotify() ;
		try
		{
			getListenerAdapter().addHandled( mit.sql.event.TableEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.QueryEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.ExecuteEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.UpdateEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.GetProceduresEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.GetTablesEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.UsernameEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.PasswordEvent.class ) ;
			getListenerAdapter().addHandled( mit.sql.event.DatabaseNameEvent.class ) ;
			getListenerAdapter().addHandled( mit.rmi.event.MethodResponseEvent.class ) ;
		}
		catch( Exception ex )
		{
			ex.printStackTrace() ;
		}
	}
}
