org.executequery.gui.editor.QueryEditorResultsPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.executequery.gui.editor.QueryEditorResultsPanel.java

Source

/*
 * QueryEditorResultsPanel.java
 *
 * Copyright (C) 2002-2015 Takis Diakoumis
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

package org.executequery.gui.editor;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableModel;

import org.apache.commons.lang.StringUtils;
import org.executequery.GUIUtilities;
import org.executequery.UserPreferencesManager;
import org.executequery.databasemediators.QueryTypes;
import org.executequery.gui.LoggingOutputPanel;
import org.executequery.gui.resultset.RecordDataItem;
import org.executequery.gui.resultset.ResultSetTable;
import org.executequery.gui.resultset.ResultSetTableModel;
import org.executequery.sql.SqlMessages;
import org.underworldlabs.swing.GUIUtils;
import org.underworldlabs.swing.SimpleCloseTabbedPane;
import org.underworldlabs.swing.plaf.TabRollOverListener;
import org.underworldlabs.swing.plaf.TabRolloverEvent;
import org.underworldlabs.swing.plaf.TabSelectionListener;
import org.underworldlabs.util.MiscUtils;

/**
 * The Query Editor's results panel.
 *
 * @author   Takis Diakoumis
 * @version  $Revision: 1487 $
 * @date     $Date: 2015-08-23 22:21:42 +1000 (Sun, 23 Aug 2015) $
 */
public class QueryEditorResultsPanel extends SimpleCloseTabbedPane
        implements TabRollOverListener, TabSelectionListener, ResultSetTableContainer, ChangeListener {

    private static final String OUTPUT_TAB_TITLE = "Output";

    /** the editor parent */
    private QueryEditor queryEditor;

    /** the text output message pane */
    private LoggingOutputPanel outputTextPane;

    /** the result set tab count */
    private int resultSetTabTitleCounter;

    /** the result tab icon */
    private Icon resultSetTabIcon;

    /** the text output tab icon */
    private Icon outputTabIcon;

    private static final String SUCCESS = " Statement executed successfully";
    private static final String NO_ROWS = "No rows selected";
    private static final String SUCCESSFULL_NO_ROWS = SUCCESS + "\n" + NO_ROWS;
    private static final String ZERO_ROWS = " 0 rows returned";
    private static final String SPACE = " ";
    private static final String ROW_RETURNED = " row returned";
    private static final String ROWS_RETURNED = " rows returned";

    private ResultSetTableColumnResizingManager resultSetTableColumnResizingManager;

    public QueryEditorResultsPanel(QueryEditor queryEditor) {

        this(queryEditor, null);
    }

    public QueryEditorResultsPanel() {

        this(null, null);
    }

    public QueryEditorResultsPanel(QueryEditor queryEditor, ResultSet rs) {

        super(JTabbedPane.BOTTOM, JTabbedPane.SCROLL_TAB_LAYOUT);

        this.queryEditor = queryEditor;

        setTabPopupEnabled(true);

        if (queryEditor != null) {
            addTabRollOverListener(this);
            addTabSelectionListener(this);
        }

        try {

            init();

        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    private void init() {

        outputTextPane = new LoggingOutputPanel();
        outputTextPane.setBorder(null);

        outputTabIcon = GUIUtilities.loadIcon("SystemOutput.png", true);
        resultSetTabIcon = GUIUtilities.loadIcon("FrameIcon16.png", true);

        addTextOutputTab();

        if (queryEditor == null) { // editor calls this also

            setTableProperties();
        }

        resultSetTableColumnResizingManager = new ResultSetTableColumnResizingManager();
        addChangeListener(this);
    }

    private TransposedRowTableModelBuilder transposedRowTableModelBuilder;

    private TransposedRowTableModelBuilder transposedRowTableModelBuilder() {

        if (transposedRowTableModelBuilder == null) {

            transposedRowTableModelBuilder = new DefaultTransposedRowTableModelBuilder();
        }

        return transposedRowTableModelBuilder;
    }

    public void transposeRow(TableModel tableModel, int row) {

        if (!(tableModel instanceof ResultSetTableModel)) {

            throw new IllegalArgumentException("Table model must of type ResultSetTableModel.");
        }

        ResultSetTableModel resultSetTableModel = (ResultSetTableModel) tableModel;
        ResultSetTableModel model = transposedRowTableModelBuilder().transpose(resultSetTableModel, row);

        TransposedRowResultSetPanel resultSetPanel = new TransposedRowResultSetPanel(this, model);
        addResultSetPanel(queryForModel(tableModel), model.getRowCount(), resultSetPanel);
    }

    public void filter(String pattern) {

        ResultSetPanel selectedResultSetPanel = getSelectedResultSetPanel();
        if (selectedResultSetPanel == null || selectedResultSetPanel.getRowCount() == 0) {

            return;
        }

        List<List<RecordDataItem>> list = selectedResultSetPanel.filter(pattern);
        ResultSetPanel resultSetPanel = createResultSetPanel();
        ResultSetTableModel model = new ResultSetTableModel(
                selectedResultSetPanel.getResultSetTableModel().getColumnNames(), list);

        resultSetPanel.setResultSet(model, false);
        addResultSetPanel(selectedResultSetPanel.getResultSetTableModel().getQuery(), model.getRowCount(),
                resultSetPanel, true);
    }

    private String queryForModel(TableModel tableModel) {

        for (int i = 0, n = getTabCount(); i < n; i++) {

            Component c = getTabComponentAt(i);
            if (c instanceof ResultSetPanel) {

                ResultSetPanel panel = (ResultSetPanel) c;
                if (panel.getResultSetTableModel() == tableModel) {

                    return getToolTipTextAt(i);
                }

            }

        }
        return "";
    }

    protected void removePopupComponent(JComponent component) {

        if (queryEditor != null) {

            queryEditor.removePopupComponent(component);
        }
    }

    protected void addPopupComponent(JComponent component) {

        if (queryEditor != null) {

            queryEditor.addPopupComponent(component);
        }
    }

    public void cleanup() {
        try {
            destroyTable();
        } finally {
            queryEditor = null;
        }
    }

    private void addTextOutputTab() {

        if (indexOfTab(OUTPUT_TAB_TITLE) == -1) {

            insertTab(OUTPUT_TAB_TITLE, outputTabIcon, outputTextPane, "Database output", 0);
        }

    }

    /**
     * Sets the user defined (preferences) table properties.
     */
    public void setTableProperties() {

        Component[] tabs = getComponents();
        for (int i = 0; i < tabs.length; i++) {

            Component c = tabs[i];
            if (c instanceof ResultSetPanel) {

                ResultSetPanel panel = (ResultSetPanel) c;
                panel.setTableProperties();
            }

        }

    }

    public int getResultSetTabCount() {

        int count = 0;
        Component[] components = getComponents();
        for (Component component : components) {

            if (component instanceof ResultSetPanel) {

                count++;
            }

        }

        return count;
    }

    public void removeAll() {

        super.removeAll();
        setVisible(true);
    }

    public void remove(int index) {

        super.remove(index);
        setVisible(true);
    }

    public boolean hasOutputPane() {

        return getResultSetTabCount() == (getTabCount() - 1);
    }

    /**
     * Invoked when the target of the listener has changed its state.
     *
     * @param e - the event object
     */
    public void stateChanged(ChangeEvent e) {

        Component selectedComponent = getSelectedComponent();
        if (selectedComponent instanceof ResultSetPanel) {

            int rowCount = ((ResultSetPanel) selectedComponent).getRowCount();
            resetEditorRowCount(rowCount);
        }

        if (hasNoTabs()) {

            queryEditor.allResultTabsClosed();
        }

    }

    /**
     * Indicates whether the current model displayed has
     * retained the ResultSetMetaData.
     *
     * @return true | false
     */
    public boolean hasResultSetMetaData() {
        ResultSetPanel panel = getSelectedResultSetPanel();
        if (panel != null) {
            return panel.hasResultSetMetaData();
        }
        return false;
    }

    public void interrupt() {
        Component[] tabs = getComponents();
        for (int i = 0; i < tabs.length; i++) {
            Component c = tabs[i];
            if (c instanceof ResultSetPanel) {
                ResultSetPanel panel = (ResultSetPanel) c;
                panel.interrupt();
            }
        }
    }

    /**
     * Sets the result set object.
     *
     * @param rset - the executed result set
     * @param showRowNumber - whether to return the result set row count
     * @param maxRecords - the maximum records to return
     */
    public int setResultSet(ResultSet rset, boolean showRowNumber, int maxRecords) throws SQLException {

        return setResultSet(rset, showRowNumber, maxRecords, null);
    }

    /**
     * Sets the result set object.
     *
     * @param rset - the executed result set
     * @param showRowNumber - whether to return the result set row count
     * @param maxRecords - the maximum records to return
     * @param query - the executed query of the result set
     */
    public int setResultSet(ResultSet rset, boolean showRowNumber, int maxRecords, String query) {

        ResultSetTableModel model = new ResultSetTableModel(rset, maxRecords, query);

        int rowCount = getResultSetRowCount(model, showRowNumber);
        if (rowCount == 0) {

            return rowCount;
        }

        if (rowCount == 1 && transposeSingleRowResultSets()) {

            transposeRow(model, 0);

        } else {

            ResultSetPanel panel = createResultSetPanel();
            ResultSetTable table = panel.getTable();
            try {

                resultSetTableColumnResizingManager.suspend(table);

                panel.setResultSet(model, showRowNumber);
                resultSetTableColumnResizingManager.setColumnWidthsForTable(table);

            } finally {

                resultSetTableColumnResizingManager.reinstate(table);
            }
            addResultSetPanel(query, rowCount, panel);
        }

        return rowCount;
    }

    private ResultSetPanel createResultSetPanel() {

        ResultSetPanel panel = new ResultSetPanel(this);
        resultSetTableColumnResizingManager.manageResultSetTable(panel.getTable());

        return panel;
    }

    private void resetTabCount() {

        int tabCount = getTabCount();
        if (tabCount == 0 || (tabCount == 1 && hasOutputPane())) {

            resultSetTabTitleCounter = 0;
        }

        resultSetTabTitleCounter++;
    }

    private void addResultSetPanel(String query, int rowCount, final ResultSetPanel panel) {

        addResultSetPanel(query, rowCount, panel, false);
    }

    private void addResultSetPanel(String query, int rowCount, final ResultSetPanel panel, boolean filtered) {

        resetTabCount();

        String title = "Result Set " + resultSetTabTitleCounter + (filtered ? " - Filtered" : "");
        if (useSingleResultSetTabs()) {

            if (getResultSetTabCount() >= 1) {

                closeResultSetTabs();
            }
        }

        addTab(title, resulSetTabIcon(), panel, query);

        if (queryEditor != null) {

            queryEditor.setMetaDataButtonEnabled(true);
            resetEditorRowCount(rowCount);
            queryEditor.setExportButtonEnabled(true);
        }

        GUIUtils.invokeLater(new Runnable() {
            public void run() {
                setSelectedComponent(panel);
            }
        });

    }

    private void closeResultSetTabs() {

        Component[] components = getComponents();
        for (Component component : components) {

            if (component instanceof ResultSetPanel) {

                remove(component);
            }

        }

    }

    private boolean useSingleResultSetTabs() {

        return UserPreferencesManager.isResultSetTabSingle();
    }

    private boolean transposeSingleRowResultSets() {

        return UserPreferencesManager.isTransposingSingleRowResultSets();
    }

    private Icon resulSetTabIcon() {

        return resultSetTabIcon;
    }

    /**
     * Sets the returned rows status text using the specified row count.
     *
     * @param rowCount - the result set row count
     */
    private void resetEditorRowCount(int rowCount) {

        if (queryEditor != null) {

            if (rowCount > 1) {

                queryEditor.setLeftStatusText(SPACE + rowCount + ROWS_RETURNED);

            } else if (rowCount == 1) {

                queryEditor.setLeftStatusText(SPACE + rowCount + ROW_RETURNED);

            } else {

                queryEditor.setLeftStatusText(ZERO_ROWS);
            }

        }

    }

    private int getResultSetRowCount(ResultSetTableModel model, boolean showRowNumber) {
        int rowCount = model.getRowCount();
        if (rowCount == 0) {
            if (showRowNumber) {
                setOutputMessage(SqlMessages.PLAIN_MESSAGE, SUCCESSFULL_NO_ROWS.trim(), true);
                resetEditorRowCount(rowCount);
                queryEditor.setMetaDataButtonEnabled(false);
            }
        }
        return rowCount;
    }

    public void setResultText(int result, int type) {

        if (hasNoTabs()) {

            addTextOutputTab();
        }

        setSelectedIndex(0);

        String row = " row ";
        if (result > 1 || result == 0) {

            row = " rows ";
        }

        String rText = null;
        switch (type) {
        case QueryTypes.INSERT:
            rText = row + "created.";
            break;
        case QueryTypes.UPDATE:
            rText = row + "updated.";
            break;
        case QueryTypes.DELETE:
            rText = row + "deleted.";
            break;
        case QueryTypes.DROP_TABLE:
            rText = "Table dropped.";
            break;
        case QueryTypes.CREATE_TABLE:
            rText = "Table created.";
            break;
        case QueryTypes.ALTER_TABLE:
            rText = "Table altered.";
            break;
        case QueryTypes.CREATE_SEQUENCE:
            rText = "Sequence created.";
            break;
        case QueryTypes.CREATE_PROCEDURE:
            rText = "Procedure created.";
            break;
        case QueryTypes.CREATE_FUNCTION:
            rText = "Function created.";
            break;
        case QueryTypes.GRANT:
            rText = "Grant succeeded.";
            break;
        case QueryTypes.CREATE_SYNONYM:
            rText = "Synonym created.";
            break;
        case QueryTypes.COMMIT:
            rText = "Commit complete.";
            break;
        case QueryTypes.ROLLBACK:
            rText = "Rollback complete.";
            break;
        case QueryTypes.SELECT_INTO:
            rText = "Statement executed successfully.";
            break;
        case QueryTypes.UNKNOWN:
        case QueryTypes.EXECUTE:
            if (result > -1) {
                rText = result + row + "affected.\nStatement executed successfully.";
            } else {
                rText = "Statement executed successfully.";
            }
            break;
        }

        StringBuilder sb = new StringBuilder();
        if ((result > -1 && type >= QueryTypes.ALL_UPDATES) && type != QueryTypes.UNKNOWN) {

            sb.append(result);
        }

        sb.append(rText);

        setOutputMessage(SqlMessages.PLAIN_MESSAGE, sb.toString(), true);
        queryEditor.setLeftStatusText(SUCCESS);
    }

    private boolean hasNoTabs() {

        return getTabCount() == 0;
    }

    public void setResultBackground(Color colour) {

        outputTextPane.setBackground(colour);

        Component[] tabs = getComponents();
        for (int i = 0; i < tabs.length; i++) {
            Component c = tabs[i];
            if (c instanceof ResultSetPanel) {
                ResultSetPanel panel = (ResultSetPanel) c;
                panel.setResultBackground(colour);
            }
        }
    }

    public void destroyTable() {
        Component[] tabs = getComponents();
        for (int i = 0; i < tabs.length; i++) {
            Component c = tabs[i];
            if (c instanceof ResultSetPanel) {
                ResultSetPanel panel = (ResultSetPanel) c;
                panel.destroyTable();
            }
        }
    }

    private ResultSetPanel getSelectedResultSetPanel() {

        int selectedIndex = getSelectedIndex();
        if (selectedIndex <= 0) {

            return null;
        }

        Component c = getComponentAt(selectedIndex);
        if (c instanceof ResultSetPanel) {

            return (ResultSetPanel) c;
        }

        return null;
    }

    /**
     * Returns whether a result set panel is selected and that
     * that panel has a result set row count > 0.
     *
     * @return true | false
     */
    public boolean isResultSetSelected() {
        ResultSetPanel panel = getSelectedResultSetPanel();
        if (panel != null) {
            return panel.getRowCount() > 0;
        }
        return false;
    }

    public ResultSetTable getResultSetTable() {
        ResultSetPanel panel = getSelectedResultSetPanel();
        if (panel != null) {
            return panel.getTable();
        }
        return null;
    }

    public ResultSetTableModel getResultSetTableModel() {
        ResultSetPanel panel = getSelectedResultSetPanel();
        if (panel != null) {
            return panel.getResultSetTableModel();
        }
        return null;
    }

    public void setWarningMessage(String s) {
        appendOutput(SqlMessages.WARNING_MESSAGE, s);
    }

    public void setPlainMessage(String s) {
        appendOutput(SqlMessages.PLAIN_MESSAGE, s);
    }

    public void setActionMessage(String s) {
        appendOutput(SqlMessages.ACTION_MESSAGE, s);
    }

    public void setErrorMessage(String s) {
        if (hasNoTabs()) {
            addTextOutputTab();
        }

        setSelectedIndex(0);
        if (!MiscUtils.isNull(s)) {
            appendOutput(SqlMessages.ERROR_MESSAGE, s);
        }
        if (queryEditor != null) {
            queryEditor.setExportButtonEnabled(false);
            queryEditor.setMetaDataButtonEnabled(false);
        }
    }

    public void setOutputMessage(int type, String text) {
        setOutputMessage(type, text, true);
    }

    public void setOutputMessage(int type, String text, boolean selectTab) {

        if (hasNoTabs()) {

            addTextOutputTab();
        }

        if (selectTab) {

            setSelectedIndex(0);
        }

        if (StringUtils.isNotBlank(text)) {

            appendOutput(type, text);
        }

        if (queryEditor != null) {

            if (!isResultSetSelected()) {
                queryEditor.setExportButtonEnabled(false);
                queryEditor.setMetaDataButtonEnabled(false);
            }

        }
    }

    protected void appendOutput(int type, String text) {
        outputTextPane.append(type, text);
    }

    public void clearOutputPane() {
        outputTextPane.clear();
    }

    /**
     * Indicates the current execute has completed to
     * clear the temp panel availability cache.
     */
    public void finished() {
    }

    private boolean panelHasResultSetMetaData(ResultSetPanel panel) {
        return panel != null && panel.hasResultSetMetaData();
    }

    /**
     * Sets to display the result set meta data for the
     * currently selected result set tab.
     */
    public void displayResultSetMetaData() {

        ResultSetPanel panel = getSelectedResultSetPanel();
        if (panelHasResultSetMetaData(panel)) {

            int index = getSelectedIndex();
            ResultSetMetaDataPanel metaDataPanel = panel.getResultSetMetaDataPanel();

            // check if the meta data is already displayed
            // at the index next to the result panel
            if (index != getTabCount() - 1) {

                Component c = getComponentAt(index + 1);
                if (c == metaDataPanel) {

                    setSelectedIndex(index + 1);
                    return;
                }
            }

            // otherwise add it
            insertTab(ResultSetMetaDataPanel.TITLE, GUIUtilities.loadIcon("RSMetaData16.png", true), metaDataPanel,
                    getToolTipTextAt(index), index + 1);
            setSelectedIndex(index + 1);
        }
    }

    /**
     * Indicates a query is about to be executed
     */
    public void preExecute() {

        addTextOutputTab();
    }

    /**
     * Moves the caret to the beginning of the specified query.
     *
     * @param query - the query to move the cursor to
     */
    public void caretToQuery(String query) {
        queryEditor.caretToQuery(query);
    }

    /** the query display popup */
    private static QueryTextPopup queryPopup;

    /** last popup rollover index */
    private int lastRolloverIndex = -1;

    /**
     * Returns the result set's query at the specified index.
     *
     * @param index - the result set index
     * @return the query string
     */
    public String getQueryTextAt(int index) {
        return getToolTipTextAt(index);
    }

    private boolean isQueryPopupVisible() {

        return (queryPopup != null && queryPopup.isVisible());
    }

    public void tabSelected(MouseEvent e) {

        if (e.getClickCount() >= 2) {

            queryEditor.toggleResultPane();
        }

    }

    /**
     * Reacts to a tab rollover.
     *
     * @param the associated event
     */
    public void tabRollOver(TabRolloverEvent e) {

        int index = e.getIndex();

        // check if we're over the output panel (index 0)
        if (index == 0 && hasOutputPane()) {

            lastRolloverIndex = index;
            if (isQueryPopupVisible()) {

                queryPopup.dispose();
            }

            return;
        }

        if (isQueryPopupVisible() && lastRolloverIndex == index) {

            return;
        }

        if (index != -1) {
            String query = getToolTipTextAt(index);
            if (!MiscUtils.isNull(query)) {
                if (queryPopup == null) {
                    queryPopup = new QueryTextPopup(this);
                }
                lastRolloverIndex = index;
                queryPopup.showPopup(e.getX(), e.getY(), query, getTitleAt(index), index);
            }
        }
    }

    /**
     * Reacts to a tab rollover finishing.
     *
     * @param the associated event
     */
    public void tabRollOverFinished(TabRolloverEvent e) {
        int index = e.getIndex();
        if (index == -1) {
            lastRolloverIndex = index;
            if (queryPopup != null) {
                queryPopup.dispose();
            }
        }
    }

    /**
     * Reacts to a tab rollover finishing.
     *
     * @param the associated event
     */
    public void tabRollOverCancelled(TabRolloverEvent e) {
        if (queryPopup != null) {
            queryPopup.disposeNow();
        }
    }

    public boolean isTransposeAvailable() {
        return true;
    }

}