@Bindable
  // TODO: migrate to CSV datasource
  public void finish() {

    if (finishButton.isDisabled()) {
      return;
    }
    finishButton.setDisabled(true);
    final String datasourceName = this.wizardModel.getDatasourceName();

    // Validating whether the datasource name contains any illegal characters
    if (isDatasourceNameValid(datasourceName)) {
      UIDatasourceServiceManager manager = UIDatasourceServiceManager.getInstance();
      manager.getIds(
          new XulServiceCallback<List<IDatasourceInfo>>() {
            @Override
            public void success(List<IDatasourceInfo> datasourceInfos) {
              finishButton.setDisabled(false);
              boolean isEditing = wizardModel.isEditing();
              List<String> datasourceNames = new ArrayList<String>();
              for (IDatasourceInfo datasourceInfo : datasourceInfos) {
                if (datasourceInfo.getType().equals("Data Source Wizard")
                    || datasourceInfo.getType().equals("Analysis")) {
                  datasourceNames.add(datasourceInfo.getName());
                }
              }
              if (datasourceNames.contains(datasourceName) && !isEditing) {
                showWarningDialog();
              } else {
                setFinished();
              }
            }

            @Override
            public void error(String s, Throwable throwable) {
              finishButton.setDisabled(false);
              throwable.printStackTrace();
              MessageHandler.getInstance().showErrorDialog(throwable.getMessage());
            }
          });
    } else {
      finishButton.setDisabled(false);
      MessageHandler.getInstance()
          .showErrorDialog(
              "Error",
              MessageHandler //$NON-NLS-1$
                  .getString(
                  "DatasourceEditor.ERROR_0005_INVALID_DATASOURCE_NAME",
                  NameUtils.reservedCharListForDisplay(" ")),
              true); //$NON-NLS-1$
    }
  }
  private void setFinished() {

    wizardDialog.hide();
    MessageHandler.getInstance().showWaitingDialog();
    activeDatasource.onFinish(
        new XulServiceCallback<IDatasourceSummary>() {
          @Override
          public void success(IDatasourceSummary iDatasourceSummary) {

            iDatasourceSummary
                .getDomain()
                .getLogicalModels()
                .get(0)
                .setProperty("DatasourceType", new Property<String>(activeDatasource.getId()));
            for (IWizardListener wizardListener : wizardListeners) {
              wizardListener.onFinish(iDatasourceSummary);
            }
          }

          @Override
          public void error(String s, Throwable throwable) {
            throwable.printStackTrace();
            // TODO: improve error messaging
            MessageHandler.getInstance().closeWaitingDialog();
            MessageHandler.getInstance()
                .showErrorDialog(
                    "Error",
                    ExceptionParser //$NON-NLS-1$
                        .getErrorMessage(
                        throwable,
                        MessageHandler.getString(
                            "DatasourceEditor.ERROR_0001_UNKNOWN_ERROR_HAS_OCCURED")),
                    true); //$NON-NLS-1$
          }
        });
  }
  public void init() {

    // We need the SelectDatasourceStep at all times, add it now

    wizardDialog = (XulDialog) document.getElementById("main_wizard_window");

    summaryDialog = (XulDialog) document.getElementById("summaryDialog");

    finishButton = (XulButton) document.getElementById(FINISH_BTN_ELEMENT_ID);

    datasourceName = (XulTextbox) document.getElementById("datasourceName"); // $NON-NLS-1$
    bf.createBinding(datasourceName, "value", wizardModel, "datasourceName");
    wizardModel.addPropertyChangeListener(
        new PropertyChangeListener() {
          @Override
          public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
            if (propertyChangeEvent.getPropertyName().equals("datasourceName")) {
              steps.get(activeStep).setValid(steps.get(activeStep).isValid());
            }
          }
        });

    bf.setBindingType(Binding.Type.ONE_WAY);

    datatypeMenuList = (XulMenuList) document.getElementById("datatypeMenuList");

    Binding datasourceBinding =
        bf.createBinding(wizardModel, "datasources", datatypeMenuList, "elements");
    bf.setBindingType(Binding.Type.ONE_WAY);
    bf.createBinding(datatypeMenuList, "selectedItem", wizardModel, "selectedDatasource");

    bf.setBindingType(Binding.Type.ONE_WAY);
    bf.createBinding(wizardModel, "selectedDatasource", this, "selectedDatasource");
    bf.createBinding(
        this,
        ACTIVE_STEP_PROPERTY_NAME,
        BACK_BTN_ELEMENT_ID,
        DISABLED_PROPERTY_NAME,
        new BackButtonBindingConverter());

    dummyDatasource = ((DummyDatasource) wizardModel.getDatasources().iterator().next());
    activeDatasource = dummyDatasource;
    selectDatasourceStep = dummyDatasource.getSelectDatasourceStep();

    try {
      for (IWizardDatasource datasource : wizardModel.getDatasources()) {
        datasource.init(getXulDomContainer(), wizardModel);
      }
      steps.add(selectDatasourceStep);
      selectDatasourceStep.activating();
      setActiveStep(0);
      datasourceBinding.fireSourceChanged();
      setSelectedDatasource(dummyDatasource);
      datasourceService.getDatasourceIllegalCharacters(
          new XulServiceCallback<String>() {
            @Override
            public void success(String retVal) {}

            @Override
            public void error(String message, Throwable error) {}
          });
    } catch (XulException e) {
      MessageHandler.getInstance().showErrorDialog("Error", e.getMessage());
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      MessageHandler.getInstance().showErrorDialog("Error", e.getMessage());
      e.printStackTrace();
    }
  }