/*
* (C) Copyright IBM Corp. 2009
*
* LICENSE: Eclipse Public License v1.0
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.ibm.gaiandb.draw;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import prefuse.action.assignment.ColorAction;
import prefuse.data.Table;
import prefuse.visual.VisualTable;
/**
* Represents a chart, which in reality is just a visual frontend for a prefuse
* {@link prefuse.data.Table Table} structure. Retrieves data from a prepared
* SQL statement and renders it according to the subclass.
*
* @author Samir Talwar - stalwar@uk.ibm.com
*/
public abstract class Chart extends DatabaseDiagram {
// 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 long serialVersionUID = 6717483758565644169L;
/** Stores the data to be rendered in the chart. */
protected Table data;
/**
* A version of {@link #data} that provides access to graphical and visual
* properties.
*/
protected VisualTable vt;
/**
* The prepared statement that is executed on every update. It may have
* unbound parameters - these are set on each update via arguments to
* {@link #populateTable} and {@link #updateTable}.
*/
protected final PreparedStatement statement;
/**
* The first parameter of {@link #statement} to be set when updating the
* table through {@link #populateTable} or {@link #updateTable}. Any
* parameter before this will be set once in the constructor, and then
* left alone.
*/
protected final int firstStatementVar;
/**
* A set of field names that can be used to compare two rows in {@link data}
* for row equality. Used to decide whether to add a row or update an
* existing one. The keys are set by the concrete class.
*/
protected final Set<String> keys = new HashSet<String>();
/**
* The maximum duration the data in the chart should be left alive.
* Implementation (or lack thereof) is left to the concrete subclass.
*/
protected int maxDuration = 60;
/**
* Retrieves the maximum time the data in the chart should be left alive.
*
* @return The maximum duration of the data in the chart, in seconds.
*/
public int getMaxDuration() { return maxDuration; }
/**
* Sets a new maximum for the lifetime of data in the chart.
*
* @param maxDuration
* The maximum duration of the data in the chart, in seconds.
*/
public void setMaxDuration(int maxDuration) {
if (maxDuration > 0) {
this.maxDuration = maxDuration;
}
}
/**
* Used by prefuse to determine the chart colors.
*/
protected ColorAction colorAction;
/**
* Retrieves the diagram's color action. Color actions are used by prefuse
* to determine the colors used in the chart.
*
* @return A prefuse color action.
*/
public ColorAction getColorAction() {
return colorAction;
}
/**
* Sets the new color action. Color actions are used by prefuse to determine
* the colors used in the chart.
*
* @param colorAction
* The new color action.
*/
public void setColorAction(ColorAction colorAction) {
this.colorAction = colorAction;
}
/**
* Creates a new chart, using the provided <code>PreparedStatement</code> as
* the method of data retrieval. The parameters are added to the prepared
* statement as permanent bound objects. Any unbound parameters are bound on
* each update via {@link #populateTable} or {@link #updateTable} for the
* lifecycle of the update.
*
* @param statement
* The prepared statement to use when retrieving data for
* updates.
* @param params
* The parameters to be permanently bound to the prepared
* statement.
* @throws SQLException
* if binding parameters fails.
*/
public Chart(PreparedStatement statement, Object... params) throws SQLException {
super();
this.statement = statement;
firstStatementVar = TableUtil.bindToPreparedStatement(statement, params);
}
/**
* This method binds the parameters provided to the prepared statement,
* executes it and creates a new data structure from the result. It then
* creates a new visualization and prepares it for rendering.
*
* @param params
* The parameters to be bound to the prepared statement. These
* will not overwrite those bound in the constructor, but will be
* appended to the end of them.
*/
public synchronized void populateTable(Object... params) throws SQLException {
TableUtil.bindToPreparedStatement(statement, params, firstStatementVar);
ResultSet resultSet = statement.executeQuery();
beforeUpdate();
data = TableUtil.addResultSetToTable(resultSet, null, handler, keys);
afterUpdate();
prepareVisualization();
}
/**
* This method binds the parameters provided to the prepared statement,
* executes it and adds the result to its internal data structure. It then
* updates and redraws the visualization.
*
* @param params
* The parameters to be bound to the prepared statement. These
* will not overwrite those bound in the constructor, but will be
* appended to the end of them.
*/
public synchronized void updateTable(Object... params) throws SQLException {
if (null == data) {
populateTable(params);
return;
}
synchronized (data) {
TableUtil.bindToPreparedStatement(statement, params, firstStatementVar);
ResultSet resultSet = statement.executeQuery();
beforeUpdate();
TableUtil.addResultSetToTable(resultSet, data, handler, keys);
afterUpdate();
}
updateVisualization();
}
/**
* An overridable method run before each update.
*
* @throws SQLException
*
* @see #afterUpdate
*/
protected void beforeUpdate() throws SQLException { }
/**
* An overridable method run after each update.
*
* @throws SQLException
*
* @see #beforeUpdate
*/
protected void afterUpdate() throws SQLException { }
public void prepareVisualization() {
if (null == data || 0 == data.getRowCount()) {
preparation = PreparationStages.UNPREPARED;
return;
}
super.prepareVisualization();
}
public void updateVisualization() {
if (null == data || 0 == data.getRowCount()) {
return;
}
super.updateVisualization();
}
}