diff --git a/src/main/java/com/gyrobian/database/CachedResultSet.java b/src/main/java/com/gyrobian/database/CachedResultSet.java index bf581f3..b3df069 100644 --- a/src/main/java/com/gyrobian/database/CachedResultSet.java +++ b/src/main/java/com/gyrobian/database/CachedResultSet.java @@ -3,7 +3,10 @@ package com.gyrobian.database; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Represents a result set from a SELECT query. @@ -30,6 +33,12 @@ public class CachedResultSet { return this.rows; } + /** + * Constructs a new cached result set from an actual result set. + * @param resultSet The result set to gather data from. + * @return A cached result set that can be used later. + * @throws SQLException If an error occurs while reading the result set. + */ public static CachedResultSet fromResultSet(ResultSet resultSet) throws SQLException { ResultSetMetaData metaData = resultSet.getMetaData(); @@ -51,6 +60,9 @@ public class CachedResultSet { return new CachedResultSet(columnNames, rows); } + /** + * @return This result set, formatted as an ASCII table. + */ public String toFormattedTableString() { int[] optimumColumnWidths = new int[this.columnNames.length]; int totalTableWidth = 0; @@ -84,12 +96,4 @@ public class CachedResultSet { } return sb.toString(); } - - @Override - public String toString() { - return "CachedResultSet{" + - "columnNames=" + Arrays.toString(columnNames) + - ", rows=" + rows + - '}'; - } } diff --git a/src/main/java/com/gyrobian/database/ExecutionLog.java b/src/main/java/com/gyrobian/database/ExecutionLog.java index ad826f7..104dab8 100644 --- a/src/main/java/com/gyrobian/database/ExecutionLog.java +++ b/src/main/java/com/gyrobian/database/ExecutionLog.java @@ -14,6 +14,10 @@ public class ExecutionLog { this.actions = new ArrayList<>(); } + /** + * Records a new action. + * @param action The action to record. + */ public void recordAction(ExecutionAction action) { this.actions.add(action); } @@ -21,4 +25,16 @@ public class ExecutionLog { public List getActions() { return this.actions; } + + /** + * @return True if there's an exception somewhere in this execution log, or false otherwise. + */ + public boolean containsExceptions() { + for (ExecutionAction action : this.getActions()) { + if (action.getException() != null) { + return true; + } + } + return false; + } } diff --git a/src/main/java/com/gyrobian/listener/AssessExecutionsListener.java b/src/main/java/com/gyrobian/listener/AssessExecutionsListener.java new file mode 100644 index 0000000..2c1d3f4 --- /dev/null +++ b/src/main/java/com/gyrobian/listener/AssessExecutionsListener.java @@ -0,0 +1,71 @@ +package com.gyrobian.listener; + +import com.gyrobian.database.ExecutionLog; +import com.gyrobian.view.AssessmentDisplay; +import com.gyrobian.view.ExecutionLogDisplay; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Listener for when pressing a button triggers comparing the executions of the template and testing + * scripts. + */ +public class AssessExecutionsListener implements ActionListener { + private ExecutionLogDisplay templateExecutionLogDisplay; + private ExecutionLogDisplay testingExecutionLogDisplay; + private JButton executeTemplateButton; + private JButton executeTestingButton; + private AssessmentDisplay assessmentDisplay; + + public AssessExecutionsListener( + ExecutionLogDisplay templateExecutionLogDisplay, + ExecutionLogDisplay testingExecutionLogDisplay, + JButton executeTemplateButton, + JButton executeTestingButton, + AssessmentDisplay assessmentDisplay + ) { + this.templateExecutionLogDisplay = templateExecutionLogDisplay; + this.testingExecutionLogDisplay = testingExecutionLogDisplay; + this.executeTemplateButton = executeTemplateButton; + this.executeTestingButton = executeTestingButton; + this.assessmentDisplay = assessmentDisplay; + } + + /** + * Invoked when an action occurs. + * + * @param e the event to be processed + */ + @Override + public void actionPerformed(ActionEvent e) { + ExecutionLog lastTemplateExecution = this.templateExecutionLogDisplay.getLastExecutionLogDisplayed(); + ExecutionLog lastTestingExecution = this.testingExecutionLogDisplay.getLastExecutionLogDisplayed(); + if (lastTemplateExecution == null || lastTestingExecution == null) { + this.assessmentDisplay.appendToDocument("Could not find a recent execution for one of the scripts, re-running...\n", null); + triggerButton(this.executeTemplateButton, this); + triggerButton(this.executeTestingButton, this); + lastTemplateExecution = this.templateExecutionLogDisplay.getLastExecutionLogDisplayed(); + lastTestingExecution = this.testingExecutionLogDisplay.getLastExecutionLogDisplayed(); + + if (lastTemplateExecution == null || lastTestingExecution == null) { + JOptionPane.showMessageDialog(this.assessmentDisplay, "Could not execute both scripts.", "Assessment Error", JOptionPane.WARNING_MESSAGE); + return; + } + } + + + } + + /** + * Triggers all action listeners on a particular button. + * @param button The button to trigger. + * @param source The object that triggered the button. + */ + private static void triggerButton(JButton button, Object source) { + for (ActionListener listener : button.getActionListeners()) { + listener.actionPerformed(new ActionEvent(source, ActionEvent.ACTION_PERFORMED, null)); + } + } +} diff --git a/src/main/java/com/gyrobian/view/AppendableJTextPane.java b/src/main/java/com/gyrobian/view/AppendableJTextPane.java new file mode 100644 index 0000000..08e4f7d --- /dev/null +++ b/src/main/java/com/gyrobian/view/AppendableJTextPane.java @@ -0,0 +1,25 @@ +package com.gyrobian.view; + +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyledDocument; + +/** + * A slightly modified text pane that makes appending text a bit easier. + */ +public class AppendableJTextPane extends JTextPane { + /** + * Appends a styled string to the document. + * @param str The string to append. + * @param style The style to use for the string. + */ + public void appendToDocument(String str, Style style) { + StyledDocument document = this.getStyledDocument(); + try { + document.insertString(document.getLength(), str, style); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/gyrobian/view/AssessmentDisplay.java b/src/main/java/com/gyrobian/view/AssessmentDisplay.java new file mode 100644 index 0000000..91a1e8b --- /dev/null +++ b/src/main/java/com/gyrobian/view/AssessmentDisplay.java @@ -0,0 +1,7 @@ +package com.gyrobian.view; + +/** + * A text pane that's specially suited for displaying the results of assessing two execution logs. + */ +public class AssessmentDisplay extends AppendableJTextPane { +} diff --git a/src/main/java/com/gyrobian/view/ExecutionLogDisplay.java b/src/main/java/com/gyrobian/view/ExecutionLogDisplay.java index 5c4e6e0..7db7b32 100644 --- a/src/main/java/com/gyrobian/view/ExecutionLogDisplay.java +++ b/src/main/java/com/gyrobian/view/ExecutionLogDisplay.java @@ -2,17 +2,14 @@ package com.gyrobian.view; import com.gyrobian.database.*; -import javax.swing.*; -import javax.swing.text.BadLocationException; import javax.swing.text.Style; import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; import java.awt.*; /** * A type of text pane that's built for displaying SQL script execution logs. */ -public class ExecutionLogDisplay extends JTextPane { +public class ExecutionLogDisplay extends AppendableJTextPane { private Style timestampStyle; private Style actionSubsectionLabelStyle; @@ -93,20 +90,6 @@ public class ExecutionLogDisplay extends JTextPane { StyleConstants.setBold(this.exceptionStyle, true); } - /** - * Appends a styled string to the document. - * @param str The string to append. - * @param style The style to use for the string. - */ - private void appendToDocument(String str, Style style) { - StyledDocument document = this.getStyledDocument(); - try { - document.insertString(document.getLength(), str, style); - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - /** * Overrides the behavior of JTextPane so that any time this display's text disappears, we wipe * any memory of a previous execution log. diff --git a/src/main/java/com/gyrobian/view/Window.form b/src/main/java/com/gyrobian/view/Window.form index b1208b0..c2ab56b 100644 --- a/src/main/java/com/gyrobian/view/Window.form +++ b/src/main/java/com/gyrobian/view/Window.form @@ -161,7 +161,7 @@ - + @@ -178,9 +178,8 @@ - + - @@ -441,10 +440,10 @@ - + - + diff --git a/src/main/java/com/gyrobian/view/Window.java b/src/main/java/com/gyrobian/view/Window.java index aaddfcf..bb32482 100644 --- a/src/main/java/com/gyrobian/view/Window.java +++ b/src/main/java/com/gyrobian/view/Window.java @@ -1,5 +1,6 @@ package com.gyrobian.view; +import com.gyrobian.listener.AssessExecutionsListener; import com.gyrobian.listener.ClearTextComponentListener; import com.gyrobian.listener.LoadTextComponentFromFileListener; import com.gyrobian.listener.ScriptExecutionListener; @@ -33,8 +34,7 @@ public class Window extends JFrame { private JPanel testingOutputPanel; private ExecutionLogDisplay templateOutputTextPane; private ExecutionLogDisplay testingOutputTextPane; - private JLabel assessmentPanelTitle; - private JTextPane assessmentTextPane; + private AssessmentDisplay assessmentTextPane; private JPanel mainControlPanel; private JButton executeBothButton; private JButton executeTemplateButton; @@ -44,7 +44,7 @@ public class Window extends JFrame { private JTextField jdbcUrlInput; private JCheckBox enableForeignKeysCheckbox; private JButton clearExecutionOutputsButton; - private JButton compareExecutionsButton; + private JButton assessExecutionsButton; public Window() { super("SQL-Assesser-2"); @@ -83,10 +83,19 @@ public class Window extends JFrame { this.executeTestingButton.addActionListener(executeTestingListener); this.executeBothButton.addActionListener(executeTemplateListener); this.executeBothButton.addActionListener(executeTestingListener); + + this.assessExecutionsButton.addActionListener(new AssessExecutionsListener( + this.templateOutputTextPane, + this.testingOutputTextPane, + this.executeTemplateButton, + this.executeTestingButton, + this.assessmentTextPane + )); } protected void createUIComponents() { this.templateOutputTextPane = new ExecutionLogDisplay(); this.testingOutputTextPane = new ExecutionLogDisplay(); + this.assessmentTextPane = new AssessmentDisplay(); } }