/*!
* 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 (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.dataaccess.datasource.wizard.controllers;
import java.util.ArrayList;
import java.util.List;
import org.pentaho.database.model.IDatabaseConnection;
import org.pentaho.metadata.model.SqlPhysicalModel;
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.models.DatasourceModel;
import org.pentaho.platform.dataaccess.datasource.wizard.service.IXulAsyncDSWDatasourceService;
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 applyQueryConfirmationDialog = null;
private XulDialog previewResultsDialog = null;
private IXulAsyncDSWDatasourceService 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 columnFormatTreeCol = null;\
XulTree sampleDataTree = null;
XulDialog aggregationEditorDialog = null;
XulDialog sampleDataDialog = null;
private String connectionNamesListProp = "connectionNames"; //$NON-NLS-1$
public WizardRelationalDatasourceController() {
}
@Bindable
public void init( final DatasourceModel datasourceModel ) {
this.datasourceModel = datasourceModel;
bf = new GwtBindingFactory( document );
sampleDataTree = (XulTree) document.getElementById( "relationalSampleDataTable" ); //$NON-NLS-1$
aggregationEditorDialog = (XulDialog) document.getElementById( "relationalAggregationEditorDialog" ); //$NON-NLS-1$
sampleDataDialog = (XulDialog) document.getElementById( "relationalSampleDataDialog" ); //$NON-NLS-1$
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$
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$
bf.setBindingType( Binding.Type.ONE_WAY );
bf.createBinding( datasourceModel.getGuiStateModel(), "relationalPreviewValidated", previewButton,
"!disabled" ); //$NON-NLS-1$ //$NON-NLS-2$
List<Binding> bindingsThatNeedInitialized = new ArrayList<Binding>();
BindingConvertor<IDatabaseConnection, Boolean> buttonConvertor =
new BindingConvertor<IDatabaseConnection, Boolean>() {
@Override
public Boolean sourceToTarget( IDatabaseConnection value ) {
return !( value == null );
}
@Override
public IDatabaseConnection targetToSource( Boolean value ) {
return null;
}
};
bf.setBindingType( Binding.Type.ONE_WAY );
final Binding domainBinding = bf.createBinding( datasourceModel.getGuiStateModel(),
"connections", this, "relationalConnections" ); //$NON-NLS-1$ //$NON-NLS-2$
bf.createBinding( this, connectionNamesListProp, connections, "elements" ); //$NON-NLS-1$
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<IDatabaseConnection, Integer>() { //$NON-NLS-1$ //$NON-NLS-2$
@Override
public Integer sourceToTarget( IDatabaseConnection connection ) {
if ( connection != null ) {
return datasourceModel.getGuiStateModel().getConnectionIndex( connection );
}
return -1;
}
@Override
public IDatabaseConnection targetToSource( Integer value ) {
if ( value >= 0 ) {
return datasourceModel.getGuiStateModel().getConnections().get( value );
}
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();
}
}
}
@Bindable
public void setRelationalConnections( List<IDatabaseConnection> connections ) {
List<String> names = new ArrayList<String>();
for ( IDatabaseConnection conn : connections ) {
names.add( conn.getName() );
}
firePropertyChange( connectionNamesListProp, null, names );
}
public String getName() {
return "relationalDatasourceController"; //$NON-NLS-1$
}
@Bindable
public void closeConnectionDialog() {
connectionDialog.hide();
}
@Bindable
public void closeApplyQueryConfirmationDialog() {
applyQueryConfirmationDialog.hide();
}
@Bindable
public void displayPreview() {
showWaitingDialog( MessageHandler.getString( "DatasourceController.GENERATE_PREVIEW_DATA" ), //$NON-NLS-1$
MessageHandler.getString( "DatasourceController.WAIT" ) ); //$NON-NLS-1$
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;
// 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" ); //$NON-NLS-1$
treeCol.setLabel( columns[ i ] );
treeCol.setWidth( 100 );
treeCols.addColumn( treeCol );
} catch ( XulException e ) {
//Do Nothing
}
}
// Create the tree children and setting the data
try {
for ( int i = 0; i < data.size(); i++ ) {
XulTreeRow row = (XulTreeRow) document.createElement( "treerow" ); //$NON-NLS-1$
for ( int j = 0; j < columnCount; j++ ) {
XulTreeCell cell = (XulTreeCell) document.createElement( "treecell" ); //$NON-NLS-1$
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 IXulAsyncDSWDatasourceService getService() {
return service;
}
public void setService( IXulAsyncDSWDatasourceService 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();
}
}
@Bindable
public void showWaitingDialog( String title, String message ) {
MessageHandler.showBusyIndicator( title, message );
}
@Bindable
public void hideWaitingDialog() {
MessageHandler.hideBusyIndicator();
}
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();
}
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;
}
}