com.nextep.designer.sqlclient.ui.connectors.SQLResultConnector.java Source code

Java tutorial

Introduction

Here is the source code for com.nextep.designer.sqlclient.ui.connectors.SQLResultConnector.java

Source

/*******************************************************************************
 * Copyright (c) 2011 neXtep Software and contributors.
 * All rights reserved.
 *
 * This file is part of neXtep designer.
 *
 * NeXtep designer 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.
 *
 * NeXtep designer 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     neXtep Softwares - initial API and implementation
 *******************************************************************************/
package com.nextep.designer.sqlclient.ui.connectors;

import java.sql.Types;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ICellEditorListener;
import org.eclipse.jface.viewers.ICellEditorValidator;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.progress.UIJob;
import com.nextep.datadesigner.gui.impl.FontFactory;
import com.nextep.designer.sqlclient.ui.SQLClientMessages;
import com.nextep.designer.sqlclient.ui.jface.DateCellValidator;
import com.nextep.designer.sqlclient.ui.jface.DateComparator;
import com.nextep.designer.sqlclient.ui.jface.NumberComparator;
import com.nextep.designer.sqlclient.ui.jface.SQLResultContentProvider;
import com.nextep.designer.sqlclient.ui.jface.SQLResultLabelProvider;
import com.nextep.designer.sqlclient.ui.jface.SQLResultViewerComparator;
import com.nextep.designer.sqlclient.ui.jface.SQLRowResultCellModifier;
import com.nextep.designer.sqlclient.ui.jface.StringComparator;
import com.nextep.designer.sqlclient.ui.model.INextepMetadata;
import com.nextep.designer.sqlclient.ui.model.ISQLQuery;
import com.nextep.designer.sqlclient.ui.model.ISQLQueryListener;
import com.nextep.designer.sqlclient.ui.model.ISQLTypeSerializer;
import com.nextep.designer.sqlclient.ui.model.IStatusAccessor;
import com.nextep.designer.sqlclient.ui.model.impl.DateSerializer;
import com.nextep.designer.sqlclient.ui.model.impl.NumberSerializer;
import com.nextep.designer.sqlclient.ui.model.impl.StringSerializer;
import com.nextep.designer.ui.factories.ImageFactory;
import com.nextep.designer.ui.model.base.AbstractUIComponent;

public class SQLResultConnector extends AbstractUIComponent implements ISQLQueryListener {

    private final static Log LOGGER = LogFactory.getLog(SQLResultConnector.class);

    public final static String KEY_CELL_VALIDATOR = "validator"; //$NON-NLS-1$
    public final static String KEY_DESERIALIZER = "deserializer";
    private final static ICellEditorValidator DATE_VALIDATOR = new DateCellValidator();
    private final static ISQLTypeSerializer DATE_DESERIALIZER = new DateSerializer();
    private final static ISQLTypeSerializer NUMBER_DESERIALIZER = new NumberSerializer();
    private final static ISQLTypeSerializer STRING_DESERIALIZER = new StringSerializer();

    private Table sqlView;
    private TableViewer sqlViewer;
    private SQLRowResultCellModifier modifier;
    private int[] colMaxWidth;
    private CLabel timeLabel;
    private CLabel rowsCount;
    private SQLResultViewerComparator comparator;
    private ISQLQuery currentQuery;
    private boolean isEditable = false;

    @Override
    public Control create(Composite parent) {
        Composite resultPane = new Composite(parent, SWT.NONE);
        sqlView = new Table(resultPane, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL | SWT.MULTI);
        // final NextepTableEditor editor = NextepTableEditor.handle(sqlView);
        CoolBar statsBar = new CoolBar(resultPane, SWT.NONE);
        statsBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        // Status item for result count
        final CoolItem rowsItem = new CoolItem(statsBar, SWT.NONE);
        rowsItem.setSize(rowsItem.computeSize(150, 20));
        rowsCount = new CLabel(statsBar, SWT.NONE);
        rowsItem.setControl(rowsCount);
        // Status item for query time and fetch time
        final CoolItem timeItem = new CoolItem(statsBar, SWT.NONE);
        timeLabel = new CLabel(statsBar, SWT.NONE);
        timeItem.setControl(timeLabel);
        timeItem.setSize(timeItem.computeSize(400, 20));

        sqlView.setHeaderVisible(true);
        sqlView.setLinesVisible(true);
        sqlView.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1));
        resultPane.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1));
        GridLayout grid = new GridLayout();
        grid.marginBottom = grid.marginHeight = grid.marginLeft = grid.marginRight = grid.marginTop = grid.marginWidth = 0;
        resultPane.setLayout(grid);

        // Configuring viewer
        sqlViewer = new TableViewer(sqlView);
        sqlViewer.setContentProvider(new SQLResultContentProvider());
        ColumnViewerToolTipSupport.enableFor(sqlViewer, ToolTip.NO_RECREATE);
        SQLResultLabelProvider lblProvider = new SQLResultLabelProvider(this, 0);
        final TableViewerColumn viewerCol = new TableViewerColumn(sqlViewer, SWT.NONE);
        viewerCol.setLabelProvider(lblProvider);
        // final ITableLabelProvider labelProvider = new SQLResultLabelProvider();
        // sqlViewer.setLabelProvider(labelProvider);
        modifier = new SQLRowResultCellModifier(false, sqlViewer, new IStatusAccessor() {

            @Override
            public void setStatus(String status, boolean error) {
                setStatusLabel(status, error);
            }
        });
        // Initializing comparator
        comparator = new SQLResultViewerComparator(sqlViewer);
        sqlViewer.setComparator(comparator);
        return resultPane;
    }

    @Override
    public void queryStarted(ISQLQuery query) {
        disposeQuery();
        currentQuery = query;
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                setStatusLabel("Executing...", false);
                rowsCount.setText("");
                removeTableColumns();
                modifier.setSQLQuery(currentQuery);
            }
        });
    }

    private void disposeQuery() {
        if (currentQuery != null) {
            currentQuery.dispose();
        }
    }

    private void removeTableColumns() {
        for (TableColumn c : sqlView.getColumns()) {
            c.dispose();
        }
        sqlViewer.setItemCount(0);
        sqlViewer.setInput(null);
    }

    @Override
    public void queryFinished(final ISQLQuery query, final long execTime, final long totalTime,
            final int resultCount, final boolean isResultSet) {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                if (isResultSet) {
                    setStatusLabel(MessageFormat.format(SQLClientMessages.getString("sql.executionFetchTime"),
                            execTime, totalTime - execTime), false);
                    rowsCount.setText(
                            MessageFormat.format(SQLClientMessages.getString("sql.fetchedRows"), resultCount));
                } else {
                    setStatusLabel(MessageFormat.format(SQLClientMessages.getString("sql.updateTime"), totalTime),
                            false);

                    if (resultCount > 0) {
                        rowsCount.setText(
                                MessageFormat.format(SQLClientMessages.getString("sql.updatedRows"), resultCount));
                    } else {
                        rowsCount.setText(SQLClientMessages.getString("sql.queryOk"));
                    }
                }
                if (query.hasMoreRows()) {
                    sqlViewer.setItemCount(resultCount + 1);
                } else {
                    query.dispose();
                    query.removeQueryListener(SQLResultConnector.this);
                }
            }
        });
        UIJob j = new UIJob("Auto-sizing columns") {

            @Override
            public IStatus runInUIThread(IProgressMonitor monitor) {
                adjusteColumnSizes();
                return Status.OK_STATUS;
            }
        };
        j.schedule(500);
    }

    public void adjusteColumnSizes() {
        for (TableColumn c : sqlView.getColumns()) {
            c.pack();
        }
    }

    @Override
    public void queryResultMetadataAvailable(final ISQLQuery query, final long executionTime,
            final INextepMetadata md) {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                initializeTable(query, executionTime, md);
            }
        });
    }

    private void initializeTable(ISQLQuery query, long executionTime, INextepMetadata md) {
        colMaxWidth = new int[md.getColumnCount() + 1];
        // Checking columns to display
        int displayedColumns = query.getDisplayedColumnsCount();
        if (displayedColumns <= 0) {
            displayedColumns = md.getColumnCount();
        }
        for (int i = 1; i <= displayedColumns; i++) {
            final String colName = md.getColumnName(i);
            // final int colPrecision = md.getPrecision(index);
            final int colType = md.getColumnType(i);

            final int colIndex = i - 1;
            if (!sqlView.isDisposed()) {
                TableColumn c = new TableColumn(sqlView, SWT.NONE);
                c.setText(colName);
                c.setWidth(colName.length() * 8);
                c.addListener(SWT.Selection, comparator);
                colMaxWidth[colIndex] = c.getWidth();
                SQLResultLabelProvider lblProvider = new SQLResultLabelProvider(this, colIndex);
                final TableViewerColumn viewerCol = new TableViewerColumn(sqlViewer, c);
                viewerCol.setLabelProvider(lblProvider);
                // Registering column comparator
                switch (colType) {
                case Types.BIGINT:
                case Types.BIT:
                case Types.DECIMAL:
                case Types.DOUBLE:
                case Types.FLOAT:
                case Types.INTEGER:
                case Types.NUMERIC:
                case Types.REAL:
                case Types.SMALLINT:
                case Types.TINYINT:
                    c.setData(SQLResultViewerComparator.KEY_COMPARATOR, new NumberComparator());
                    // Setting our deserializer which can produce number from string
                    c.setData(KEY_DESERIALIZER, NUMBER_DESERIALIZER);
                    break;
                case Types.DATE:
                case Types.TIME:
                case Types.TIMESTAMP:
                    // Defines validation so that user will be notified about problems
                    c.setData(KEY_CELL_VALIDATOR, DATE_VALIDATOR);
                    // Setting our deserializer which can produce date from string
                    c.setData(KEY_DESERIALIZER, DATE_DESERIALIZER);
                    c.setData(SQLResultViewerComparator.KEY_COMPARATOR, new DateComparator());
                    break;
                default:
                    c.setData(KEY_DESERIALIZER, STRING_DESERIALIZER);
                    c.setData(SQLResultViewerComparator.KEY_COMPARATOR, new StringComparator());
                }
            }
        }
        registerCellEditors();
        setStatusLabel(MessageFormat.format(SQLClientMessages.getString("sql.executionTime"), executionTime),
                false);
        sqlViewer.setInput(query.getResult());
    }

    @Override
    public void queryFailed(ISQLQuery query, final Exception e) {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                setStatusLabel("Query failed: " + e.getMessage(), true);
            }
        });
    }

    /**
     * Refreshes the status label from this SQL result component.
     * 
     * @param status the message to display
     * @param error whether this is an error message or information
     */
    private void setStatusLabel(String status, boolean error) {
        if (error) {
            timeLabel.setImage(ImageFactory.ICON_ERROR_TINY);
            timeLabel.setForeground(FontFactory.ERROR_COLOR);
        } else {
            timeLabel.setImage(null);
            timeLabel.setForeground(FontFactory.BLACK);
        }
        timeLabel.setText(status == null ? "" : status);
    }

    public ISQLQuery getSQLQuery() {
        return currentQuery;
    }

    public TableViewer getTableViewer() {
        return sqlViewer;
    }

    public void setEditableState(boolean isEditable) {
        modifier.setModifiable(isEditable);
        this.isEditable = isEditable;
    }

    public boolean getEditableState() {
        return isEditable;
    }

    private void registerCellEditors() {
        List<CellEditor> editors = new ArrayList<CellEditor>();
        List<String> colProperties = new ArrayList<String>();
        int i = 0;
        for (TableColumn c : sqlView.getColumns()) {
            final TextCellEditor editor = new TextCellEditor(sqlView);
            final ICellEditorValidator validator = (ICellEditorValidator) c.getData(KEY_CELL_VALIDATOR);
            if (validator != null) {
                editor.setValidator(validator);
                // This editor listener handles the refresh of the status bar on validation of the
                // user edition
                editor.addListener(new ICellEditorListener() {

                    @Override
                    public void editorValueChanged(boolean oldValidState, boolean newValidState) {
                        if (!newValidState) {
                            setStatusLabel(editor.getErrorMessage(), true);
                        } else {
                            setStatusLabel(null, false);
                        }
                    }

                    @Override
                    public void cancelEditor() {
                    }

                    @Override
                    public void applyEditorValue() {

                    }
                });
            }
            editors.add(editor);
            colProperties.add(String.valueOf(i++));
        }
        sqlViewer.setCellEditors(editors.toArray(new CellEditor[editors.size()]));
        sqlViewer.setCellModifier(modifier);
        sqlViewer.setColumnProperties(colProperties.toArray(new String[colProperties.size()]));
    }
}