public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
    meta = (SapInputMeta) smi;
    data = (SapInputData) sdi;

    if (super.init(smi, sdi)) {
      // Verify some basic things first...
      //
      boolean passed = true;
      if (meta.getFunction() == null) {
        logError(BaseMessages.getString(PKG, "SapInput.Exception.FunctionIsNeeded"));
        passed = false;
      }

      if (meta.getDatabaseMeta() == null) {
        logError(BaseMessages.getString(PKG, "SapInput.Exception.DatabaseConnectionsIsNeeded"));
        passed = false;
      }
      if (!passed) return false;

      try {
        data.sapConnection = SAPConnectionFactory.create();
        data.sapConnection.open(meta.getDatabaseMeta());
        return true;
      } catch (SAPException e) {
        logError("An error occurred while connecting to SAP ERP, processing will be stopped:", e);
        setErrors(1);
        stopAll();
      }
    }

    return false;
  }
  /** Copy information from the meta-data input to the dialog fields. */
  public void getData() {
    logDebug(BaseMessages.getString(PKG, "SapInputDialog.Log.GettingKeyInfo"));

    // The database connection name...
    //
    if (input.getDatabaseMeta() != null) {
      wConnection.setText(input.getDatabaseMeta().getName());
    } else if (transMeta.nrDatabases() == 1) {
      wConnection.setText(transMeta.getDatabase(0).getName());
    }

    // The name of the function to use
    //
    function = input.getFunction();
    if (input.getFunction() != null) {
      wFunction.setText(Const.NVL(input.getFunction().getName(), ""));
    }

    // The parameters...
    //
    for (int i = 0; i < input.getParameters().size(); i++) {
      SapParameter parameter = input.getParameters().get(i);
      TableItem item = wInput.table.getItem(i);
      int colnr = 1;
      item.setText(colnr++, Const.NVL(parameter.getFieldName(), ""));
      item.setText(colnr++, parameter.getSapType().getDescription());
      item.setText(colnr++, Const.NVL(parameter.getTableName(), ""));
      item.setText(colnr++, Const.NVL(parameter.getParameterName(), ""));
      item.setText(colnr++, ValueMeta.getTypeDesc(parameter.getTargetType()));
    }
    wInput.setRowNums();
    wInput.optWidth(true);

    // The parameters...
    //
    for (int i = 0; i < input.getOutputFields().size(); i++) {
      SapOutputField outputField = input.getOutputFields().get(i);
      TableItem item = wOutput.table.getItem(i);
      int colnr = 1;
      item.setText(colnr++, Const.NVL(outputField.getSapFieldName(), ""));
      item.setText(colnr++, outputField.getSapType().getDescription());
      item.setText(colnr++, Const.NVL(outputField.getTableName(), ""));
      item.setText(colnr++, Const.NVL(outputField.getNewName(), ""));
      item.setText(colnr++, ValueMeta.getTypeDesc(outputField.getTargetType()));
    }
    wOutput.setRowNums();
    wOutput.optWidth(true);
  }
  public String open() {
    Shell parent = getParent();
    Display display = parent.getDisplay();

    shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN);
    props.setLook(shell);
    setShellImage(shell, input);

    if (!SAPLibraryTester.isJCoLibAvailable()) {
      int style = SWT.ICON_ERROR;
      MessageBox messageBox = new MessageBox(shell, style);
      messageBox.setMessage(BaseMessages.getString(PKG, "SapInputDialog.JCoLibNotFound"));
      messageBox.open();
      // dispose();
      // return stepname;
    }

    if (!SAPLibraryTester.isJCoImplAvailable()) {
      int style = SWT.ICON_ERROR;
      MessageBox messageBox = new MessageBox(shell, style);
      messageBox.setMessage(BaseMessages.getString(PKG, "SapInputDialog.JCoImplNotFound"));
      messageBox.open();
      // dispose();
      // return stepname;
    }

    ModifyListener lsMod =
        new ModifyListener() {
          public void modifyText(ModifyEvent e) {
            input.setChanged();
          }
        };

    ModifyListener lsConnectionMod =
        new ModifyListener() {
          public void modifyText(ModifyEvent e) {
            input.setChanged();
          }
        };
    backupChanged = input.hasChanged();

    FormLayout formLayout = new FormLayout();
    formLayout.marginWidth = Const.FORM_MARGIN;
    formLayout.marginHeight = Const.FORM_MARGIN;

    shell.setLayout(formLayout);
    shell.setText(BaseMessages.getString(PKG, "SapInputDialog.shell.Title"));

    int middle = props.getMiddlePct();
    int margin = Const.MARGIN;

    // Stepname line
    wlStepname = new Label(shell, SWT.RIGHT);
    wlStepname.setText(BaseMessages.getString(PKG, "SapInputDialog.Stepname.Label"));
    props.setLook(wlStepname);
    fdlStepname = new FormData();
    fdlStepname.left = new FormAttachment(0, 0);
    fdlStepname.right = new FormAttachment(middle, -margin);
    fdlStepname.top = new FormAttachment(0, margin);
    wlStepname.setLayoutData(fdlStepname);
    wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
    wStepname.setText(stepname);
    props.setLook(wStepname);
    wStepname.addModifyListener(lsMod);
    fdStepname = new FormData();
    fdStepname.left = new FormAttachment(middle, 0);
    fdStepname.top = new FormAttachment(0, margin);
    fdStepname.right = new FormAttachment(100, 0);
    wStepname.setLayoutData(fdStepname);
    Control lastControl = wStepname;

    // Connection line
    //
    wConnection = addConnectionLine(shell, lastControl, middle, margin);
    List<String> items = new ArrayList<String>();
    for (DatabaseMeta dbMeta : transMeta.getDatabases()) {
      if (dbMeta.getDatabaseInterface() instanceof SAPR3DatabaseMeta) {
        items.add(dbMeta.getName());
      }
    }
    wConnection.setItems(items.toArray(new String[items.size()]));
    if (input.getDatabaseMeta() == null && transMeta.nrDatabases() == 1) {
      wConnection.select(0);
    }
    wConnection.addModifyListener(lsConnectionMod);
    lastControl = wConnection;

    // Function
    //
    wlFunction = new Label(shell, SWT.RIGHT);
    wlFunction.setText(BaseMessages.getString(PKG, "SapInputDialog.Function.Label"));
    props.setLook(wlFunction);
    FormData fdlFunction = new FormData();
    fdlFunction.left = new FormAttachment(0, 0);
    fdlFunction.right = new FormAttachment(middle, -margin);
    fdlFunction.top = new FormAttachment(lastControl, margin);
    wlFunction.setLayoutData(fdlFunction);
    wbFunction = new Button(shell, SWT.PUSH);
    props.setLook(wbFunction);

    wbFunction.setText(BaseMessages.getString(PKG, "SapInputDialog.FindFunctionButton.Label"));
    FormData fdbFunction = new FormData();
    fdbFunction.right = new FormAttachment(100, 0);
    fdbFunction.top = new FormAttachment(lastControl, margin);
    wbFunction.setLayoutData(fdbFunction);
    wbFunction.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            getFunction();
          }
        });

    wFunction = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
    props.setLook(wFunction);
    wFunction.addModifyListener(
        new ModifyListener() {
          public void modifyText(ModifyEvent e) {
            function = new SAPFunction(((Text) e.widget).getText());
            input.setChanged();
          }
        });
    FormData fdFunction = new FormData();
    fdFunction.left = new FormAttachment(middle, 0);
    fdFunction.right = new FormAttachment(wbFunction, -margin);
    fdFunction.top = new FormAttachment(lastControl, margin);
    wFunction.setLayoutData(fdFunction);
    lastControl = wFunction;

    // The parameter input fields...
    //
    wlInput = new Label(shell, SWT.NONE);
    wlInput.setText(BaseMessages.getString(PKG, "SapInputDialog.Input.Label"));
    props.setLook(wlInput);
    FormData fdlInput = new FormData();
    fdlInput.left = new FormAttachment(0, 0);
    fdlInput.top = new FormAttachment(lastControl, margin);
    wlInput.setLayoutData(fdlInput);

    ColumnInfo[] ciKey =
        new ColumnInfo[] {
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.Field"),
              ColumnInfo.COLUMN_TYPE_CCOMBO,
              new String[] {""},
              false),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.SAPType"),
              ColumnInfo.COLUMN_TYPE_CCOMBO,
              SapType.getDescriptions()),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.TableOrStruct"),
              ColumnInfo.COLUMN_TYPE_TEXT,
              false,
              false),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.SAPParameterName"),
              ColumnInfo.COLUMN_TYPE_TEXT,
              false,
              false),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.TargetType"),
              ColumnInfo.COLUMN_TYPE_CCOMBO,
              ValueMeta.getTypes()),
        };
    inputFieldColumns.add(ciKey[0]);

    wInput =
        new TableView(
            transMeta,
            shell,
            SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL,
            ciKey,
            input.getParameters().size(),
            lsMod,
            props);

    FormData fdInput = new FormData();
    fdInput.left = new FormAttachment(0, 0);
    fdInput.top = new FormAttachment(wlInput, margin);
    fdInput.right = new FormAttachment(100, 0);
    fdInput.bottom = new FormAttachment(40, 0);
    wInput.setLayoutData(fdInput);
    lastControl = wInput;

    // THE BUTTONS
    wOK = new Button(shell, SWT.PUSH);
    wOK.setText(BaseMessages.getString(PKG, "System.Button.OK"));
    // wPreview = new Button(shell, SWT.PUSH);
    // wPreview.setText(BaseMessages.getString(PKG, "System.Button.Preview"));
    wGet = new Button(shell, SWT.PUSH);
    wGet.setText(BaseMessages.getString(PKG, "SapInputDialog.GetFields.Button"));
    wCancel = new Button(shell, SWT.PUSH);
    wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
    wAbout = new Button(shell, SWT.PUSH);
    wAbout.setText(BaseMessages.getString(PKG, "SapInputDialog.About.Button"));
    // Preview not possible without inputRowSets in BaseStep.getRow()
    // setButtonPositions(new Button[] { wOK, wPreview, wAbout , wGet, wCancel}, margin, null);
    setButtonPositions(new Button[] {wOK, wAbout, wGet, wCancel}, margin, null);

    // The output fields...
    //
    wlOutput = new Label(shell, SWT.NONE);
    wlOutput.setText(BaseMessages.getString(PKG, "SapInputDialog.Output.Label"));
    props.setLook(wlOutput);
    FormData fdlOutput = new FormData();
    fdlOutput.left = new FormAttachment(0, 0);
    fdlOutput.top = new FormAttachment(wInput, margin);
    wlOutput.setLayoutData(fdlOutput);

    ColumnInfo[] ciReturn =
        new ColumnInfo[] {
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.SAPField"),
              ColumnInfo.COLUMN_TYPE_CCOMBO,
              new String[] {},
              false),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.SAPType"),
              ColumnInfo.COLUMN_TYPE_CCOMBO,
              SapType.getDescriptions(),
              false),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.TableOrStruct"),
              ColumnInfo.COLUMN_TYPE_TEXT,
              false),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.NewName"),
              ColumnInfo.COLUMN_TYPE_TEXT,
              false),
          new ColumnInfo(
              BaseMessages.getString(PKG, "SapInputDialog.ColumnInfo.TargetType"),
              ColumnInfo.COLUMN_TYPE_CCOMBO,
              ValueMeta.getTypes()),
        };
    outputFieldColumns.add(ciReturn[0]);

    wOutput =
        new TableView(
            transMeta,
            shell,
            SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL,
            ciReturn,
            input.getOutputFields().size(),
            lsMod,
            props);

    FormData fdOutput = new FormData();
    fdOutput.left = new FormAttachment(0, 0);
    fdOutput.top = new FormAttachment(wlOutput, margin);
    fdOutput.right = new FormAttachment(100, 0);
    fdOutput.bottom = new FormAttachment(wOK, -8 * margin);
    wOutput.setLayoutData(fdOutput);
    lastControl = wOutput;

    this.wAscLink = new Link(this.shell, SWT.NONE);
    FormData fdAscLink = new FormData();
    fdAscLink.left = new FormAttachment(0, 0);
    fdAscLink.top = new FormAttachment(wOutput, margin);
    wAscLink.setLayoutData(fdAscLink);
    this.wAscLink.setText(BaseMessages.getString(PKG, "SapInputDialog.Provided.Info"));
    lastControl = wAscLink;

    // Add listeners
    lsOK =
        new Listener() {
          public void handleEvent(Event e) {
            ok();
          }
        };
    lsPreview =
        new Listener() {
          public void handleEvent(Event e) {
            preview();
          }
        };
    lsGet =
        new Listener() {
          public void handleEvent(Event e) {
            get();
          }
        };
    lsCancel =
        new Listener() {
          public void handleEvent(Event e) {
            cancel();
          }
        };
    Listener lsAbout =
        new Listener() {
          public void handleEvent(Event e) {
            about();
          }
        };

    wOK.addListener(SWT.Selection, lsOK);
    // wPreview.addListener(SWT.Selection, lsPreview);
    wGet.addListener(SWT.Selection, lsGet);
    wCancel.addListener(SWT.Selection, lsCancel);
    this.wAbout.addListener(SWT.Selection, lsAbout);

    this.wAscLink.addListener(
        SWT.Selection,
        new Listener() {
          public void handleEvent(final Event event) {
            Program.launch(event.text);
          }
        });

    lsDef =
        new SelectionAdapter() {
          public void widgetDefaultSelected(SelectionEvent e) {
            ok();
          }
        };

    wStepname.addSelectionListener(lsDef);
    wFunction.addSelectionListener(lsDef);

    // Detect X or ALT-F4 or something that kills this window...
    shell.addShellListener(
        new ShellAdapter() {
          public void shellClosed(ShellEvent e) {
            cancel();
          }
        });

    getData();

    // Set the shell size, based upon previous time...
    setSize();

    input.setChanged(backupChanged);

    setComboValues();
    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
    return stepname;
  }