[power-matchmaker] r2769 committed - Fix for Benjie.

Skip to first unread message

power-ma...@googlecode.com

unread,
Jan 27, 2011, 1:07:20 PM1/27/11
to matchmake...@googlegroups.com
Revision: 2769
Author: ThomasObrien95
Date: Thu Jan 27 10:06:15 2011
Log: Fix for Benjie.
http://code.google.com/p/power-matchmaker/source/detail?r=2769

Modified:
/branches/0.9.7/src/ca/sqlpower/matchmaker/MatchMakerUtils.java
/branches/0.9.7/src/ca/sqlpower/matchmaker/MatchPool.java
/branches/0.9.7/src/ca/sqlpower/matchmaker/Project.java
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MMSUtils.java

/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MatchMakerTreeMouseAndSelectionListener.java

/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MatchResultVisualizer.java

/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/address/AddressPoolLoadingWorker.java

/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/address/AddressValidationPanel.java
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/engine/EngineWorker.java

=======================================
--- /branches/0.9.7/src/ca/sqlpower/matchmaker/MatchMakerUtils.java Thu
Apr 9 19:56:43 2009
+++ /branches/0.9.7/src/ca/sqlpower/matchmaker/MatchMakerUtils.java Thu Jan
27 10:06:15 2011
@@ -22,12 +22,34 @@
import org.apache.log4j.Logger;

import ca.sqlpower.matchmaker.event.MatchMakerListener;
+import ca.sqlpower.sql.JDBCDataSource;
+import ca.sqlpower.sql.JDBCDataSourceType;
+import ca.sqlpower.sqlobject.SQLDatabase;

/**
* A collection of static methods that help with common operations
* in the core MatchMaker API.
*/
public class MatchMakerUtils {
+
+ /**
+ * The name of the table that will group the keys of source table entries
+ * into groups that make up graphs. This will be stored in Derby in
the .mm
+ * directory.
+ */
+ public static final String GRAPH_TABLE_NAME = "validate_graph_table";
+
+ /**
+ * The column name for the graph table that groups source key entries into
+ * a graph.
+ */
+ public static final String GRAPH_ID_COL_NAME = "graph_id";
+
+ /**
+ * The column name prefix for primary key columns in the graph table.
+ * The key columns together define the source entries that make up a
graph.
+ */
+ public static final String PK_KEY_PREFIX = "key_";

private static final Logger logger =
Logger.getLogger(MatchMakerUtils.class);

@@ -92,5 +114,40 @@
unlistenToHierarchy(listener, obj);
}
}
+
+ /**
+ * Creates a Derby database in the .mm directory in the user's home folder
+ * to store the graph table. The database name is based on the project's
+ * name which is sufficient since no two projects can have the same name.
+ *
+ * @param session
+ * Used to retrieve the data source collection and data source
+ * types.
+ * @param project
+ * Used to name the table.
+ */
+ public static SQLDatabase createProjectGraphDataSource(MatchMakerSession
session, Project project) {
+ JDBCDataSource ds = new
JDBCDataSource(session.getContext().getPlDotIni());
+ ds.setName(project.getName() + "'s graph database");
+ ds.setUser("");
+ ds.setPass("");
+ ds.setUrl("jdbc:derby:"+System.getProperty("user.home")+"/.mm/" +
project.getName() + ";create=true");
+
+ // find Derby parent type
+ JDBCDataSourceType derbyType = null;
+ for (JDBCDataSourceType type :
session.getContext().getPlDotIni().getDataSourceTypes()) {
+ if (type.getName() != null && type.getName().startsWith("Derby"))
{
+ derbyType = type;
+ break;
+ }
+ }
+ if (derbyType == null) {
+ throw new RuntimeException("Derby database type is missing in
pl.ini. " +
+ "Please create a database type that starts with Derby.");
+ }
+ ds.setParentType(derbyType);
+ SQLDatabase db = new SQLDatabase(ds);
+ return db;
+ }

}
=======================================
--- /branches/0.9.7/src/ca/sqlpower/matchmaker/MatchPool.java Thu Apr 9
19:56:43 2009
+++ /branches/0.9.7/src/ca/sqlpower/matchmaker/MatchPool.java Thu Jan 27
10:06:15 2011
@@ -20,6 +20,7 @@
package ca.sqlpower.matchmaker;

import java.math.BigDecimal;
+import java.math.BigInteger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -50,8 +51,10 @@
import ca.sqlpower.matchmaker.graph.GraphConsideringOnlyGivenNodes;
import
ca.sqlpower.matchmaker.graph.NonDirectedUserValidatedMatchPoolGraphModel;
import ca.sqlpower.matchmaker.munge.MungeProcess;
+import ca.sqlpower.sql.CachedRowSet;
import ca.sqlpower.sql.SQL;
import ca.sqlpower.sqlobject.SQLColumn;
+import ca.sqlpower.sqlobject.SQLDatabase;
import ca.sqlpower.sqlobject.SQLIndex;
import ca.sqlpower.sqlobject.SQLObjectException;
import ca.sqlpower.sqlobject.SQLTable;
@@ -184,12 +187,81 @@
* @throws SQLObjectException if SQLObjects fail to populate its
children
*/
public void findAll(List<SQLColumn> displayColumns) throws
SQLException, SQLObjectException {
+ findAll(displayColumns, true, null, false, 0);
+ }
+
+ /**
+ * Finds all of the potential matches. Can be limited to a specific range
of
+ * graphs.
+ *
+ * @param displayColumns
+ * The columns to display to the user
+ * @param selectAll
+ * If true the following parameters can be defaulted to nulls,
+ * empty strings or the like as they will not be used.
+ * @param startPoint
+ * The start point of looking for a set of graphs. If we are
+ * going forward in the graphs all of the graphs including and
+ * following this number will be retrieved up to the display
+ * count value. If we are going backwards all of the graphs
+ * including and before this number will be retrieved.
+ * @param forward
+ * If we are going forwards or backwards in the list of graphs.
+ * @param displayCount
+ * The number of graphs to retrieve.
+ * @throws SQLException
+ * @throws SQLObjectException
+ */
+ public void findAll(List<SQLColumn> displayColumns, boolean selectAll,
BigInteger startPoint,
+ boolean forward, int displayCount) throws SQLException,
SQLObjectException {
SQLTable resultTable = project.getResultTable();
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
String lastSQL = null;
try {
+ CachedRowSet pkCRS = null;
+ if (!selectAll) {
+ SQLDatabase db =
MatchMakerUtils.createProjectGraphDataSource(session, project);
+ try {
+ con = db.getConnection();
+ stmt = con.createStatement();
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("SELECT *
FROM ").append(MatchMakerUtils.GRAPH_TABLE_NAME);
+ if (startPoint != null) {
+ sb.append(" WHERE ").append(MatchMakerUtils.GRAPH_ID_COL_NAME);
+ if (forward) {
+ sb.append(" >= ");
+ } else {
+ sb.append(" <= ");
+ }
+ sb.append(startPoint);
+ sb.append(" AND ").append(MatchMakerUtils.GRAPH_ID_COL_NAME);
+ if (forward) {
+ sb.append("
< ").append(startPoint.add(BigInteger.valueOf(displayCount)));
+ } else {
+ sb.append("
> ").append(startPoint.subtract(BigInteger.valueOf(displayCount)));
+ }
+ }
+ sb.append(" ORDER
BY ").append(MatchMakerUtils.GRAPH_ID_COL_NAME);
+ if (forward) {
+ sb.append(" ASC");
+ } else {
+ sb.append(" DESC");
+ }
+ rs = stmt.executeQuery(sb.toString());
+ pkCRS = new CachedRowSet();
+ pkCRS.populate(rs);
+ } finally {
+ if (rs != null) try { rs.close(); } catch
(SQLException ex) { logger.error("Couldn't close result set", ex); }
+ if (stmt != null) try { stmt.close(); } catch
(SQLException ex) { logger.error("Couldn't close statement", ex); }
+ if (con != null) try { con.close(); } catch
(SQLException ex) { logger.error("Couldn't close connection", ex); }
+ rs = null;
+ stmt = null;
+ con = null;
+ }
+ }
con = project.createResultTableConnection();
stmt = con.createStatement();
StringBuilder sql = new StringBuilder();
@@ -246,6 +318,30 @@
sql.append("source2." + col.getColumn().getName());
index++;
}
+ if (!selectAll && pkCRS.size() > 0) {
+ sql.append(" AND (");
+ while (pkCRS.next()) {
+ if (!pkCRS.isFirst()) {
+ sql.append(" OR");
+ }
+ sql.append("(");
+ int i = 0;
+ for (SQLIndex.Column col:
(List<SQLIndex.Column>)sourceTableIndex.getChildren()) {
+ if (i > 0) {
+ sql.append(" AND");
+ }
+ sql.append("DUP_CANDIDATE_1").append(i).append(" = ");
+ if (SQL.isNumeric(col.getColumn().getType()) ||
SQL.isBoolean(col.getColumn().getType())) {
+ sql.append(pkCRS.getObject(i + 2));
+ } else {
+ sql.append("'" + pkCRS.getObject(i + 2) + "'");
+ }
+ i++;
+ }
+ sql.append(")");
+ }
+ sql.append(")");
+ }
lastSQL = sql.toString();
logger.debug("MatchPool's findAll method SQL: \n" + lastSQL);
rs = stmt.executeQuery(lastSQL);
=======================================
--- /branches/0.9.7/src/ca/sqlpower/matchmaker/Project.java Tue Jan 5
08:49:34 2010
+++ /branches/0.9.7/src/ca/sqlpower/matchmaker/Project.java Thu Jan 27
10:06:15 2011
@@ -373,7 +373,7 @@
* @param baseName The base name of the new columns.
* @throws SQLObjectException
*/
- private void addResultTableColumns(SQLTable t, SQLIndex si, String
baseName) throws SQLObjectException {
+ public void addResultTableColumns(SQLTable t, SQLIndex si, String
baseName) throws SQLObjectException {
for (int i = 0; i < si.getChildCount(); i++) {
SQLColumn idxCol = ((Column) si.getChild(i)).getColumn();
logger.debug("addColumn: i="+i+" idx="+si.getChild(i)+"
idxcol="+idxCol);
=======================================
--- /branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MMSUtils.java Mon
Dec 21 08:29:38 2009
+++ /branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MMSUtils.java Thu
Jan 27 10:06:15 2011
@@ -30,10 +30,14 @@
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Callable;

import javax.swing.AbstractAction;
@@ -60,10 +64,23 @@
import ca.sqlpower.architect.ddl.DDLGenerator;
import ca.sqlpower.architect.ddl.DDLStatement;
import ca.sqlpower.architect.ddl.DDLUtils;
+import ca.sqlpower.graph.ConnectedComponentFinder;
+import ca.sqlpower.graph.GraphModel;
+import ca.sqlpower.matchmaker.MatchMakerSession;
+import ca.sqlpower.matchmaker.MatchMakerUtils;
+import ca.sqlpower.matchmaker.MatchPool;
+import ca.sqlpower.matchmaker.PotentialMatchRecord;
import ca.sqlpower.matchmaker.Project;
+import ca.sqlpower.matchmaker.SourceTableRecord;
+import ca.sqlpower.matchmaker.SourceTableRecordDisplayComparator;
+import ca.sqlpower.matchmaker.graph.MatchPoolGraphModel;
import ca.sqlpower.sql.JDBCDataSource;
+import ca.sqlpower.sqlobject.SQLColumn;
+import ca.sqlpower.sqlobject.SQLDatabase;
import ca.sqlpower.sqlobject.SQLIndex;
import ca.sqlpower.sqlobject.SQLObjectException;
+import ca.sqlpower.sqlobject.SQLObjectRuntimeException;
+import ca.sqlpower.sqlobject.SQLTable;
import ca.sqlpower.swingui.DataEntryPanel;
import ca.sqlpower.swingui.DataEntryPanelBuilder;
import ca.sqlpower.swingui.SPSUtils;
@@ -373,4 +390,187 @@
editor.setLocationRelativeTo(null);
editor.setVisible(true);
}
-}
+
+ /**
+ * This method will load the entire pool of matches into memory, create
the
+ * subgraphs based on the potential matches, and store them in a Derby
+ * database on the user's system.
+ *
+ * @param project
+ * @param logger
+ * @param db
+ * @throws SQLException
+ */
+ public static void populateProjectGraphTable(Project project, Logger
logger, SQLDatabase db) throws SQLException {
+ Connection testConnection;
+ // This will store the graphs in a derby table in the .mm folder to
+ // allow the validation screen to load up faster.
+ MatchPool pool = new MatchPool(project);
+ try {
+ pool.findAll(null);
+ } catch (SQLObjectException e) {
+ throw new SQLObjectRuntimeException(e);
+ }
+ GraphModel<SourceTableRecord, PotentialMatchRecord> graphModel =
new MatchPoolGraphModel(pool);
+ ConnectedComponentFinder<SourceTableRecord, PotentialMatchRecord>
ccf =
+ new ConnectedComponentFinder<SourceTableRecord,
PotentialMatchRecord>(new SourceTableRecordDisplayComparator());
+ Set<Set<SourceTableRecord>> components =
ccf.findConnectedComponents(graphModel);
+
+ testConnection = null;
+ PreparedStatement ps = null;
+ try {
+ testConnection = db.getConnection();
+ StringBuffer sb = new StringBuffer();
+ sb.append("INSERT INTO ");
+ sb.append(MatchMakerUtils.GRAPH_TABLE_NAME);
+ sb.append(" (").append(MatchMakerUtils.GRAPH_ID_COL_NAME);
+ for (int i = 0; i <
project.getSourceTableIndex().getChildCount(); i++) {
+ sb.append(",");
+ sb.append(MatchMakerUtils.PK_KEY_PREFIX).append(i);
+ }
+ sb.append(") VALUES (");
+ for (int i = 0; i <
project.getSourceTableIndex().getChildCount(); i++) {
+ sb.append("?,");
+ }
+ sb.append("?)");
+ ps = testConnection.prepareStatement(sb.toString());
+ int i = 0;
+ for (Set<SourceTableRecord> graph : components) {
+ for (SourceTableRecord str : graph) {
+ ps.setObject(1, i);
+ for (int j = 0; j < str.getKeyValues().size(); j++) {
+ ps.setObject(j + 2, str.getKeyValues().get(j));
+ }
+ ps.execute();
+ }
+ i++;
+ }
+ } catch (SQLObjectException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (ps != null) {
+ try {
+ ps.close();
+ } catch (Exception e) {
+ logger.error("Error closing statement to graph db.", e);
+ }
+ }
+ if (testConnection != null) {
+ try {
+ testConnection.close();
+ } catch (Exception e) {
+ logger.error("Error closing connection test.", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true if there is a table that exists to contain the graph
+ * groupings in the .mm directory.
+ */
+ public static boolean checkForGraphTable(MatchMakerSession session,
Project project, Logger logger) {
+ SQLDatabase db = MatchMakerUtils.createProjectGraphDataSource(session,
project);
+ Connection con = null;
+ Statement stmt = null;
+ ResultSet rs = null;
+ try {
+ con = db.getConnection();
+ stmt = con.createStatement();
+ stmt.setFetchSize(1);
+ stmt.setMaxRows(1);
+ try {
+ rs = stmt.executeQuery("SELECT * FROM " +
MatchMakerUtils.GRAPH_TABLE_NAME);
+ return true;
+ } catch (SQLException e) {
+ return false;
+ }
+ // XXX Should use getMetaData().getTables() but it does not return
+ // expected results so hacking a bit due to time.
+// rs = con.getMetaData().getTables(null, null,
MatchMakerUtils.GRAPH_TABLE_NAME, null);
+// if (rs.next()) {
+// return true;
+// }
+ } catch (SQLObjectException e) {
+ throw new SQLObjectRuntimeException(e);
+ } catch (SQLException e) {
+ throw new RuntimeException("There was an error connecting to a local
Derby database. " +
+ "Please check your database type information for the type that
starts with Derby. " +
+ "Also ensure a correct driver exists.", e);
+ } finally {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (SQLException e) {
+ logger.error(e);
+ }
+ }
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException e) {
+ logger.error(e);
+ }
+ }
+ if (con != null) {
+ try {
+ con.close();
+ } catch (SQLException e) {
+ logger.error(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Drops any existing graph table and re-creates it.
+ */
+ public static SQLDatabase setupProjectGraphTable(MatchMakerSession
session, Project project, Logger logger) {
+ SQLDatabase db = MatchMakerUtils.createProjectGraphDataSource(session,
project);
+ Connection testConnection = null;
+ Statement stmt = null;
+ try {
+ testConnection = db.getConnection();
+ stmt = testConnection.createStatement();
+ try {
+ stmt.execute("DROP TABLE " + MatchMakerUtils.GRAPH_TABLE_NAME);
+ } catch (SQLException e) {
+ //squishing as the table may not exist which is fine.
+ }
+ SQLTable graphTable = new SQLTable(db, true);
+ graphTable.setName(MatchMakerUtils.GRAPH_TABLE_NAME);
+ graphTable.addColumn(new SQLColumn(graphTable,
MatchMakerUtils.GRAPH_ID_COL_NAME, Types.BIGINT, 0, 0));
+ project.addResultTableColumns(graphTable,
project.getSourceTableIndex(), MatchMakerUtils.PK_KEY_PREFIX);
+ final DDLGenerator ddlg =
DDLUtils.createDDLGenerator(db.getDataSource());
+ ddlg.addTable(graphTable);
+ List<DDLStatement> ddlStatements = ddlg.getDdlStatements();
+ for (DDLStatement statement : ddlStatements) {
+ stmt.execute(statement.getSQLText());
+ }
+ } catch (SQLObjectException e) {
+ throw new SQLObjectRuntimeException(e);
+ } catch (Exception e) {
+ //TODO Make this a friendly error message not a runtime exception.
+ throw new RuntimeException("There was an error connecting to a
local Derby database. " +
+ "Please check your database type information for the type that
starts with Derby. " +
+ "Also ensure a correct driver exists.", e);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (Exception e) {
+ logger.error("Error closing statement to graph db.", e);
+ }
+ }
+ if (testConnection != null) {
+ try {
+ testConnection.close();
+ } catch (Exception e) {
+ logger.error("Error closing connection test.", e);
+ }
+ }
+ }
+ return db;
+ }
+
+}
=======================================
---
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MatchMakerTreeMouseAndSelectionListener.java
Mon Jan 25 08:17:18 2010
+++
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MatchMakerTreeMouseAndSelectionListener.java
Thu Jan 27 10:06:15 2011
@@ -554,7 +554,7 @@
} else if (node.getActionType() ==
ProjectActionType.VALIDATE_ADDRESSES) {
AddressPool pool = new AddressPool(node.getProject());
ProgressMonitor monitor = new ProgressMonitor(owningFrame, "", "",
0, 100);
- AddressPoolLoadingWorker addressPoolLoadingWorker = new
AddressPoolLoadingWorker(pool, swingSession);
+ AddressPoolLoadingWorker addressPoolLoadingWorker = new
AddressPoolLoadingWorker(pool, swingSession, node.getProject());
ProgressWatcher.watchProgress(monitor, addressPoolLoadingWorker);
Thread workerThread = new Thread(addressPoolLoadingWorker);
workerThread.start();
=======================================
---
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MatchResultVisualizer.java
Tue May 5 13:24:36 2009
+++
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/MatchResultVisualizer.java
Thu Jan 27 10:06:15 2011
@@ -27,9 +27,12 @@
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
+import java.math.BigInteger;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
@@ -45,6 +48,7 @@

import javax.swing.AbstractAction;
import javax.swing.Action;
+import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
@@ -56,6 +60,7 @@
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
+import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.ProgressMonitor;
import javax.swing.SwingUtilities;
@@ -91,6 +96,7 @@
import ca.sqlpower.swingui.SPSwingWorker;
import ca.sqlpower.swingui.SwingWorkerRegistry;

+import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.CellConstraints;
@@ -147,12 +153,18 @@
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE) == JOptionPane.NO_OPTION) return;
try {
+ pool.clearRecords();
+ pool.findAll(displayColumns);
pool.resetPool();
pool.store();
- }catch (SQLException ex) {
+ updateDisplayedMatches(true, startGraph);
+ } catch (SQLException ex) {
MMSUtils.showExceptionDialog(getPanel(), "An exception
occurred while trying to " +
"store changes to the database.", ex);
- }
+ } catch (SQLObjectException ex) {
+ MMSUtils.showExceptionDialog(getPanel(), "An exception
occurred while trying to " +
+ "store changes to the database.", ex);
+ }
graph.repaint();
}
};
@@ -211,13 +223,9 @@

try {
MatchResultVisualizer.this.displayColumns = chosenColumns;
- MatchResultVisualizer.this.getPool().findAll(chosenColumns);
- MatchResultVisualizer.this.getPanel().repaint();
- MatchResultVisualizer.this.doAutoLayout();
- } catch (SQLObjectException ex) {
+ updateDisplayedMatches(true, startGraph);
+ } catch (Exception ex) {
MMSUtils.showExceptionDialog((Component) e.getSource(),
ex.getMessage(), ex);
- } catch (SQLException sqlEx) {
- MMSUtils.showExceptionDialog((Component) e.getSource(),
sqlEx.getMessage(), sqlEx);
} finally {
dialog.dispose();
}
@@ -565,13 +573,20 @@
autoMatcher = new AutoMatcher(pool);
this.mungeProcess = mungeProcess;
this.pool = pool;
+ pool.clearRecords();
+ try {
+ pool.findAll(displayColumns);
+ } catch (SQLException e) {
+ MMSUtils.showExceptionDialog(getPanel(), e.getMessage(), e);
+ } catch (SQLObjectException e) {
+ MMSUtils.showExceptionDialog(getPanel(), e.getMessage(), e);
+ }
}

@Override
public void cleanup() throws Exception {
if (getDoStuffException() != null) {
- pool.clearRecords();
- pool.findAll(displayColumns);
+ updateDisplayedMatches(true, startGraph);
if (!(getDoStuffException() instanceof CancellationException)) {
MMSUtils.showExceptionDialog(getPanel(), "Error during auto-match",
getDoStuffException());
logger.error("Error during auto-match", getDoStuffException());
@@ -709,8 +724,40 @@
*/
private final Preferences matchValidationPrefs;

+ /**
+ * The number of records to display per page.
+ */
+ private int displayCount = 5;
+
+ /**
+ * This button will let users move back a group of graphs. The
+ * {@link #displayCount} defines how many they will move back by.
+ */
+ private final JButton prevButton;
+ /**
+ * This button will let users move forward a group of graphs. The
+ * {@link #displayCount} defines how many they will move forward by.
+ */
+ private final JButton nextButton;
+
+ /**
+ * The graph id that is the first graph in the list of graphs displayed.
Used
+ * to move forwards, back and refresh the currently displayed graphs.
+ */
+ private BigInteger startGraph = BigInteger.valueOf(0);
+
+ /**
+ * The graph id that is the last graph in the list of graphs displayed.
Used
+ * to move forwards, back and refresh the currently displayed graphs.
+ */
+ private BigInteger endGraph = BigInteger.valueOf(4);
+
public MatchResultVisualizer(Project project, MatchMakerSwingSession
session) throws SQLException, SQLObjectException {
super();
+ if (!MMSUtils.checkForGraphTable(session, project, logger)) {
+ SQLDatabase db = MMSUtils.setupProjectGraphTable(session, project,
logger);
+ MMSUtils.populateProjectGraphTable(project, logger, db);
+ }
this.project = project;

if (!project.doesSourceTableExist() |
| !project.verifySourceTableStructure()) {
@@ -736,7 +783,7 @@
JPanel topPanel = new JPanel (topLayout);
PanelBuilder pb = new PanelBuilder(topLayout, topPanel);
CellConstraints cc = new CellConstraints();
- JPanel buttonPanel = new JPanel(new GridLayout(4,1));
+ JPanel buttonPanel = new JPanel(new GridLayout(6,1));
buttonPanel.add(new JButton(chooseDisplayedValueAction));

selectionButton = new MungeProcessSelectionList(project) {
@@ -756,13 +803,10 @@
public void run() {
graph.setSelectedNode(null);
graph.setFocusedNode(null);
- pool.clearRecords();
try {
- pool.findAll(displayColumns);
- } catch (SQLObjectException ex) {
+ updateDisplayedMatches(true, startGraph);
+ } catch (Exception ex) {
MMSUtils.showExceptionDialog(getPanel(), ex.getMessage(), ex);
- } catch (SQLException sqlEx) {
- MMSUtils.showExceptionDialog(getPanel(), sqlEx.getMessage(),
sqlEx);
}
((DefaultGraphLayoutCache)graph.getLayoutCache()).clearNodes();
updateAutoMatchComboBox();
@@ -775,6 +819,44 @@
resetClusterButton = new JButton(resetClusterAction);
resetClusterButton.setEnabled(selectedNode != null);
buttonPanel.add(resetClusterButton);
+ JPanel pageCountSelectorPanel = new JPanel();
+ pageCountSelectorPanel.setLayout(new BoxLayout(pageCountSelectorPanel,
BoxLayout.X_AXIS));
+ pageCountSelectorPanel.add(new JLabel("# addresses per page"));
+ final JTextField displayCountField = new
JTextField(Integer.toString(displayCount));
+ pageCountSelectorPanel.add(displayCountField);
+ displayCountField.addFocusListener(new FocusListener() {
+ public void focusLost(FocusEvent e) {
+ try {
+ displayCount = Integer.parseInt(displayCountField.getText());
+ updateDisplayedMatches(true, startGraph);
+ } catch (NumberFormatException ex) {
+ displayCountField.setText(Integer.toString(displayCount));
+ }
+ }
+ public void focusGained(FocusEvent e) {
+ //do nothing
+ }
+ });
+ buttonPanel.add(pageCountSelectorPanel);
+
+ DefaultFormBuilder pageButtonBuilder = new DefaultFormBuilder(new
FormLayout("pref:grow, 3dlu, pref:grow"));
+ prevButton = new JButton("Prev");
+ prevButton.setAction(new AbstractAction("Prev") {
+ public void actionPerformed(ActionEvent e) {
+ updateDisplayedMatches(false, startGraph.subtract(BigInteger.ONE));
+ nextButton.setEnabled(true);
+ }
+ });
+ prevButton.setEnabled(false);
+ nextButton = new JButton(new AbstractAction("Next") {
+ public void actionPerformed(ActionEvent e) {
+ updateDisplayedMatches(true, endGraph.add(BigInteger.ONE));
+ prevButton.setEnabled(true);
+ }
+ });
+ pageButtonBuilder.append(prevButton);
+ pageButtonBuilder.append(nextButton);
+ buttonPanel.add(pageButtonBuilder.getPanel());

String prefNodePath = "ca/sqlpower/matchmaker/projectSettings/$" +
project.getSession().getDatabase().getDataSource().getName()
+
@@ -834,7 +916,12 @@
}

pool = new MatchPool(project);
- pool.findAll(displayColumns);
+ try {
+ getPool().clearRecords();
+ MatchResultVisualizer.this.getPool().findAll(displayColumns, false,
startGraph, true, displayCount);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
graphModel = new MatchPoolGraphModel(pool);
graph = new GraphViewer<SourceTableRecord,
PotentialMatchRecord>(graphModel);
graph.setNodeRenderer(new SourceTableNodeRenderer());
@@ -881,6 +968,45 @@
JPanel panel = new JPanel(new BorderLayout(12, 12));
panel.add(splitPane, BorderLayout.CENTER);
super.setPanel(panel);
+ updateDisplayedMatches(true, startGraph);
+ }
+
+ /**
+ * Updates the displayed graphs in the validation screen.
+ *
+ * @param forward
+ * Defines if we should move forward (greater) in the displayed
+ * matches or backwards.
+ * @param startPoint
+ * The graph number to start at to display graphs. The graph
+ * represented by this value will be displayed as well.
+ */
+ private void updateDisplayedMatches(boolean forward, BigInteger
startPoint) {
+ graph.setSelectedNode(null);
+ graph.setFocusedNode(null);
+ try {
+ getPool().clearRecords();
+ getPool().findAll(displayColumns, false, startPoint, forward,
displayCount);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ ((DefaultGraphLayoutCache)graph.getLayoutCache()).clearNodes();
+ doAutoLayout();
+ getPanel().repaint();
+
+ if (forward) {
+ startGraph = startPoint;
+ endGraph =
startPoint.add(BigInteger.valueOf(displayCount)).subtract(BigInteger.ONE);
+ } else {
+ startGraph =
startPoint.subtract(BigInteger.valueOf(displayCount)).add(BigInteger.ONE);
+ endGraph = startPoint;
+ }
+ if (startGraph.compareTo(BigInteger.ZERO) == -1) {
+ startGraph = BigInteger.ZERO;
+ }
+ if (startGraph.equals(BigInteger.ZERO)) {
+ prevButton.setEnabled(false);
+ }
}

/**
=======================================
---
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/address/AddressPoolLoadingWorker.java
Tue May 5 13:24:36 2009
+++
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/address/AddressPoolLoadingWorker.java
Thu Jan 27 10:06:15 2011
@@ -21,6 +21,7 @@

import org.apache.log4j.Logger;

+import ca.sqlpower.matchmaker.Project;
import ca.sqlpower.matchmaker.address.AddressPool;
import ca.sqlpower.matchmaker.swingui.MatchMakerSwingSession;
import ca.sqlpower.swingui.SPSwingWorker;
@@ -39,15 +40,18 @@
private MatchMakerSwingSession session;
private AddressPool pool;
private AddressValidationPanel panel;
+
+ private final Project project;

/**
* @param pool The Address Pool that we want to load and display in an
{@link AddressValidationPanel}
* @param session The {@link MatchMakerSwingSession} that will contain
the panel we generate
*/
- public AddressPoolLoadingWorker(AddressPool pool, MatchMakerSwingSession
session) {
+ public AddressPoolLoadingWorker(AddressPool pool, MatchMakerSwingSession
session, Project project) {
super(session);
this.session = session;
this.pool = pool;
+ this.project = project;
}

@Override
@@ -62,8 +66,7 @@
@Override
public void doStuff() throws Exception {
setMessage("Loading invalid addresses");
- pool.load(logger);
- panel = new AddressValidationPanel(session, pool);
+ panel = new AddressValidationPanel(session, pool, project);
}

@Override
=======================================
---
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/address/AddressValidationPanel.java
Thu Apr 9 19:56:43 2009
+++
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/address/AddressValidationPanel.java
Thu Jan 27 10:06:15 2011
@@ -22,24 +22,31 @@
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
import java.io.File;
import java.sql.SQLException;
-import java.util.Collection;
-
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
+import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
+import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.log4j.Logger;

+import ca.sqlpower.matchmaker.Project;
import ca.sqlpower.matchmaker.address.AddressDatabase;
import ca.sqlpower.matchmaker.address.AddressPool;
import ca.sqlpower.matchmaker.address.AddressResult;
@@ -47,6 +54,8 @@
import ca.sqlpower.matchmaker.swingui.NoEditEditorPane;
import ca.sqlpower.sqlobject.SQLObjectException;

+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
import com.sleepycat.je.DatabaseException;

public class AddressValidationPanel extends NoEditEditorPane {
@@ -56,7 +65,7 @@
/**
* A collection of invalid addresses
*/
- private Collection<AddressResult> addressResults;
+ private final List<AddressResult> addressResults = new
ArrayList<AddressResult>();

private AddressDatabase addressDatabase;

@@ -95,29 +104,45 @@

private AddressPool pool;

- public AddressValidationPanel(MatchMakerSwingSession session,
AddressPool pool) {
+ /**
+ * The number of addresses to display at a time.
+ */
+ private int displayCount = 5;
+
+ private final List<Object> startPoint;
+ private final List<Object> endPoint;
+ private final int pkeyChildCount;
+
+ private final JButton prevButton = new JButton(new AbstractAction("Prev")
{
+ public void actionPerformed(ActionEvent e) {
+ updateDisplayedAddresses(false, startPoint);
+ nextButton.setEnabled(true);
+ }
+ });
+
+ private final JButton nextButton = new JButton(new AbstractAction("Next")
{
+ public void actionPerformed(ActionEvent e) {
+ updateDisplayedAddresses(true, endPoint);
+ prevButton.setEnabled(true);
+ }
+ });
+
+ public AddressValidationPanel(MatchMakerSwingSession session,
AddressPool pool, Project project) {
+ try {
+ pkeyChildCount = project.getSourceTableIndex().getChildCount();
+ } catch (SQLObjectException e) {
+ throw new RuntimeException("A database exception occured while
trying to connect to the Berkley DB", e);
+ }
+ startPoint = new ArrayList<Object>(pkeyChildCount);
+ endPoint = new ArrayList<Object>(pkeyChildCount);
try {
addressDatabase = new AddressDatabase(new
File(session.getContext().getAddressCorrectionDataPath()));
} catch (DatabaseException e) {
throw new RuntimeException("A database exception occured while trying
to connect to the Berkley DB", e);
}
this.pool = pool;
- addressResults = pool.getAddressResults(logger);
-
- Object[] addressArray = addressResults.toArray();
- for (int i = 0; i < addressArray.length; i++) {
- AddressResult address =(AddressResult)addressArray[i];
- allResults.add(0, address);
-// if (!address.getOutputAddress().isEmptyAddress()) {
- if (address.isValid()) {
- validResults.add(0, address);
- } else {
- invalidResults.add(0, address);
- }
-// } else {
-// invalidResults.add(0, address);
-// }
- }
+
+ updateDisplayedAddresses(true, startPoint);

needsValidationList = new JList(allResults);

needsValidationList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
@@ -146,12 +171,97 @@

});
validateResultPane.add(displayComboBox);
+ JPanel pageCountSelectorPanel = new JPanel();
+ pageCountSelectorPanel.setLayout(new BoxLayout(pageCountSelectorPanel,
BoxLayout.X_AXIS));
+ pageCountSelectorPanel.add(new JLabel("# addresses per page"));
+ final JTextField displayCountField = new
JTextField(Integer.toString(displayCount));
+ pageCountSelectorPanel.add(displayCountField);
+ displayCountField.addFocusListener(new FocusListener() {
+ public void focusLost(FocusEvent e) {
+ try {
+ displayCount = Integer.parseInt(displayCountField.getText());
+ updateDisplayedAddresses(true, startPoint);
+ } catch (NumberFormatException ex) {
+ displayCountField.setText(Integer.toString(displayCount));
+ }
+ }
+ public void focusGained(FocusEvent e) {
+ //do nothing
+ }
+ });
+ validateResultPane.add(pageCountSelectorPanel);
+
+ DefaultFormBuilder pageButtonBuilder = new DefaultFormBuilder(new
FormLayout("pref:grow, 3dlu, pref:grow"));
+
+ prevButton.setEnabled(false);
+ pageButtonBuilder.append(prevButton);
+ pageButtonBuilder.append(nextButton);
+ validateResultPane.add(pageButtonBuilder.getPanel());
+
+ DefaultFormBuilder pageLabelBuilder = new DefaultFormBuilder(new
FormLayout("fill:pref:grow"));
+ validateResultPane.add(pageLabelBuilder.getPanel());
validateResultPane.add(addressPane);

horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
validateResultPane,
new JLabel("To begin address validation, please select an address from
the list.", JLabel.CENTER));
setPanel(horizontalSplitPane);
}
+
+ /**
+ * Call this method to change the addresses displayed depending on the
+ * {@link #displayCount} and {@link #displayPage}.
+ */
+ private void updateDisplayedAddresses(boolean forward, List<Object>
queryPoint) {
+ addressResults.clear();
+ try {
+ pool.load(logger, false, displayCount, forward, queryPoint);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ addressResults.addAll(pool.getAddressResults(logger));
+
+ allResults.clear();
+ validResults.clear();
+ invalidResults.clear();
+ Object[] addressArray = addressResults.toArray();
+ for (int i = 0; i < addressArray.length; i++) {
+ AddressResult address =(AddressResult)addressArray[i];
+ allResults.add(0, address);
+// if (!address.getOutputAddress().isEmptyAddress()) {
+ if (address.isValid()) {
+ validResults.add(0, address);
+ } else {
+ invalidResults.add(0, address);
+ }
+// } else {
+// invalidResults.add(0, address);
+// }
+ }
+ startPoint.clear();
+ endPoint.clear();
+ if (addressArray.length > 0) {
+ int startArrayPoint;
+ int endArrayPoint;
+ if (forward) {
+ startArrayPoint = 0;
+ endArrayPoint = addressArray.length - 1;
+ } else {
+ startArrayPoint = addressArray.length - 1;
+ endArrayPoint = 0;
+ }
+ for (int i = 0; i < pkeyChildCount; i++) {
+ startPoint.add(((AddressResult)
addressArray[startArrayPoint]).getKeyValues().get(i));
+ endPoint.add(((AddressResult)
addressArray[endArrayPoint]).getKeyValues().get(i));
+ }
+ }
+ if (addressArray.length < displayCount) {
+ if (forward) {
+ nextButton.setEnabled(false);
+ } else {
+ prevButton.setEnabled(false);
+ }
+ }
+ }

@Override
public JSplitPane getPanel() {
=======================================
---
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/engine/EngineWorker.java
Thu Apr 9 19:56:43 2009
+++
/branches/0.9.7/src/ca/sqlpower/matchmaker/swingui/engine/EngineWorker.java
Thu Jan 27 10:06:15 2011
@@ -35,6 +35,7 @@
import ca.sqlpower.matchmaker.SourceTableException;
import ca.sqlpower.matchmaker.swingui.MMSUtils;
import ca.sqlpower.matchmaker.swingui.MatchMakerSwingSession;
+import ca.sqlpower.sqlobject.SQLDatabase;
import ca.sqlpower.sqlobject.SQLObjectException;
import ca.sqlpower.swingui.DocumentAppender;
import ca.sqlpower.swingui.ProgressWatcher;
@@ -44,7 +45,7 @@
* A SPSwingWorker implementation that runs a MatchMakerEngine.
*/
class EngineWorker extends SPSwingWorker {
-
+
/**
* The maximum number of characters that will be displayed in the engine
* output {@link JTextArea}. This is to keep the buffer from getting too
@@ -110,6 +111,8 @@

@Override
public void doStuff() throws EngineSettingException, IOException,
SQLException, SourceTableException, InterruptedException {
+ SQLDatabase db = MMSUtils.setupProjectGraphTable(session, project,
engine.getLogger());
+
project.acquireEngineLock(engine);
try {
appender = new DocumentAppender(engineOutputDoc, true,
LOG_OUTPUT_CHAR_LIMIT);
@@ -119,6 +122,7 @@
project.releaseEngineLock(engine);
}

+ MMSUtils.populateProjectGraphTable(project, engine.getLogger(), db);
}

@Override

Reply all
Reply to author
Forward
0 new messages