org.pentaho.platform.dataaccess.datasource.wizard.controllers.WizardConnectionController.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.platform.dataaccess.datasource.wizard.controllers.WizardConnectionController.java

Source

/*
    
 * This program is free software; you can redistribute it and/or modify it under the 
 * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software 
 * Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this 
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html 
 * or from the Free Software Foundation, Inc., 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 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 Lesser General Public License for more details.
 *
 * Copyright 2008 - 2009 Pentaho Corporation.  All rights reserved.
 *
 *
 * Created April 21, 2009
 * @author rmansoor
 */
package org.pentaho.platform.dataaccess.datasource.wizard.controllers;

import java.util.ArrayList;
import java.util.List;

import org.pentaho.database.model.DatabaseConnection;
import org.pentaho.database.model.IDatabaseConnection;
import org.pentaho.database.model.IDatabaseType;
import org.pentaho.database.util.DatabaseTypeHelper;
import org.pentaho.platform.dataaccess.datasource.beans.AutobeanUtilities;
import org.pentaho.platform.dataaccess.datasource.utils.ExceptionParser;
import org.pentaho.platform.dataaccess.datasource.wizard.ConnectionDialogListener;
import org.pentaho.platform.dataaccess.datasource.wizard.models.DatasourceModel;
import org.pentaho.ui.database.event.DatabaseDialogListener;
import org.pentaho.ui.database.event.IConnectionAutoBeanFactory;
import org.pentaho.ui.database.gwt.GwtDatabaseDialog;
import org.pentaho.ui.database.gwt.GwtXulAsyncDatabaseDialectService;
import org.pentaho.ui.xul.XulServiceCallback;
import org.pentaho.ui.xul.components.XulLabel;
import org.pentaho.ui.xul.containers.XulDialog;
import org.pentaho.ui.xul.containers.XulHbox;
import org.pentaho.ui.xul.dom.Document;
import org.pentaho.ui.xul.impl.AbstractXulEventHandler;
import org.pentaho.ui.xul.stereotype.Bindable;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;
import com.google.web.bindery.autobean.shared.AutoBeanUtils;

public class WizardConnectionController extends AbstractXulEventHandler {

    //  private IXulAsyncConnectionService connectionService;

    private List<ConnectionDialogListener> listeners = new ArrayList<ConnectionDialogListener>();

    private DatasourceModel datasourceModel;

    private XulDialog removeConfirmationDialog;

    private XulDialog saveConnectionConfirmationDialog;

    private XulDialog overwriteConnectionConfirmationDialog;

    private XulDialog renameConnectionConfirmationDialog;

    private XulDialog errorDialog;

    private XulDialog errorDetailsDialog;

    private XulDialog successDialog;

    private XulDialog successDetailsDialog;

    private XulLabel errorLabel = null;

    private XulLabel successLabel = null;

    //  GwtXulAsyncDatabaseConnectionService connService = new GwtXulAsyncDatabaseConnectionService();

    GwtXulAsyncDatabaseDialectService dialectService = new GwtXulAsyncDatabaseDialectService();

    GwtDatabaseDialog databaseDialog;

    DatabaseTypeHelper databaseTypeHelper;

    IDatabaseConnection currentConnection;

    ConnectionSetter connectionSetter = new ConnectionSetter();

    protected IConnectionAutoBeanFactory connectionAutoBeanFactory;

    protected String previousConnectionName, existingConnectionName;

    public WizardConnectionController(Document document) {
        this.document = document;
        connectionAutoBeanFactory = GWT.create(IConnectionAutoBeanFactory.class);
        init();
    }

    protected void copyDatabaseConnectionProperties(IDatabaseConnection source, IDatabaseConnection target) {
        target.setId(source.getId());
        target.setAccessType(source.getAccessType());
        target.setDatabaseType(source.getDatabaseType());
        target.setExtraOptions(source.getExtraOptions());
        target.setName(source.getName());
        target.setHostname(source.getHostname());
        target.setDatabaseName(source.getDatabaseName());
        target.setDatabasePort(source.getDatabasePort());
        target.setUsername(source.getUsername());
        target.setPassword(source.getPassword());
        target.setStreamingResults(source.isStreamingResults());
        target.setDataTablespace(source.getDataTablespace());
        target.setIndexTablespace(source.getIndexTablespace());
        target.setSQLServerInstance(source.getSQLServerInstance());
        target.setUsingDoubleDecimalAsSchemaTableSeparator(source.isUsingDoubleDecimalAsSchemaTableSeparator());
        target.setInformixServername(source.getInformixServername());
        //target.addExtraOption(String databaseTypeCode, String option, String value);
        target.setAttributes(source.getAttributes());
        target.setChanged(source.getChanged());
        target.setQuoteAllFields(source.isQuoteAllFields());
        // advanced option (convert to enum with upper, lower, none?)
        target.setForcingIdentifiersToLowerCase(source.isForcingIdentifiersToLowerCase());
        target.setForcingIdentifiersToUpperCase(source.isForcingIdentifiersToUpperCase());
        target.setConnectSql(source.getConnectSql());
        target.setUsingConnectionPool(source.isUsingConnectionPool());
        target.setInitialPoolSize(source.getInitialPoolSize());
        target.setMaximumPoolSize(source.getMaximumPoolSize());
        target.setPartitioned(source.isPartitioned());
        target.setConnectionPoolingProperties(source.getConnectionPoolingProperties());
        target.setPartitioningInformation(source.getPartitioningInformation());
    }

    protected AutoBean<IDatabaseConnection> createIDatabaseConnectionBean(IDatabaseConnection connection) {
        AutoBean<IDatabaseConnection> bean = connectionAutoBeanFactory.iDatabaseConnection();
        IDatabaseConnection connectionBean = bean.as();
        copyDatabaseConnectionProperties(connection, connectionBean);
        return AutoBeanUtils.getAutoBean(connectionBean);
        //return connectionBean;
    }

    @Bindable
    public void init() {

        XulServiceCallback<List<IDatabaseType>> callback = new XulServiceCallback<List<IDatabaseType>>() {
            public void error(String message, Throwable error) {
                error.printStackTrace();
            }

            public void success(List<IDatabaseType> retVal) {
                databaseTypeHelper = new DatabaseTypeHelper(retVal);
            }
        };
        dialectService.getDatabaseTypes(callback);

        saveConnectionConfirmationDialog = (XulDialog) document.getElementById("saveConnectionConfirmationDialog"); //$NON-NLS-1$
        overwriteConnectionConfirmationDialog = (XulDialog) document
                .getElementById("overwriteConnectionConfirmationDialog");
        renameConnectionConfirmationDialog = (XulDialog) document
                .getElementById("renameConnectionConfirmationDialog");
        errorDialog = (XulDialog) document.getElementById("errorDialog"); //$NON-NLS-1$
        errorDetailsDialog = (XulDialog) document.getElementById("errorDetailsDialog"); //$NON-NLS-1$
        errorLabel = (XulLabel) document.getElementById("errorLabel");//$NON-NLS-1$
        successDialog = (XulDialog) document.getElementById("successDialog"); //$NON-NLS-1$
        successDetailsDialog = (XulDialog) document.getElementById("successDetailsDialog"); //$NON-NLS-1$
        successLabel = (XulLabel) document.getElementById("successLabel");//$NON-NLS-1$
        removeConfirmationDialog = (XulDialog) document.getElementById("removeConfirmationDialog"); //$NON-NLS-1$
    }

    @Bindable
    public void openErrorDialog(String title, String message) {
        errorDialog.setTitle(title);
        errorLabel.setValue(message);
        errorDialog.show();
    }

    @Bindable
    public void closeErrorDialog() {
        if (!errorDialog.isHidden()) {
            errorDialog.hide();
        }
    }

    @Bindable
    public void closeSuccessDetailsDialog() {
        if (!successDetailsDialog.isHidden()) {
            successDetailsDialog.hide();
        }
    }

    @Bindable
    public void toggleDetails() {
        XulHbox details = (XulHbox) document.getElementById("details_hider"); //$NON-NLS-1$
        details.setVisible(!details.isVisible());
    }

    @Bindable
    public void openSuccesDialog(String title, String message) {
        successDialog.setTitle(title);
        successLabel.setValue(message);
        successDialog.show();
    }

    @Bindable
    public void closeSuccessDialog() {
        if (!successDialog.isHidden()) {
            successDialog.hide();
        }
    }

    @Bindable
    public void toggleSuccessDetails() {
        XulHbox details = (XulHbox) document.getElementById("success_details_hider"); //$NON-NLS-1$
        details.setVisible(!details.isVisible());
    }

    @Bindable
    public void closeErrorDetailsDialog() {
        if (!errorDetailsDialog.isHidden()) {
            errorDetailsDialog.hide();
        }
    }

    public void setDatasourceModel(DatasourceModel model) {
        this.datasourceModel = model;
    }

    public DatasourceModel getDatasourceModel() {
        return this.datasourceModel;
    }

    public String getName() {
        return "wizardConnectionController";//$NON-NLS-1$
    }

    @Bindable
    public void closeDialog() {
        for (ConnectionDialogListener listener : listeners) {
            listener.onDialogCancel();
        }
    }

    @Bindable
    public void handleDialogAccept() {
        //first, test the connection
        RequestBuilder testConnectionBuilder = new RequestBuilder(RequestBuilder.PUT,
                ConnectionController.getServiceURL("test"));
        testConnectionBuilder.setHeader("Content-Type", "application/json");
        try {
            //AutoBean<IDatabaseConnection> bean = AutoBeanUtils.getAutoBean(currentConnection);
            AutoBean<IDatabaseConnection> bean = createIDatabaseConnectionBean(currentConnection);
            testConnectionBuilder.sendRequest(AutoBeanCodex.encode(bean).getPayload(), new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    saveConnectionConfirmationDialog.show();
                }

                @Override
                public void onResponseReceived(Request request, Response response) {
                    try {
                        if (response.getStatusCode() == Response.SC_OK) {
                            //test is ok, now check if we are renaming
                            renameCheck();
                        } else {
                            //confirm if we should continu saving this invalid connection.
                            saveConnectionConfirmationDialog.show();
                        }
                    } catch (Exception e) {
                        displayErrorMessage(e);
                    }
                }

            });
        } catch (RequestException e) {
            displayErrorMessage(e);
        }
    }

    @Bindable
    public void renameCheck() {
        if (!saveConnectionConfirmationDialog.isHidden())
            closeSaveConnectionConfirmationDialog();

        if (datasourceModel.isEditing() && !previousConnectionName.equals(currentConnection.getName())) {
            showRenameConnectionConfirmationDialog();
        } else {
            overwriteCheck();
        }

    }

    @Bindable
    public void overwriteCheck() {
        if (!saveConnectionConfirmationDialog.isHidden())
            closeSaveConnectionConfirmationDialog();
        if (!renameConnectionConfirmationDialog.isHidden())
            closeRenameConnectionConfirmationDialog();

        if (datasourceModel.isEditing() && previousConnectionName.equals(currentConnection.getName())) {
            //if editing and no name change, proceed.
            updateConnection();
        } else {
            //either new connection, or editing involved a name change.
            RequestBuilder getConnectionBuilder = new RequestBuilder(RequestBuilder.GET, ConnectionController
                    .getServiceURL("get", new String[][] { { "name", currentConnection.getName() } }));
            getConnectionBuilder.setHeader("Content-Type", "application/json");
            try {
                AutoBean<IDatabaseConnection> bean = createIDatabaseConnectionBean(currentConnection);
                getConnectionBuilder.sendRequest(AutoBeanCodex.encode(bean).getPayload(), new RequestCallback() {

                    public void onResponseReceived(Request request, Response response) {
                        switch (response.getStatusCode()) {
                        case Response.SC_OK:
                            showOverwriteConnectionConfirmationDialog();
                            break;
                        case Response.SC_NOT_FOUND:
                            saveConnection();
                            break;
                        default:
                            //TODO: error message
                            saveConnection();
                        }
                    }

                    public void onError(Request request, Throwable exception) {
                        displayErrorMessage(exception);
                    }

                });
            } catch (Exception e) {
                displayErrorMessage(e);
            }
        }
    }

    @Bindable
    public void updateConnection() {
        RequestBuilder updateConnectionBuilder = new RequestBuilder(RequestBuilder.POST,
                ConnectionController.getServiceURL("update"));
        updateConnectionBuilder.setHeader("Content-Type", "application/json");
        try {
            //AutoBean<IDatabaseConnection> bean = AutoBeanUtils.getAutoBean(currentConnection); 
            AutoBean<IDatabaseConnection> bean = createIDatabaseConnectionBean(currentConnection);
            updateConnectionBuilder.sendRequest(AutoBeanCodex.encode(bean).getPayload(), new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    displayErrorMessage(exception);
                }

                @Override
                public void onResponseReceived(Request request, Response response) {
                    try {
                        if (response.getStatusCode() == Response.SC_OK) {
                            datasourceModel.getGuiStateModel().updateConnection(existingConnectionName,
                                    currentConnection);
                            datasourceModel.setSelectedRelationalConnection(currentConnection);
                        } else {
                            openErrorDialog(MessageHandler.getString("ERROR"), MessageHandler//$NON-NLS-1$
                                    .getString("ConnectionController.ERROR_0004_UNABLE_TO_UPDATE_CONNECTION"));//$NON-NLS-1$
                        }
                    } catch (Exception e) {
                        displayErrorMessage(e);
                    }
                }

            });
        } catch (RequestException e) {
            displayErrorMessage(e);
        }
    }

    @Bindable
    public void addConnection() {
        RequestBuilder addConnectionBuilder = new RequestBuilder(RequestBuilder.POST,
                ConnectionController.getServiceURL("add"));
        addConnectionBuilder.setHeader("Content-Type", "application/json");
        try {
            //AutoBean<IDatabaseConnection> bean = AutoBeanUtils.getAutoBean(currentConnection); 
            AutoBean<IDatabaseConnection> bean = createIDatabaseConnectionBean(currentConnection);
            addConnectionBuilder.sendRequest(AutoBeanCodex.encode(bean).getPayload(), new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    displayErrorMessage(exception);
                }

                @Override
                public void onResponseReceived(Request request, Response response) {
                    try {
                        if (response.getStatusCode() == Response.SC_OK) {
                            IDatabaseConnection conn = AutobeanUtilities.connectionBeanToImpl(currentConnection);
                            datasourceModel.getGuiStateModel().addConnection(conn);
                            datasourceModel.setSelectedRelationalConnection(conn);
                        } else {
                            openErrorDialog(MessageHandler.getString("ERROR"), MessageHandler//$NON-NLS-1$
                                    .getString("ConnectionController.ERROR_0001_UNABLE_TO_ADD_CONNECTION"));//$NON-NLS-1$
                        }
                    } catch (Exception e) {
                        displayErrorMessage(e);
                    }
                }

            });
        } catch (RequestException e) {
            displayErrorMessage(e);
        }
    }

    @Bindable
    public void overwriteConnection() {
        if (!saveConnectionConfirmationDialog.isHidden())
            closeSaveConnectionConfirmationDialog();
        if (!renameConnectionConfirmationDialog.isHidden())
            closeRenameConnectionConfirmationDialog();
        if (!overwriteConnectionConfirmationDialog.isHidden())
            overwriteConnectionConfirmationDialog.hide();
        existingConnectionName = currentConnection.getName();
        updateConnection();
    }

    @Bindable
    public void saveConnection() {
        if (!saveConnectionConfirmationDialog.isHidden())
            closeSaveConnectionConfirmationDialog();
        if (!renameConnectionConfirmationDialog.isHidden())
            closeRenameConnectionConfirmationDialog();
        if (!overwriteConnectionConfirmationDialog.isHidden())
            overwriteConnectionConfirmationDialog.hide();

        if (datasourceModel.isEditing())
            updateConnection();
        else
            addConnection();
    }

    @Bindable
    public void testConnection() {
        RequestBuilder testConnectionBuilder = new RequestBuilder(RequestBuilder.PUT,
                ConnectionController.getServiceURL("test"));
        testConnectionBuilder.setHeader("Content-Type", "application/json");
        try {
            //AutoBean<IDatabaseConnection> bean = AutoBeanUtils.getAutoBean(currentConnection);
            AutoBean<IDatabaseConnection> bean = createIDatabaseConnectionBean(currentConnection);
            testConnectionBuilder.sendRequest(AutoBeanCodex.encode(bean).getPayload(), new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    displayErrorMessage(exception);
                }

                @Override
                public void onResponseReceived(Request request, Response response) {
                    Boolean testPassed = new Boolean(response.getText());
                    try {
                        if (testPassed) {
                            openSuccesDialog(MessageHandler.getString("SUCCESS"), MessageHandler//$NON-NLS-1$
                                    .getString("ConnectionController.CONNECTION_TEST_SUCCESS"));//$NON-NLS-1$
                        } else {
                            openErrorDialog(MessageHandler.getString("ERROR"), MessageHandler//$NON-NLS-1$
                                    .getString("ConnectionController.ERROR_0003_CONNECTION_TEST_FAILED"));//$NON-NLS-1$
                        }
                    } catch (Exception e) {
                        displayErrorMessage(e);
                    }
                }

            });
        } catch (RequestException e) {
            displayErrorMessage(e);
        }
    }

    @Bindable
    public void deleteConnection() {
        removeConfirmationDialog.hide();
        RequestBuilder deleteConnectionBuilder = new RequestBuilder(RequestBuilder.DELETE,
                ConnectionController.getServiceURL("deletebyname", new String[][] {
                        { "name", datasourceModel.getSelectedRelationalConnection().getName() } }));
        try {
            deleteConnectionBuilder.sendRequest(null, new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    displayErrorMessage(exception);
                }

                @Override
                public void onResponseReceived(Request request, Response response) {
                    try {
                        if (response.getStatusCode() == Response.SC_OK) {
                            openSuccesDialog(MessageHandler.getString("SUCCESS"), MessageHandler//$NON-NLS-1$
                                    .getString("ConnectionController.CONNECTION_DELETED"));//$NON-NLS-1$
                            datasourceModel.getGuiStateModel()
                                    .deleteConnection(datasourceModel.getSelectedRelationalConnection().getName());
                            List<IDatabaseConnection> connections = datasourceModel.getGuiStateModel()
                                    .getConnections();
                            if (connections != null && connections.size() > 0) {
                                datasourceModel
                                        .setSelectedRelationalConnection(connections.get(connections.size() - 1));
                            } else {
                                datasourceModel.setSelectedRelationalConnection(null);
                            }

                        } else {
                            openErrorDialog(MessageHandler.getString("ERROR"), MessageHandler//$NON-NLS-1$
                                    .getString("ConnectionController.ERROR_0002_UNABLE_TO_DELETE_CONNECTION"));//$NON-NLS-1$
                        }

                    } catch (Exception e) {
                        displayErrorMessage(e);
                    }
                }
            });
        } catch (RequestException e) {
            displayErrorMessage(e);
        }
    }

    public void addConnectionDialogListener(ConnectionDialogListener listener) {
        if (listeners.contains(listener) == false) {
            listeners.add(listener);
        }
    }

    public void removeConnectionDialogListener(ConnectionDialogListener listener) {
        if (listeners.contains(listener)) {
            listeners.remove(listener);
        }
    }

    public void displayErrorMessage(Throwable th) {
        errorDialog.setTitle(
                ExceptionParser.getErrorHeader(th, MessageHandler.getString("DatasourceEditor.USER_ERROR_TITLE")));//$NON-NLS-1$
        errorLabel.setValue(ExceptionParser.getErrorMessage(th,
                MessageHandler.getString("DatasourceEditor.ERROR_0001_UNKNOWN_ERROR_HAS_OCCURED")));//$NON-NLS-1$
        errorDialog.show();
    }

    @Bindable
    public void onDialogAccept(IDatabaseConnection databaseConnection) {
        currentConnection = databaseConnection;
        addConnection();
    }

    @Bindable
    public void onDialogCancel() {
        // do nothing
    }

    @Bindable
    public void onDialogReady() {
        if (datasourceModel.isEditing()) {
            showEditConnectionDialog();
        } else {
            showAddConnectionDialog();
        }
    }

    @Bindable
    public void showAddConnectionDialog() {
        datasourceModel.setEditing(false);
        if (databaseDialog != null) {
            previousConnectionName = null;
            existingConnectionName = previousConnectionName;
            databaseDialog.setDatabaseConnection(null);
            databaseDialog.show();
        } else {
            databaseDialog = new GwtDatabaseDialog(databaseTypeHelper,
                    GWT.getModuleBaseURL() + "dataaccess-databasedialog.xul", connectionSetter); //$NON-NLS-1$
        }
    }

    @Bindable
    public void showEditConnectionDialog() {
        datasourceModel.setEditing(true);
        if (databaseDialog != null) {
            IDatabaseConnection connection = datasourceModel.getSelectedRelationalConnection();
            previousConnectionName = connection.getName();
            existingConnectionName = previousConnectionName;
            DatabaseConnection editConnection = new DatabaseConnection();
            copyDatabaseConnectionProperties(connection, editConnection);
            databaseDialog.setDatabaseConnection(editConnection);
            databaseDialog.show();
        } else {
            databaseDialog = new GwtDatabaseDialog(databaseTypeHelper,
                    GWT.getModuleBaseURL() + "dataaccess-databasedialog.xul", connectionSetter); //$NON-NLS-1$
        }
    }

    @Bindable
    public void showRemoveConnectionDialog() {
        // Display the warning message. 
        // If ok then remove the connection from the list
        removeConfirmationDialog.show();
    }

    @Bindable
    public void closeSaveConnectionConfirmationDialog() {
        saveConnectionConfirmationDialog.hide();
    }

    @Bindable
    public void closeRemoveConfirmationDialog() {
        removeConfirmationDialog.hide();
    }

    public void showRenameConnectionConfirmationDialog() {
        renameConnectionConfirmationDialog.show();
    }

    @Bindable
    public void closeRenameConnectionConfirmationDialog() {
        renameConnectionConfirmationDialog.hide();
    }

    public void showOverwriteConnectionConfirmationDialog() {
        overwriteConnectionConfirmationDialog.show();
    }

    @Bindable
    public void closeOverwriteConnectionConfirmationDialog() {
        overwriteConnectionConfirmationDialog.hide();
    }

    class ConnectionSetter implements DatabaseDialogListener {

        /* (non-Javadoc)
         * @see org.pentaho.ui.database.event.DatabaseDialogListener#onDialogAccept(org.pentaho.database.model.IDatabaseConnection)
         */
        public void onDialogAccept(IDatabaseConnection connection) {
            currentConnection = connection;
            handleDialogAccept();
        }

        /* (non-Javadoc)
         * @see org.pentaho.ui.database.event.DatabaseDialogListener#onDialogCancel()
         */
        public void onDialogCancel() {
            // do nothing
        }

        /* (non-Javadoc)
         * @see org.pentaho.ui.database.event.DatabaseDialogListener#onDialogReady()
         */
        public void onDialogReady() {
            if (datasourceModel.isEditing()) {
                showEditConnectionDialog();
            } else {
                showAddConnectionDialog();
            }
        }

    }
}