private SapType getSapType(SAPField field) {
   String type = field.getType();
   if (type != null && type.startsWith("input_")) {
     type = type.substring("input_".length());
   } else if (type != null && type.startsWith("output_")) {
     type = type.substring("output_".length());
   }
   return SapType.findTypeForCode(type);
 }
  private void get() {
    try {
      RowMetaInterface r = transMeta.getPrevStepFields(stepname);
      if (r != null && !r.isEmpty()) {
        TableItemInsertListener listener =
            new TableItemInsertListener() {
              public boolean tableItemInserted(TableItem tableItem, ValueMetaInterface v) {
                tableItem.setText(2, "=");
                return true;
              }
            };
        BaseStepDialog.getFieldsFromPrevious(
            r, wInput, 1, new int[] {1, 3}, new int[] {}, -1, -1, listener);
      }

      DatabaseMeta databaseMeta = transMeta.findDatabase(wConnection.getText());
      if (databaseMeta == null) {
        showDatabaseWarning(false);
        return;
      }

      // Fill in the parameters too
      //
      if (function != null) {

        wFunction.setText(function.getName());

        if (wInput.nrNonEmpty() != 0 || wOutput.nrNonEmpty() != 0) {
          MessageBox mb = new MessageBox(shell, SWT.YES | SWT.NO | SWT.ICON_QUESTION);
          mb.setMessage(
              BaseMessages.getString(PKG, "SapInputDialog.ClearInputOutput.DialogMessage"));
          mb.setText(BaseMessages.getString(PKG, "SapInputDialog.ClearInputOutput.DialogTitle"));
          int answer = mb.open();
          if (answer == SWT.NO) {
            return;
          }
        }

        wInput.clearAll(false);
        wOutput.clearAll(false);
        Cursor hourGlass = new Cursor(shell.getDisplay(), SWT.CURSOR_WAIT);
        SAPConnection sc = SAPConnectionFactory.create();
        try {
          shell.setCursor(hourGlass);
          sc.open(databaseMeta);
          SAPFunctionSignature signature = sc.getFunctionSignature(function);

          // Populate the input view
          // TODO: clean this up a bit, feels a bit messy
          //
          int rownr = 0;
          for (SAPField field : signature.getInput()) {
            TableItem item;
            if (rownr == 0) {
              item = wInput.table.getItem(0);
            } else {
              item = new TableItem(wInput.table, SWT.NONE);
            }
            rownr++;

            SapType type = getSapType(field);

            int colnr = 1;
            item.setText(colnr++, Const.NVL(field.getName(), ""));
            item.setText(colnr++, type == null ? "" : type.getDescription());
            item.setText(colnr++, Const.NVL(field.getTable(), ""));
            item.setText(colnr++, Const.NVL(field.getName(), ""));
            item.setText(colnr++, field.getTypePentaho());
          }
          wInput.setRowNums();
          wInput.optWidth(true);

          // Get the output rows
          //
          rownr = 0;
          for (SAPField field : signature.getOutput()) {
            TableItem item;
            if (rownr == 0) {
              item = wOutput.table.getItem(0);
            } else {
              item = new TableItem(wOutput.table, SWT.NONE);
            }
            rownr++;

            SapType type = getSapType(field);

            int colnr = 1;
            item.setText(colnr++, Const.NVL(field.getName(), ""));
            item.setText(colnr++, type == null ? "" : type.getDescription());
            item.setText(colnr++, Const.NVL(field.getTable(), ""));
            item.setText(colnr++, Const.NVL(field.getName(), ""));
            item.setText(colnr++, field.getTypePentaho());
          }
          wOutput.setRowNums();
          wOutput.optWidth(true);

        } catch (Exception e) {
          throw new KettleException(e);
        } finally {
          sc.close();
          shell.setCursor(null);
          hourGlass.dispose();
        }
      }
    } catch (KettleException ke) {
      new ErrorDialog(
          shell,
          BaseMessages.getString(PKG, "SapInputDialog.GetFieldsFailed.DialogTitle"),
          BaseMessages.getString(PKG, "SapInputDialog.GetFieldsFailed.DialogMessage"),
          ke);
    }
  }
  public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
    Object[] r = getRow();
    if (r == null) // no more input to be expected...
    {
      setOutputDone();
      return false;
    }

    if (first) {
      first = false;

      // Determine the output row metadata of this step
      //
      data.outputRowMeta = new RowMeta();
      meta.getFields(data.outputRowMeta, getStepname(), null, null, this);

      // Pre-calculate the indexes of the parameters for performance reasons...
      //
      data.parameterIndexes = new ArrayList<Integer>();
      for (SapParameter parameter : meta.getParameters()) {
        int index = getInputRowMeta().indexOfValue(parameter.getFieldName());
        if (index < 0) {
          throw new KettleException("Unable to find field '" + parameter.getFieldName() + "'");
        }
        data.parameterIndexes.add(index);
      }

      // Pre-calculate the output fields
      //
      data.output = new ArrayList<SAPField>();
      for (SapOutputField outputField : meta.getOutputFields()) {
        SAPField field =
            new SAPField(
                outputField.getSapFieldName(),
                outputField.getTableName(),
                "output_" + outputField.getSapType().getDescription());
        data.output.add(field);
      }
    }

    // Assemble the list of input fields for the SAP function execution...
    //
    ArrayList<SAPField> input = new ArrayList<SAPField>();
    for (int i = 0; i < meta.getParameters().size(); i++) {
      SapParameter parameter = meta.getParameters().get(i);
      int fieldIndex = data.parameterIndexes.get(i);
      ValueMetaInterface valueMeta = getInputRowMeta().getValueMeta(fieldIndex);
      Object value = valueMeta.convertToNormalStorageType(r[fieldIndex]);
      // TODO: figure out if the executeFunction needs the data to be in a specific data type or
      // format!!
      // If so, value needs to be converted to the appropriate data type here.

      SAPField field =
          new SAPField(
              parameter.getParameterName(),
              parameter.getTableName(),
              "input_" + parameter.getSapType().getDescription(),
              value);
      input.add(field);
    }

    // Get the output...
    //
    SAPRowIterator resultSet;
    try {
      resultSet =
          data.sapConnection.executeFunctionCursored(meta.getFunction(), input, data.output);
    } catch (SAPException e) {
      throw new KettleException(e);
    }
    while (resultSet.hasNext()) {
      SAPRow sapRow = resultSet.next();
      Object[] outputRowData = RowDataUtil.allocateRowData(data.outputRowMeta.size());
      int outputIndex =
          0; // Makes it easier to add all sorts of fields later on, like row number, input fields,
             // etc.

      for (SAPField field : sapRow.getFields()) {
        // TODO: Here we should check as well whether or not the correct data types are delivered
        // from SAP.
        // Make sure that we don't pass the appropriate data types : String, long, double, Date,
        // BigDecimal, Boolean, byte[] ONLY!!
        //
        outputRowData[outputIndex++] = field.getValue();
      }

      // Pass the row along: row metadata and data need to correspond!!
      //
      putRow(data.outputRowMeta, outputRowData);

      if (getTrans().isStopped()) break;
    }

    return true;
  }