/* * 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.metadata.model.SqlPhysicalModel; import org.pentaho.platform.dataaccess.datasource.IConnection; import org.pentaho.platform.dataaccess.datasource.beans.BusinessData; import org.pentaho.platform.dataaccess.datasource.beans.SerializedResultSet; import org.pentaho.platform.dataaccess.datasource.utils.ExceptionParser; import org.pentaho.platform.dataaccess.datasource.wizard.DatasourceMessages; import org.pentaho.platform.dataaccess.datasource.wizard.WaitingDialog; import org.pentaho.platform.dataaccess.datasource.wizard.models.DatasourceModel; import org.pentaho.platform.dataaccess.datasource.wizard.service.IXulAsyncDatasourceService; import org.pentaho.ui.xul.XulComponent; import org.pentaho.ui.xul.XulException; import org.pentaho.ui.xul.XulServiceCallback; import org.pentaho.ui.xul.binding.Binding; import org.pentaho.ui.xul.binding.BindingConvertor; import org.pentaho.ui.xul.binding.BindingFactory; import org.pentaho.ui.xul.components.XulButton; import org.pentaho.ui.xul.components.XulLabel; import org.pentaho.ui.xul.components.XulTextbox; import org.pentaho.ui.xul.components.XulTreeCell; import org.pentaho.ui.xul.components.XulTreeCol; import org.pentaho.ui.xul.containers.XulDialog; import org.pentaho.ui.xul.containers.XulListbox; import org.pentaho.ui.xul.containers.XulTree; import org.pentaho.ui.xul.containers.XulTreeChildren; import org.pentaho.ui.xul.containers.XulTreeCols; import org.pentaho.ui.xul.containers.XulTreeRow; import org.pentaho.ui.xul.gwt.binding.GwtBindingFactory; import org.pentaho.ui.xul.impl.AbstractXulEventHandler; import org.pentaho.ui.xul.stereotype.Bindable; public class WizardRelationalDatasourceController extends AbstractXulEventHandler { public static final int MAX_SAMPLE_DATA_ROWS = 5; public static final int MAX_COL_SIZE = 13; public static final String EMPTY_STRING = ""; //$NON-NLS-1$ public static final String COMMA = ","; //$NON-NLS-1$ private XulDialog connectionDialog; private XulDialog waitingDialog = null; private XulDialog applyQueryConfirmationDialog = null; private XulLabel waitingDialogLabel = null; private XulDialog previewResultsDialog = null; private IXulAsyncDatasourceService service; private DatasourceModel datasourceModel; BindingFactory bf; XulTree previewResultsTable = null; XulTextbox datasourceName = null; XulListbox connections = null; XulTextbox query = null; XulTreeCols previewResultsTreeCols = null; XulTextbox previewLimit = null; XulButton editConnectionButton = null; XulButton removeConnectionButton = null; XulButton editQueryButton = null; XulButton previewButton = null; private XulDialog errorDialog; private XulDialog successDialog; private XulLabel errorLabel = null; private XulLabel successLabel = null; private XulTreeCol columnNameTreeCol = null; private XulTreeCol columnTypeTreeCol = null; //private XulTreeCol columnFormatTreeCol = null;\ XulTree sampleDataTree = null; XulDialog aggregationEditorDialog = null; XulDialog sampleDataDialog = null; public WizardRelationalDatasourceController() { } @Bindable public void init(final DatasourceModel datasourceModel) { this.datasourceModel = datasourceModel; bf = new GwtBindingFactory(document); sampleDataTree = (XulTree) document.getElementById("relationalSampleDataTable"); aggregationEditorDialog = (XulDialog) document.getElementById("relationalAggregationEditorDialog"); sampleDataDialog = (XulDialog) document.getElementById("relationalSampleDataDialog"); errorDialog = (XulDialog) document.getElementById("errorDialog"); //$NON-NLS-1$ errorLabel = (XulLabel) document.getElementById("errorLabel");//$NON-NLS-1$ applyQueryConfirmationDialog = (XulDialog) document.getElementById("applyQueryConfirmationDialog"); //$NON-NLS-1$ errorLabel = (XulLabel) document.getElementById("errorLabel");//$NON-NLS-1$ waitingDialog = (XulDialog) document.getElementById("waitingDialog"); //$NON-NLS-1$ waitingDialogLabel = (XulLabel) document.getElementById("waitingDialogLabel");//$NON-NLS-1$ successDialog = (XulDialog) document.getElementById("successDialog"); //$NON-NLS-1$ successLabel = (XulLabel) document.getElementById("successLabel");//$NON-NLS-1$ datasourceName = (XulTextbox) document.getElementById("datasourceName"); //$NON-NLS-1$ connections = (XulListbox) document.getElementById("connectionList"); //$NON-NLS-1$ query = (XulTextbox) document.getElementById("query"); //$NON-NLS-1$ connectionDialog = (XulDialog) document.getElementById("connectionDialog");//$NON-NLS-1$ previewResultsDialog = (XulDialog) document.getElementById("previewResultsDialog");//$NON-NLS-1$ previewResultsTable = (XulTree) document.getElementById("previewResultsTable"); //$NON-NLS-1$ previewResultsTreeCols = (XulTreeCols) document.getElementById("previewResultsTreeCols"); //$NON-NLS-1$ previewLimit = (XulTextbox) document.getElementById("previewLimit"); //$NON-NLS-1$ editConnectionButton = (XulButton) document.getElementById("editConnection"); //$NON-NLS-1$ removeConnectionButton = (XulButton) document.getElementById("removeConnection"); //$NON-NLS-1$ editQueryButton = (XulButton) document.getElementById("editQuery"); //$NON-NLS-1$ previewButton = (XulButton) document.getElementById("preview"); //$NON-NLS-1$ columnNameTreeCol = (XulTreeCol) document.getElementById("relationalColumnNameTreeCol"); //$NON-NLS-1$ columnTypeTreeCol = (XulTreeCol) document.getElementById("relationalColumnTypeTreeCol"); //$NON-NLS-1$ bf.setBindingType(Binding.Type.ONE_WAY); bf.createBinding(datasourceModel.getGuiStateModel(), "relationalPreviewValidated", previewButton, "!disabled");//$NON-NLS-1$ //$NON-NLS-2$ BindingConvertor<String, Boolean> widgetBindingConvertor = new BindingConvertor<String, Boolean>() { @Override public Boolean sourceToTarget(String value) { return !((value == null) || value.length() <= 0); } @Override public String targetToSource(Boolean value) { return null; } }; List<Binding> bindingsThatNeedInitialized = new ArrayList<Binding>(); BindingConvertor<IConnection, Boolean> buttonConvertor = new BindingConvertor<IConnection, Boolean>() { @Override public Boolean sourceToTarget(IConnection value) { return !(value == null); } @Override public IConnection targetToSource(Boolean value) { return null; } }; bf.setBindingType(Binding.Type.ONE_WAY); final Binding domainBinding = bf.createBinding(datasourceModel.getGuiStateModel(), "connections", connections, "elements"); //$NON-NLS-1$ //$NON-NLS-2$ bf.createBinding(datasourceModel, "selectedRelationalConnection", editConnectionButton, "!disabled", buttonConvertor); //$NON-NLS-1$ //$NON-NLS-2$ bf.createBinding(datasourceModel, "selectedRelationalConnection", removeConnectionButton, "!disabled", buttonConvertor); //$NON-NLS-1$ //$NON-NLS-2$ bf.setBindingType(Binding.Type.BI_DIRECTIONAL); bf.createBinding(datasourceModel, "selectedRelationalConnection", connections, "selectedIndex", new BindingConvertor<IConnection, Integer>() { //$NON-NLS-1$ //$NON-NLS-2$ @Override public Integer sourceToTarget(IConnection connection) { if (connection != null) { return datasourceModel.getGuiStateModel().getConnectionIndex(connection); } else { return -1; } } @Override public IConnection targetToSource(Integer value) { if (value >= 0) { return datasourceModel.getGuiStateModel().getConnections().get(value); } else { return null; } } }); bf.setBindingType(Binding.Type.BI_DIRECTIONAL); bf.createBinding(datasourceModel.getGuiStateModel(), "previewLimit", previewLimit, "value"); //$NON-NLS-1$ //$NON-NLS-2$ bf.createBinding(datasourceModel, "query", query, "value"); //$NON-NLS-1$ //$NON-NLS-2$ try { // Fires the population of the model listbox. This cascades down to the categories and columns. In essence, this // call initializes the entire UI. domainBinding.fireSourceChanged(); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } for(Binding b : bindingsThatNeedInitialized){ try { b.fireSourceChanged(); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } } public String getName() { return "relationalDatasourceController"; } @Bindable public void closeConnectionDialog() { connectionDialog.hide(); } @Bindable public void closeApplyQueryConfirmationDialog() { applyQueryConfirmationDialog.hide(); } @Bindable public void displayPreview() { showWaitingDialog(MessageHandler.getString("DatasourceController.GENERATE_PREVIEW_DATA"), MessageHandler .getString("DatasourceController.WAIT")); service.doPreview(datasourceModel.getSelectedRelationalConnection().getName(), datasourceModel .getQuery(), datasourceModel.getGuiStateModel().getPreviewLimit(), new XulServiceCallback<SerializedResultSet>() { public void error(String message, Throwable error) { hideWaitingDialog(); displayErrorMessage(error); } public void success(SerializedResultSet rs) { try { List<List<String>> data = rs.getData(); String[] columns = rs.getColumns(); int columnCount = columns.length; // Remove any existing children List<XulComponent> previewResultsList = previewResultsTable.getChildNodes(); // Show the dialog. We do this here so browsers such as IE can render // column sizes and provide column resizing previewResultsDialog.show(); previewResultsTable.suppressLayout(true); XulTreeChildren treeChildren = previewResultsTable.getRootChildren(); if (treeChildren != null) { treeChildren.removeAll(); } // Remove all the existing columns previewResultsTable.getColumns().getChildNodes().clear(); // Recreate the colums XulTreeCols treeCols = previewResultsTable.getColumns(); // Setting column data for (int i = 0; i < columnCount; i++) { try { XulTreeCol treeCol = (XulTreeCol) document.createElement("treecol"); treeCol.setLabel(columns[i]); treeCol.setWidth(100); treeCols.addColumn(treeCol); } catch (XulException e) { } } // Create the tree children and setting the data try { for (int i = 0; i < data.size(); i++) { XulTreeRow row = (XulTreeRow) document.createElement("treerow"); for (int j = 0; j < columnCount; j++) { XulTreeCell cell = (XulTreeCell) document.createElement("treecell"); cell.setLabel(getCellData(data, i, j)); row.addCell(cell); } previewResultsTable.addTreeRow(row); } previewResultsTable.suppressLayout(false); previewResultsTable.update(); hideWaitingDialog(); } catch (XulException e) { // TODO: add logging hideWaitingDialog(); System.out.println(e.getMessage()); e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); hideWaitingDialog(); displayErrorMessage(e); } } }); } @Bindable public void closePreviewResultsDialog() { previewResultsDialog.hide(); } public IXulAsyncDatasourceService getService() { return service; } public void setService(IXulAsyncDatasourceService service) { this.service = service; } @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 openSuccesDialog(String title, String message) { successDialog.setTitle(title); successLabel.setValue(message); successDialog.show(); } @Bindable public void closeSuccessDialog() { if (!successDialog.isHidden()) { successDialog.hide(); } } /* public void showWaitingDialog(String title, String message) { getWaitingDialog().setTitle(title); getWaitingDialog().setMessage(message); getWaitingDialog().show(); } public void hideWaitingDialog() { getWaitingDialog().hide(); } */ @Bindable public void showWaitingDialog(String title, String message) { waitingDialog.setTitle(title); waitingDialogLabel.setValue(message); waitingDialog.show(); } @Bindable public void hideWaitingDialog() { waitingDialog.hide(); } public void displayErrorMessage(Throwable th) { errorDialog.setTitle(ExceptionParser.getErrorHeader(th, MessageHandler.getString("DatasourceEditor.USER_ERROR_TITLE"))); errorLabel.setValue(ExceptionParser.getErrorMessage(th, MessageHandler.getString("DatasourceEditor.ERROR_0001_UNKNOWN_ERROR_HAS_OCCURED"))); errorDialog.show(); } public boolean supportsBusinessData(BusinessData businessData) { return (businessData.getDomain().getPhysicalModels().get(0) instanceof SqlPhysicalModel); } private String getCellData(List<List<String>> data, int rowNumber, int columnNumber) { String returnValue = null; int rowCount = 0; for (List<String> row : data) { if(rowCount == rowNumber) { returnValue = row.get(columnNumber); } rowCount++; } return returnValue; } public boolean finishing() { // metaStep.updateDomain(datasourceModel.getRelationalModel() // .getSelectedConnection().getName(), null, this.query.getValue()); return true; } }