/*
* (C) Copyright IBM Corp. 2009
*
* LICENSE: Eclipse Public License v1.0
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.ibm.gaiandb.apps.dashboard;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class LtAndDsTab extends UpdatingTab implements ActionListener {
private static final long serialVersionUID = 7386019679008602855L;
// Use PROPRIETARY notice if class contains a main() method, otherwise use
// COPYRIGHT notice.
public static final String COPYRIGHT_NOTICE = "(c) Copyright IBM Corp. 2009";
private static final Logger LOGGER = Logger.getLogger(LtAndDsTab.class
.getName());
private static final int GRAPH_INTERVAL = 10000;
private static final String GRAPH_SQL = "SELECT GDB_NODE, LTNAME, LTDEF from new com.ibm.db2j.GaianQuery('select * from new com.ibm.db2j.GaianConfig(''LTDEFS'') GC', 'with_provenance') GQ order by LTNAME";
private static String PROPDEF_SQL = "select PROPID, PROPDEF from new com.ibm.db2j.GaianQuery("
+ "'select * from new com.ibm.db2j.GaianConfig(''FULLCONFIG'') GC', 'with_provenance') GQ";
static final String[] COLUMN_NAMES = { "Name", "Definition", "Constants" };
static final int LT_NAME_COLUMN = 0;
static final int LT_DEF_COLUMN = 1;
static final int LT_CONSTANT_COLUMN = 2;
private static final int COLUMN_PADDING = 10;
private JPanel filterPanel = null;
private JPanel tablePanel = null;
private JSplitPane graphTableSplit = null;
private JTable table = null;
private JLabel filterLabel = new JLabel("Filter: ");
JTextField filterText = new JTextField(20);
Map<String, String> logicalTables = new TreeMap<String, String>();
Map<String, String> listConfig = new HashMap<String, String>();
private LtAndDsGraph graph = null;
private String localNodeID = null;
private PreparedStatement graphStatement;
private PreparedStatement configStatement;
Updater graphUpdater;
private long lastUpdate = 0;
String savedFilter = null;
private DefaultTableModel tableModel = null;
public LtAndDsTab(Dashboard container) {
super(container, new BorderLayout(Dashboard.BORDER_SIZE,
Dashboard.BORDER_SIZE));
}
@Override
protected void create() {
/*
* FilterGraph Panel
*/
filterPanel = new JPanel(new GridBagLayout());
filterText.setEditable(true);
filterText.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent arg0) {
// DO NOTHING!
}
public void keyReleased(KeyEvent arg0) {
String input;
if (KeyEvent.getKeyText(arg0.getKeyCode()).equals("Escape")) {
input = null;
filterText.setText("");
} else {
input = filterText.getText();
}
// For refreshes
savedFilter = input;
// System.out.println("key released" + arg0.toString());
// Do this last
filterDisplay(input);
}
public void keyTyped(KeyEvent arg0) {
// DO NOTHING!
}
});
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
filterPanel.add(filterLabel, c);
c.gridx = 1;
filterPanel.add(filterText, c);
/*
* Graph Panel
*/
graph = LtAndDsGraph.getSingleton(this);
graph.setNodeRenderer(true);
graph.setBorder(BorderFactory.createEtchedBorder());
graph.panAbs(graph.getWidth() / 2, graph.getHeight() / 2);
localNodeID = container.getLocalNodeID();
graph.setLocalNode(localNodeID);
try {
graphStatement = conn.prepareStatement(GRAPH_SQL);
graphStatement.setQueryTimeout(Dashboard.QUERY_TIMEOUT);
configStatement = conn.prepareStatement(PROPDEF_SQL
+ " WHERE GDB_NODE = '" + localNodeID + "'");
configStatement.setQueryTimeout(Dashboard.QUERY_TIMEOUT);
} catch (SQLException e) {
if (container.checkConnection()) {
LOGGER.severe(unravelMessages(e));
destroy();
showError("Could not retrieve the logical table information.");
}
return;
}
graphUpdater = new Updater("LtAndDsTab.updateTab", GRAPH_INTERVAL) {
protected boolean update() {
if (System.currentTimeMillis() > lastUpdate
+ (long) GRAPH_INTERVAL) {
// System.out.println("Updating...");
return updateData();
} else {
return true;
}
}
public void wake() {
super.wake();
this.update();
}
};
addUpdater(graphUpdater);
/*
* Table Panel
*/
tablePanel = new JPanel(new GridBagLayout());
// tablePanel.setBackground(Color.BLUE); // For Testing
graphTableSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, graph,
tablePanel);
graphTableSplit.setResizeWeight(0.75);
tableModel = new DefaultTableModel();
table = new JTable(tableModel);
c.anchor = GridBagConstraints.LINE_START;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
tablePanel.add(new JScrollPane(table), c);
tableModel.setColumnIdentifiers(COLUMN_NAMES);
hideMessage();
this.add(filterPanel, BorderLayout.PAGE_START);
this.add(graphTableSplit, BorderLayout.CENTER);
updateData();
}
protected synchronized Boolean updateData() {
// Get the logical Tables
try {
ResultSet resultSet = graphStatement.executeQuery();
logicalTables.clear();
if (!resultSet.isClosed()) {
while (resultSet.next()) {
if (resultSet.getString("GDB_NODE").equals(localNodeID)) {
String lt = resultSet.getString("LTNAME").toUpperCase();
String ltDef = resultSet.getString("LTDEF");
logicalTables.put(lt, ltDef);
}
}
}
} catch (SQLException e) {
e.printStackTrace();
if (container.checkConnection()) {
LOGGER.severe(unravelMessages(e));
destroy();
showError("Could not display the logical table and data source information.");
}
return false;
}
// Get the config information
try {
ResultSet resultSet = configStatement.executeQuery();
if (!resultSet.isClosed()) {
while (resultSet.next()) {
String key = resultSet.getString("PROPID").toUpperCase();
String value = resultSet.getString("PROPDEF");
// System.out.println("key: " + key + " value: " + value);
listConfig.put(key, value);
}
}
} catch (SQLException e) {
e.printStackTrace();
if (container.checkConnection()) {
LOGGER.severe(unravelMessages(e));
destroy();
showError("Could not display the logical table and data source information.");
}
return false;
}
return filterDisplay(savedFilter);
}
protected boolean filterDisplay() {
return filterDisplay(null);
}
protected synchronized boolean filterDisplay(String filter) {
lastUpdate = System.currentTimeMillis();
// savedFilter may have been changed by LtAndDsGraph
if (!filterText.getText().equals(savedFilter)) {
filterText.setText(savedFilter);
}
// Work out the regex
String regex = "^";
if (filter != null) {
regex += filter.toLowerCase();
if (filter.contains("*")) {
regex = regex.replaceAll("\\*", ".*");
} else {
regex += ".*";
}
} else {
regex += ".*";
}
regex += "$";
// System.out.println("Compiled regex: " +
// Pattern.compile(regex).toString());
if (null == graph)
return false; // no-op if graph was destroyed
try {
// Show the node at the middle
graph.setEdge(localNodeID, localNodeID);
// Clear the table
tableModel.setRowCount(0);
for (Entry<String, String> logicalTable : logicalTables.entrySet()) {
String ltName = logicalTable.getKey();
// String ltDef = logicalTable.getValue();
if (!regex.equals("^")) {
if (Pattern.compile(regex).matcher(ltName.toLowerCase())
.find()) {
// Draw on the graph
graph.setEdge(ltName, localNodeID);
// Now do the table
Object[] ltRow = new Object[3];
ltRow[0] = ltName;
ltRow[1] = listConfig
.get(ltName.toUpperCase() + "_DEF");
ltRow[2] = listConfig.get(ltName.toUpperCase()
+ "_CONSTANTS");
tableModel.addRow(ltRow);
}
}
}
} catch (Exception e) {
e.printStackTrace();
if (container.checkConnection()) {
LOGGER.severe(unravelMessages(e));
destroy();
showError("Could not display the logical table and data source information.");
}
return false;
}
// Get the widths right
int columnCount = table.getColumnCount();
TableColumnModel columnModel = table.getColumnModel();
for (int y = 0; y < columnCount; y++) {
TableColumn column = columnModel.getColumn(y);
int maxWidth = column.getPreferredWidth();
for (int x = 0; x < table.getRowCount(); x++) {
maxWidth = Math.max(
maxWidth,
table.getCellRenderer(x, y)
.getTableCellRendererComponent(table,
table.getValueAt(x, y), false, false,
x, y).getPreferredSize().width);
}
column.setPreferredWidth(maxWidth + COLUMN_PADDING);
}
// Now add the cell Editors to the table
for (int i = 0; i < columnCount; i++) {
table.getColumnModel().getColumn(i)
.setCellEditor(new LtAndDsTableCellEditor(this));
}
tablePanel.updateUI();
for (KeyListener listener : table.getKeyListeners()) {
System.out.println("KeyListener: " + listener.toString());
}
graph.update();
graph.recenter();
return true;
}
@Override
protected void destroy() {
if (null != filterPanel) {
remove(filterPanel);
filterPanel = null;
}
if (null != graph) {
remove(graph);
graph = null;
}
if (null != tablePanel) {
remove(tablePanel);
tablePanel = null;
}
if (null != graphTableSplit) {
remove(graphTableSplit);
graphTableSplit = null;
}
graphUpdater = null;
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
class LtAndDsTableCellEditor extends AbstractCellEditor implements
TableCellEditor {
private static final long serialVersionUID = 3426752811053766328L;
// This is the component that will handle the editing of the cell value
JComponent component = new JTextField();
LtAndDsTab context = null;
int rowIndex = -1;
int colIndex = -1;
String originalText = null;
String ltName = null;
String ltDef = null;
String ltConstants = null;
public LtAndDsTableCellEditor(LtAndDsTab callerContext) {
context = callerContext;
}
// When editing begins...
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
// System.out.println("Started editing");
context.filterText.setEnabled(false);
context.graphUpdater.suspend();
component.setBorder(BorderFactory.createEmptyBorder());
// Escape on the table cancels editing, which is not handled by
// default. We handle it here instead and enable the filter text
if (component.getKeyListeners().length == 0) {
component.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent arg0) {
if (KeyEvent.getKeyText(arg0.getKeyCode()).equals("Escape")) {
// System.out.println("Escaped!");
context.filterText.setEnabled(true);
context.graphUpdater.wake();
}
}
public void keyReleased(KeyEvent arg0) {
// DO NOTHING!
}
public void keyTyped(KeyEvent arg0) {
// DO NOTHING!
}
});
}
rowIndex = row;
colIndex = column;
originalText = (String) value;
ltName = (String) table.getValueAt(row, LtAndDsTab.LT_NAME_COLUMN);
ltDef = (String) table.getValueAt(row, LtAndDsTab.LT_DEF_COLUMN);
ltConstants = (String) table.getValueAt(row,
LtAndDsTab.LT_CONSTANT_COLUMN);
if (ltConstants == null) {
ltConstants = "";
}
// Configure the component with the specified value
((JTextField) component).setText((String) value);
// Return the configured component
return component;
}
// When editing finishes...
public Object getCellEditorValue() {
// System.out.println(((JTextField) component).getText());
Boolean goToEnd = false;
String newText = ((JTextField) component).getText();
// Did we make any changes?
if (newText.equals(originalText)) {
goToEnd = true;
}
// Check we set the row properly, if not return
// the original text
if ((goToEnd == false) && (rowIndex == -1 || colIndex == -1)) {
newText = originalText;
goToEnd = true;
}
// Did we edit the table name or the definition?
if (goToEnd == false) {
if (colIndex == LtAndDsTab.LT_NAME_COLUMN) {
// To change the name, we will remove the old LT and create a
// new one
try {
Statement remove = context.conn.createStatement();
remove.setQueryTimeout(Dashboard.QUERY_TIMEOUT);
String sql = "call removelt('" + ltName + "')";
remove.execute(sql);
remove.close();
} catch (SQLException e) {
e.printStackTrace();
goToEnd = true;
}
ltName = newText;
} else if (colIndex == LtAndDsTab.LT_DEF_COLUMN) {
ltDef = newText;
} else if (colIndex == LtAndDsTab.LT_CONSTANT_COLUMN) {
ltConstants = newText;
}
}
if (goToEnd == false) {
try {
Statement editDef = context.conn.createStatement();
editDef.setQueryTimeout(Dashboard.QUERY_TIMEOUT);
String sql = "call setlt('" + ltName.toUpperCase() + "','"
+ ltDef + "','" + ltConstants + "')";
editDef.execute(sql);
editDef.close();
} catch (SQLException e) {
System.out.println("WARNING! Caught SQLException");
e.printStackTrace();
}
}
// goToEnd
// System.out.println("Stopped editing");
context.filterText.setEnabled(true);
// Update now, so that graph is up to date
context.graphUpdater.wake();
return newText;
}
}