/* * 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) 2009 Pentaho Corporation.. All rights reserved. */ package org.pentaho.platform.dataaccess.datasource.wizard; import com.google.gwt.user.client.Window; import org.pentaho.agilebi.modeler.ModelerMessagesHolder; import org.pentaho.agilebi.modeler.gwt.GwtModelerMessages; import org.pentaho.gwt.widgets.client.utils.i18n.IResourceBundleLoadCallback; import org.pentaho.gwt.widgets.client.utils.i18n.ResourceBundle; import org.pentaho.metadata.model.Domain; import org.pentaho.platform.dataaccess.datasource.modeler.ModelerDialog; import org.pentaho.platform.dataaccess.datasource.wizard.controllers.ConnectionController; import org.pentaho.platform.dataaccess.datasource.wizard.controllers.FileImportController; import org.pentaho.platform.dataaccess.datasource.wizard.controllers.MainWizardController; import org.pentaho.platform.dataaccess.datasource.wizard.controllers.MessageHandler; import org.pentaho.platform.dataaccess.datasource.wizard.controllers.SummaryDialogController; import org.pentaho.platform.dataaccess.datasource.wizard.controllers.WizardDatasourceController; import org.pentaho.platform.dataaccess.datasource.wizard.models.DatasourceModel; import org.pentaho.platform.dataaccess.datasource.wizard.models.IWizardModel; import org.pentaho.platform.dataaccess.datasource.wizard.models.WizardModel; import org.pentaho.platform.dataaccess.datasource.wizard.service.IXulAsyncConnectionService; import org.pentaho.platform.dataaccess.datasource.wizard.service.IXulAsyncDatasourceService; import org.pentaho.platform.dataaccess.datasource.wizard.service.gwt.ICsvDatasourceServiceAsync; import org.pentaho.platform.dataaccess.datasource.wizard.sources.csv.CsvDatasource; import org.pentaho.platform.dataaccess.datasource.wizard.sources.multitable.MultiTableDatasource; import org.pentaho.platform.dataaccess.datasource.wizard.sources.query.QueryDatasource; import org.pentaho.ui.xul.XulDomContainer; import org.pentaho.ui.xul.XulServiceCallback; import org.pentaho.ui.xul.binding.BindingFactory; import org.pentaho.ui.xul.components.XulButton; import org.pentaho.ui.xul.components.XulFileUpload; import org.pentaho.ui.xul.containers.XulDialog; import org.pentaho.ui.xul.dom.Document; import org.pentaho.ui.xul.gwt.GwtXulRunner; import org.pentaho.ui.xul.gwt.binding.GwtBindingFactory; import org.pentaho.ui.xul.gwt.util.AsyncConstructorListener; import org.pentaho.ui.xul.gwt.util.AsyncXulLoader; import org.pentaho.ui.xul.gwt.util.IXulLoaderCallback; import org.pentaho.ui.xul.stereotype.Bindable; import org.pentaho.ui.xul.util.AbstractXulDialogController; import com.google.gwt.core.client.GWT; @SuppressWarnings("unchecked") public class EmbeddedWizard extends AbstractXulDialogController<Domain> implements IXulLoaderCallback, IResourceBundleLoadCallback, IWizardListener, XulServiceCallback<Domain>{ protected static final String MAIN_WIZARD_PANEL = "main_wizard_panel.xul"; //$NON-NLS-1$ protected static final String MAIN_WIZARD_PANEL_PACKAGE = "main_wizard_panel"; //$NON-NLS-1$ protected static final String WIZARD_DIALOG_ID = "main_wizard_window"; //$NON-NLS-1$ private XulDomContainer mainWizardContainer; private XulDialog dialog; private MainWizardController wizardController; private DatasourceModel datasourceModel = new DatasourceModel(); private WizardDatasourceController datasourceController; //TODO: need to move this to the relational data source private ConnectionController connectionController; private IXulAsyncConnectionService connectionService; private boolean checkHasAccess; private IXulAsyncDatasourceService datasourceService; private DatasourceMessages datasourceMessages; private boolean initialized; private AsyncConstructorListener asyncConstructorListener; private ResourceBundle bundle; private IDatasourceSummary summary; private ModelerDialog modeler; private SummaryDialogController summaryDialogController = new SummaryDialogController(); private IWizardModel wizardModel = new WizardModel(); private ICsvDatasourceServiceAsync csvDatasourceService; private DialogListener<Domain> modelerDialogListener; private boolean reportingOnlyValid = true; /** /** * @param checkHasAccess */ public EmbeddedWizard(boolean checkHasAccess) { this.checkHasAccess = checkHasAccess; } public void bundleLoaded(String bundleName) { try{ ModelerMessagesHolder.setMessages(new GwtModelerMessages(bundle)); } catch(Exception ignored){ // Messages may have been set earlier, ignore. } } public void init(final AsyncConstructorListener<EmbeddedWizard> constructorListener) { asyncConstructorListener = constructorListener; setConnectionService(connectionService); setDatasourceService(datasourceService); wizardModel.addDatasource(new CsvDatasource(datasourceModel, datasourceService, csvDatasourceService)); wizardModel.addDatasource(new QueryDatasource(datasourceService, datasourceModel)); wizardModel.addDatasource(new MultiTableDatasource(datasourceModel)); if (checkHasAccess) { datasourceService.hasPermission(new XulServiceCallback<Boolean>() { public void error(String message, Throwable error) { MessageHandler.getInstance().showErrorDialog(datasourceMessages.getString("DatasourceEditor.ERROR"), //$NON-NLS-1$ datasourceMessages.getString( "DatasourceEditor.ERROR_0002_UNABLE_TO_SHOW_DIALOG", error.getLocalizedMessage())); //$NON-NLS-1$ } public void success(Boolean retVal) { loadXul(); onDialogReady(); } }); } else { loadXul(); } } private void loadXul(){ bundle = new ResourceBundle("", "modeler", true, this); AsyncXulLoader.loadXulFromUrl(MAIN_WIZARD_PANEL, MAIN_WIZARD_PANEL_PACKAGE, EmbeddedWizard.this); } public void onCancel(){ dialog.hide(); datasourceModel.clearModel(); wizardController.setActiveStep(0); } @Override public void onFinish(final IDatasourceSummary summary) { this.summary = summary; if(wizardModel.isEditing()){ MessageHandler.getInstance().closeWaitingDialog(); // biserver-6210 - manage modeler dialog listener separate from the wizard's listener if (modelerDialogListener != null) { modelerDialogListener.onDialogAccept(getDialogResult()); } modelerDialogListener = null; return; } summaryDialogController.showSummaryDialog(summary, new XulServiceCallback<IDatasourceSummary>(){ @Override public void error(String s, Throwable throwable) { MessageHandler.getInstance().showErrorDialog(s, throwable.getMessage()); } @Override public void success(IDatasourceSummary iDatasourceSummary) { if(iDatasourceSummary.isShowModeler()){ showModelEditor(); } else { onDialogAccept(); } MessageHandler.getInstance().closeWaitingDialog(); } }); } private void checkInitialized() { if (!initialized) { throw new IllegalStateException(datasourceMessages .getString("DatasourceEditor.ERROR_0003_CONSTRUCTOR_NOT_INITIALIZED_ERROR")); //$NON-NLS-1$ } } /** * Specified by <code>DialogController</code>. */ public void addDialogListener(org.pentaho.ui.xul.util.DialogController.DialogListener<Domain> listener) { checkInitialized(); super.addDialogListener(listener); listener.onDialogReady(); } /** * Specified by <code>DialogController</code>. */ public void showDialog() { this.modelerDialogListener = null; if (datasourceModel.getGuiStateModel().getConnections() == null || datasourceModel.getGuiStateModel().getConnections().size() <= 0) { checkInitialized(); } wizardModel.setEditing(false); wizardController.setActiveStep(0); wizardModel.reset(); wizardModel.setReportingOnlyValid(this.reportingOnlyValid); /* BISERVER-5153: Work around where XulGwtButton is getting its disabled state and style * confused. The only way to get the train on the track is to flip-flop it. */ XulButton nextButton = (XulButton)mainWizardContainer.getDocumentRoot().getElementById("main_wizard_window_extra2"); //$NON-NLS-1$ nextButton.setDisabled(false); nextButton.setDisabled(true); /* end of work around */ dialog.show(); } public void showEditDialog(final Domain domain, DialogListener<Domain> listener) { checkInitialized(); // biserver-6210 this.modelerDialogListener = listener; String datasourceType = (String) domain.getLogicalModels().get(0).getProperty("DatasourceType"); //previous versions of Data-access would leave this property blank for Query datasources. if(datasourceType == null){ datasourceType = "SQL-DS"; } IWizardDatasource selectedDatasource = null; for(IWizardDatasource datasource: wizardModel.getDatasources()){ if(datasource.getId().equals(datasourceType)){ selectedDatasource = datasource; break; } } if(selectedDatasource == null){ Window.alert("bad one: " + datasourceType); MessageHandler.getInstance().showErrorDialog(MessageHandler.getString("datasourceDialog.ERROR_INCOMPATIBLE_DOMAIN_TITLE"), MessageHandler.getString("datasourceDialog.ERROR_INCOMPATIBLE_DOMAIN")); return; } wizardModel.reset(); wizardModel.setReportingOnlyValid(this.reportingOnlyValid); wizardModel.setSelectedDatasource(selectedDatasource); wizardModel.setEditing(true); wizardController.reset(); selectedDatasource.restoreSavedDatasource(domain, new XulServiceCallback<Void>(){ @Override public void error(String s, Throwable throwable) { MessageHandler.getInstance().showErrorDialog(MessageHandler.getString("datasourceDialog.ERROR_INCOMPATIBLE_DOMAIN"), throwable.getMessage()); } @Override public void success(Void aVoid) { dialog.show(); } }); } /* (non-Javadoc) * @see org.pentaho.ui.xul.gwt.util.IXulLoaderCallback#overlayLoaded() */ public void overlayLoaded() { } /* (non-Javadoc) * @see org.pentaho.ui.xul.gwt.util.IXulLoaderCallback#overlayRemoved() */ public void overlayRemoved() { // TODO Auto-generated method stub } public XulDomContainer getMainWizardContainer() { return mainWizardContainer; } public void setConnectionService(IXulAsyncConnectionService service) { this.connectionService = service; if(connectionController != null){ connectionController.setService(service); connectionController.reloadConnections(); } } public IXulAsyncConnectionService getConnectionService() { return connectionService; } public IXulAsyncDatasourceService getDatasourceService() { return datasourceService; } public MainWizardController getWizardController() { return wizardController; } public void setDatasourceService(IXulAsyncDatasourceService datasourceService) { this.datasourceService = datasourceService; } /* (non-Javadoc) * @see org.pentaho.ui.xul.gwt.util.IXulLoaderCallback#xulLoaded(org.pentaho.ui.xul.gwt.GwtXulRunner) */ public void xulLoaded(GwtXulRunner runner) { mainWizardContainer = runner.getXulDomContainers().get(0); Document rootDocument = mainWizardContainer.getDocumentRoot(); BindingFactory bf = new GwtBindingFactory(rootDocument); ResourceBundle resBundle = (ResourceBundle) mainWizardContainer.getResourceBundles().get(0); datasourceMessages = new GwtDatasourceMessages(); datasourceMessages.setMessageBundle(resBundle); MessageHandler.getInstance().setMessages(datasourceMessages); connectionController = new ConnectionController(); connectionController.setService(connectionService); summaryDialogController.setBindingFactory(bf); mainWizardContainer.addEventHandler(summaryDialogController); wizardController = new MainWizardController(bf, wizardModel, datasourceService); mainWizardContainer.addEventHandler(wizardController); dialog = (XulDialog) rootDocument.getElementById(WIZARD_DIALOG_ID); MessageHandler.getInstance().setWizardDialog(dialog); datasourceController = new WizardDatasourceController(); datasourceController.setBindingFactory(bf); datasourceController.setDatasourceMessages(datasourceMessages); mainWizardContainer.addEventHandler(datasourceController); mainWizardContainer.addEventHandler(MessageHandler.getInstance()); // add the steps .. // physicalStep = new RelationalPhysicalStep(datasourceService, connectionService, datasourceMessages, this); wizardController.addWizardListener(this); // Controller for the File Import functionality FileImportController fileImportController = new FileImportController(datasourceModel, datasourceMessages); mainWizardContainer.addEventHandler(fileImportController); // init other controllers fileImportController.init(); MessageHandler.getInstance().init(); summaryDialogController.init(); // Create the gui try { //new WizardContentPanel(wizardController).addContent(mainWizardContainer); wizardController.init(); initialized = true; } catch (Exception throwable) { throwable.printStackTrace(); } // Remap the upload action in development mode if(GWT.isScript() == false){ XulFileUpload upload = (XulFileUpload) rootDocument.getElementById("fileUpload"); //$NON-NLS-1$ upload.setAction(GWT.getModuleBaseURL()+ "UploadService"); //$NON-NLS-1$ } if (asyncConstructorListener != null) { asyncConstructorListener.asyncConstructorDone(this); } } public DatasourceModel getDatasourceModel() { return datasourceModel; } public void setDatasourceModel(DatasourceModel datasourceModel) { this.datasourceModel = datasourceModel; } /* (non-Javadoc) * @see org.pentaho.ui.xul.util.AbstractXulDialogController#getDialog() */ @Override protected XulDialog getDialog() { return dialog; } /* (non-Javadoc) * @see org.pentaho.ui.xul.util.AbstractXulDialogController#getDialogResult() */ @Override protected Domain getDialogResult() { return summary.getDomain(); } public DatasourceMessages getDatasourceMessages() { return datasourceMessages; } public void setDatasourceMessages(DatasourceMessages datasourceMessages) { this.datasourceMessages = datasourceMessages; } public void setWizardController(MainWizardController wizardController) { this.wizardController = wizardController; } @Bindable public void showModelEditor() { // open up the modeler final DialogListener<Domain> listener = new DialogListener<Domain>(){ public void onDialogCancel() { } public void onDialogAccept(final Domain domain) { EmbeddedWizard.this.onDialogAccept(); } public void onDialogReady() { } }; final Domain domain = summary.getDomain(); modeler = ModelerDialog.getInstance(this, new AsyncConstructorListener<ModelerDialog>(){ public void asyncConstructorDone(ModelerDialog dialog) { dialog.addDialogListener(listener); MessageHandler.getInstance().closeWaitingDialog(); dialog.showDialog(domain); } }); } @Override public void error(String s, Throwable throwable) { //To change body of implemented methods use File | Settings | File Templates. } @Override public void success(Domain domain) { MessageHandler.getInstance().closeWaitingDialog(); if(summary.isShowModeler()){ showModelEditor(); } else { onDialogAccept(); } } /** * Upload path is by necessity relative. as such it will differ where the module is based. * @param path */ public void setUploadPath(String path){ Document rootDocument = mainWizardContainer.getDocumentRoot(); XulFileUpload upload = (XulFileUpload) rootDocument.getElementById("fileUpload"); //$NON-NLS-1$ upload.setAction(path); } public void addDatasource(IWizardDatasource datasource) { wizardModel.addDatasource(datasource); } public void removeDatasourceOfType(Class<? extends IWizardDatasource> datasource){ wizardModel.removeDatasourceByType(datasource); } public IWizardModel getWizardModel() { return wizardModel; } public void setWizardModel(IWizardModel wizardModel) { this.wizardModel = wizardModel; } public ICsvDatasourceServiceAsync getCsvDatasourceService() { return csvDatasourceService; } public void setCsvDatasourceService(ICsvDatasourceServiceAsync csvDatasourceService) { this.csvDatasourceService = csvDatasourceService; } public void setReportingOnlyValid(boolean reportingOnlyValid){ this.reportingOnlyValid = reportingOnlyValid; } }