src.com.ibm.as400.vaccess.SQLResultSetFormPane Maven / Gradle / Ivy
Show all versions of jt400-jdk8 Show documentation
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: SQLResultSetFormPane.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2000 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.vaccess;
import com.ibm.as400.access.ActionCompletedListener;
import com.ibm.as400.access.ActionCompletedEvent;
import javax.swing.SwingConstants;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Types;
/**
The SQLResultSetFormPane class represents a form that is filled in with the
result set generated by a SQL query using JDBC. The
form displays one record of the result set at a time and provides
buttons that allow the user to scroll forward,
backward, to the first or last record, or refresh the
view of the result set.
The data in the form is retrieved from the system
(and the GUI fields for the data are created)
when load() is called. If load() is not called,
the form will be empty.
It is up to the user to register a JDBC driver when using this class.
For example, the following code registers the IBM Toolbox for Java
JDBC driver.
DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
Users should call close() to ensure that the result set
is closed when this table is no longer needed. close() should
also be called on the SQLConnection object as well to close the connection.
Most errors are reported by firing ErrorEvents, rather
than throwing exceptions. Users should listen for ErrorEvents
in order to diagnose and recover from error conditions.
SQLResultSetFormPane objects generate the following events:
- ActionCompletedEvent
- ErrorEvent
- PropertyChangeEvent
// Register JDBC driver.
DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
// Set up table for result set contents.
final SQLConnection connection = new SQLConnection("jdbc:as400://MySystem", "Userid", "Password");
String query = "SELECT * FROM MYLIB.MYTABLE";
final SQLResultSetFormPane pane = new SQLResultSetFormPane(connection, query);
// Set up window to hold table
JFrame frame = new JFrame ("My Window");
WindowListener l = new WindowAdapter()
{
// Close the pane when window is closed.
public void windowClosing(WindowEvent e)
{
pane.close();
connection.close();
}
};
frame.addWindowListener(l);
// Set up the error dialog adapter.
pane.addErrorListener (new ErrorDialogAdapter (frame));
// Add the component and get data from system.
frame.getContentPane().add(pane);
pane.load();
// Display the window
frame.setVisible(true)
@deprecated Use Java Swing instead, along with the classes in package com.ibm.as400.access
**/
public class SQLResultSetFormPane
extends JComponent
implements Serializable
{
private static final String copyright = "Copyright (C) 1997-2000 International Business Machines Corporation and others.";
// The variables which have private commented out had to made
// package scope since currently Internet Explorer does not
// allow inner class to access private variables in their
// containing class.
// Label for the record number.
transient private JLabel recordLabel_; //@B0C - made transient
// Label for the record number.
transient private JLabel recordNumber_; //@B0C - made transient
// Button for moving to the first record.
/*private*/ transient JButton firstButton_; //@B0C - made transient
// Button for moving to the last record.
/*private*/ transient JButton lastButton_; //@B0C - made transient
// Button for moving to the next record.
/*private*/ transient JButton nextButton_; //@B0C - made transient
// Button for moving to the previous record.
/*private*/ transient JButton previousButton_; //@B0C - made transient
// Button for refreshing the result set.
/*private*/ transient JButton refreshButton_; //@B0C - made transient
// Labels for the description of each field.
transient private JLabel[] labels_ = new JLabel[0];
// Textfields for the value of each field.
transient private JTextField[] values_ = new JTextField[0];
// Formatters for the value of each field.
transient private DBCellRenderer[] formatter_ = new DBCellRenderer[0];
// Status line. Used for errors.
private JLabel status_;
// Panel used for center data area.
private JPanel dataArea_;
// Renderers for the different types of data, textfields use these.
private DBCellRenderer leftCell_ = new DBCellRenderer(SwingConstants.LEFT);
private DBDateCellRenderer dateCell_ = new DBDateCellRenderer(DBDateCellRenderer.FORMAT_DATE);
private DBDateCellRenderer timeCell_ = new DBDateCellRenderer(DBDateCellRenderer.FORMAT_TIME);
private DBDateCellRenderer timestampCell_ = new DBDateCellRenderer(DBDateCellRenderer.FORMAT_TIMESTAMP);
// General types of data in columns. Used to determine column renderer.
private static final int TYPE_CHAR = 1;
private static final int TYPE_TIME = 2;
private static final int TYPE_TIMESTAMP = 3;
private static final int TYPE_DATE = 4;
private static final int TYPE_BIT = 5;
// Event support.
transient private ActionCompletedEventSupport actionListeners_
= new ActionCompletedEventSupport (this);
transient /*private*/ ErrorEventSupport errorListeners_
= new ErrorEventSupport (this);
// Result set data
transient int current_ = -1; // Record being shown. Range is 0 to numRows-1.
private SQLResultSetData tableData_ = new SQLResultSetData();
// Flag for if an error event was sent.
transient /*private*/ boolean error_;
// Adapter for listening for working events and enabling working cursor.
transient private WorkingCursorAdapter worker_
= new WorkingCursorAdapter(this);
/**
Constructs a SQLResultSetFormPane object.
**/
public SQLResultSetFormPane ()
{
super();
//@B0A
// We add a fake FocusListener whose real purpose is to uninstall
// the UI early so the JTable that is part of our UI does not try
// to get serialized.
// See also: source code for javax.swing.JComponent in JDK 1.2.
addFocusListener(new SerializationListener(this)); //@B0A
// Add self as listener for errors and work events
tableData_.addErrorListener(new ErrorListener_());
tableData_.addWorkingListener(worker_);
init();
}
/**
Constructs a SQLResultSetFormPane object.
@param connection The SQL connection.
@param query The SQL query.
**/
public SQLResultSetFormPane (SQLConnection connection,
String query)
{
super();
if (connection == null)
throw new NullPointerException("connection");
if (query == null)
throw new NullPointerException("query");
//@B0A
// We add a fake FocusListener whose real purpose is to uninstall
// the UI early so the JTable that is part of our UI does not try
// to get serialized.
// See also: source code for javax.swing.JComponent in JDK 1.2.
addFocusListener(new SerializationListener(this)); //@B0A
tableData_.setConnection(connection);
tableData_.setQuery(query);
// Add self as listener for errors and work events
tableData_.addErrorListener(new ErrorListener_());
tableData_.addWorkingListener(worker_);
init();
}
/**
Adds a listener to be notified when a new record is displayed.
The listener's actionCompleted() method will be called.
@param listener The listener.
**/
public void addActionCompletedListener (ActionCompletedListener listener)
{
actionListeners_.addActionCompletedListener(listener);
}
/**
Adds a listener to be notified when an error occurs.
The listener's errorOccurred() method will be called.
@param listener The listener.
**/
public void addErrorListener (ErrorListener listener)
{
errorListeners_.addErrorListener (listener);
}
/**
Clears all SQL warnings.
**/
public void clearWarnings ()
{
tableData_.clearWarnings();
}
/**
Closes the SQL result set this form represents.
**/
public void close()
{
tableData_.close();
}
/**
Displays the first record of the result set.
**/
public void displayFirst ()
{
synchronized (this)
{
current_ = 0;
refreshScreen();
}
// Send event.
actionListeners_.fireActionCompleted();
}
/**
Displays the last record of the result set.
**/
public void displayLast ()
{
synchronized (this)
{
error_ = false;
current_ = tableData_.getNumberOfRows() - 1;
if (error_) // error during getNumberOfRows
current_ = tableData_.getLastRecordProcessed();
refreshScreen();
}
// Send event.
actionListeners_.fireActionCompleted();
}
/**
Displays the next record of the result set.
If the last record is being displayed, the first record
will be displayed.
**/
public void displayNext ()
{
synchronized (this)
{
// Move the current record index.
if (tableData_.getAllRecordsProcessed())
{
// Do not want to do getNumberOfRows unless all records processed
// since getNumberOfRows will process all records.
// getNumberOfRows should never fire an error here.
if (current_+1 == tableData_.getNumberOfRows())
current_ = 0;
else
++current_;
}
else
{
++current_;
}
refreshScreen();
}
// Send event.
actionListeners_.fireActionCompleted();
}
/**
Displays the previous record of the result set.
If the first record is being displayed, the last record
will be displayed.
**/
public void displayPrevious ()
{
synchronized (this)
{
// Move the current record index.
if (current_ < 1)
{
error_ = false;
current_ = tableData_.getNumberOfRows() - 1;
if (error_) //getNumberOfRows() failed
{
current_ = tableData_.getLastRecordProcessed();
}
}
else
{
--current_;
}
refreshScreen();
}
// Send event.
actionListeners_.fireActionCompleted();
}
/**
Returns the SQL connection with which to access data.
@return The SQL connection.
**/
public SQLConnection getConnection ()
{
return tableData_.getConnection();
}
/**
Returns the index of the record currently being displayed.
Indices start at 0, and increment one for each of the records
in the result set.
Note that this is not the same as the record number.
@return The index of the record currently being displayed.
If there is no record being displayed, -1 is returned.
**/
synchronized public int getCurrentRecord()
{
return current_;
}
/**
Returns the text of the label at the given index.
@param index The index of the label. Indices start at 0.
@return The text of the label at the given index.
**/
synchronized public String getLabelText(int index)
{
return labels_[index].getText();
}
/**
Returns the SQL query used to generate the form data.
@return The SQL query.
**/
public String getQuery ()
{
String result = tableData_.getQuery();
if (result == null)
return "";
return result;
}
/**
Returns the string value of the current record at the given index.
@param index The index of the value. Indices start at 0.
@return The value at the given index as a string.
**/
synchronized public String getStringValueAt(int index)
{
return values_[index].getText();
}
/**
Returns the value of the current record at the given index.
@param index The index of the value. Indices start at 0.
@return The value at the given index.
**/
synchronized public Object getValueAt(int index)
{
return tableData_.getValueAt(current_, index);
}
/**
Returns the warnings generated by the JDBC connection, statement, and
result set.
The warnings from the result set will be
linked to the end of any statement warnings, which in turn are linked
to the end of any connection warnings.
Warnings are cleared when load() or clearWarnings()
is called.
@return The warnings generated by the connection, statement, and
result set, or null if none.
**/
public SQLWarning getWarnings ()
{
return tableData_.getWarnings();
}
/**
Create GUI.
**/
private void init()
{
//------------------------------------------------------
// Create constant screen components. Data fields will
// be created by load().
//------------------------------------------------------
// Create position labels.
recordLabel_ = new JLabel(ResourceLoader.getText("DBFORM_LABEL_RECORD_NUMBER"));
recordNumber_ = new JLabel();
// Create all the buttons.
String text = ResourceLoader.getText("DBFORM_TOOLTIP_FIRST");
firstButton_ = new JButton(ResourceLoader.getIcon("FirstIcon.gif", text));
firstButton_.setToolTipText(text);
text = ResourceLoader.getText("DBFORM_TOOLTIP_LAST");
lastButton_ = new JButton(ResourceLoader.getIcon("LastIcon.gif", text));
lastButton_.setToolTipText(text);
text = ResourceLoader.getText("DBFORM_TOOLTIP_NEXT");
nextButton_ = new JButton(ResourceLoader.getIcon("NextIcon.gif", text));
nextButton_.setToolTipText(text);
text = ResourceLoader.getText("DBFORM_TOOLTIP_PREVIOUS");
previousButton_ = new JButton(ResourceLoader.getIcon("PreviousIcon.gif", text));
previousButton_.setToolTipText(text);
text = ResourceLoader.getText("DBFORM_TOOLTIP_REFRESH");
refreshButton_ = new JButton(ResourceLoader.getIcon("RefreshIcon.gif", null));
refreshButton_.setToolTipText(text);
// Add listeners to buttons to call correct functions.
ButtonListener_ l = new ButtonListener_();
firstButton_.addActionListener(l);
lastButton_.addActionListener(l);
nextButton_.addActionListener(l);
previousButton_.addActionListener(l);
refreshButton_.addActionListener(l);
// build center data area
dataArea_ = new JPanel();
dataArea_.setBorder(new EmptyBorder(5,5,5,5));
// build status line
status_ = new JLabel(ResourceLoader.getText("DBFORM_MSG_NO_DATA"));
//------------------------------------------------------
// Build the constant screen components. Data fields will
// be added by load().
//------------------------------------------------------
// Set main layout to border layout.
setLayout(new BorderLayout());
// Add buttons to panel.
JPanel panel1 = new JPanel();
panel1.setLayout(new FlowLayout(FlowLayout.CENTER));
panel1.add(firstButton_);
panel1.add(previousButton_);
panel1.add(nextButton_);
panel1.add(lastButton_);
panel1.add(refreshButton_);
// Add status line to panel.
JPanel panel2 = new JPanel();
panel2.setLayout(new FlowLayout(FlowLayout.CENTER));
panel2.add(status_);
// Add buttons and status to bottom.
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add("North", panel1);
panel.add("South", panel2);
add("South", panel);
// Add position labels.
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
panel.add(recordLabel_);
panel.add(recordNumber_);
add("North", panel);
// Add center data area
add("Center", dataArea_);
}
/**
Refreshes the view based on the state of the system. This runs
the SQL query. The first record will be displayed.
The labels are reconstructed, so any label text customization will be lost.
The query and connection properties
must be set before this method is called.
**/
public void load ()
{
synchronized (this)
{
// Remove any previous components from the screen
dataArea_.removeAll();
// verify we have enough info to get data
IllegalStateException exception = null;
error_ = false;
if (tableData_.getConnection() == null)
{
exception = new IllegalStateException("connection");
error_ = true;
}
else if (tableData_.getQuery() == null)
{
exception = new IllegalStateException("query");
error_ = true;
}
else
{
// Do a load to make sure we have no errors.
// Other calls should not throw errors once a load is done
// successfully.
tableData_.load();
}
if (error_)
{
values_ = new JTextField[0];
labels_ = new JLabel[0];
current_ = -1;
refreshScreen();
if (exception != null)
throw exception;
return;
}
// Build labels, values and formatters.
// Add all fields to the screen.
int num = tableData_.getNumberOfColumns();
// label variables
labels_ = new JLabel[num];
JLabel label;
// value variables
values_ = new JTextField[num];
JTextField value;
// formatter variables
formatter_ = new DBCellRenderer[num];
// panel setup
dataArea_.setLayout(new GridLayout(num,1));
JPanel panel;
int type, sqltype;
// Loop through each field in the record.
for (int i=0; iload() is done.
@param connection The SQL connection.
@exception PropertyVetoException If the change is vetoed.
**/
public void setConnection (SQLConnection connection)
throws PropertyVetoException
{
if (connection == null)
throw new NullPointerException("connection");
SQLConnection old = getConnection();
// Fire a vetoable change event.
fireVetoableChange("connection", old, connection);
// Make property change.
tableData_.setConnection(connection);
// Fire the property change event.
firePropertyChange("connection", old, connection);
}
/**
Sets the text of the label at the given index.
@param index The index of the label. Indices start at 0.
@param text The text of the label.
**/
synchronized public void setLabelText(int index,
String text)
{
labels_[index].setText(text);
}
/**
Sets the SQL query used to generate the result set.
This property is bound and constrained.
Note that the data in the form will not change
until a load() is done.
@param query The SQL query.
@exception PropertyVetoException If the change is vetoed.
**/
public void setQuery (String query)
throws PropertyVetoException
{
if (query == null)
throw new NullPointerException("query");
String old = getQuery();
// Fire a vetoable change event.
fireVetoableChange("query", old, query);
// Make property change.
tableData_.setQuery(query);
// Fire the property change event.
firePropertyChange("query", old, query);
}
/**
Class for listening to action events. This is used to run the
SQL statement when the button is pressed.
**/
private class ButtonListener_
implements ActionListener
{
public void actionPerformed(ActionEvent ev)
{
// try to perform the appropriate action
Object source = ev.getSource();
if (source == firstButton_)
{
displayFirst();
}
else if (source == lastButton_)
{
displayLast();
}
else if (source == nextButton_)
{
displayNext();
}
else if (source == previousButton_)
{
displayPrevious();
}
else if (source == refreshButton_)
{
load();
}
// else unknown source - ignore
}
} // end of class ButtonListener_
/**
Class for listening to error events. The error_ flag is set,
and the event's source is changed and redispatched to our listeners.
**/
private class ErrorListener_
implements ErrorListener
{
public void errorOccurred(ErrorEvent event)
{
// set flag that an error occurred
error_ = true;
// Change the source in the event and fire
// to our listeners.
errorListeners_.fireError(event.getException());
}
} // end of class ErrorListener_
}