private Object[] lookupValues(RowMetaInterface rowMeta, Object[] row) throws KettleException {
    // See if we need to stop.
    if (isStopped()) return null;

    if (data.lookupColumnIndex == null) {
      String names[] = data.lookupMeta.getFieldNames();
      data.lookupColumnIndex = new int[names.length];

      for (int i = 0; i < names.length; i++) {
        data.lookupColumnIndex[i] = rowMeta.indexOfValue(names[i]);
        if (data.lookupColumnIndex[i] < 0) {
          // we should not get here
          throw new KettleStepException("The lookup column '" + names[i] + "' could not be found");
        }
      }
    }

    // Copy value references to lookup table.
    //
    Object[] lu = new Object[data.keynrs.length];
    for (int i = 0; i < data.keynrs.length; i++) {
      // If the input is binary storage data, we convert it to normal storage.
      //
      if (data.convertKeysToNative[i]) {
        lu[i] =
            data.lookupMeta
                .getValueMeta(i)
                .convertBinaryStringToNativeType((byte[]) row[data.keynrs[i]]);
      } else {
        lu[i] = row[data.keynrs[i]];
      }
    }

    // Handle conflicting types (Number-Integer-String conversion to lookup type in hashtable)
    if (data.keyTypes != null) {
      for (int i = 0; i < data.lookupMeta.size(); i++) {
        ValueMetaInterface inputValue = data.lookupMeta.getValueMeta(i);
        ValueMetaInterface lookupValue = data.keyTypes.getValueMeta(i);
        if (inputValue.getType() != lookupValue.getType()) {
          try {
            // Change the input value to match the lookup value
            //
            lu[i] = lookupValue.convertDataCompatible(inputValue, lu[i]);
          } catch (KettleValueException e) {
            throw new KettleStepException("Error converting data while looking up value", e);
          }
        }
      }
    }

    Object[] add = null;

    if (data.hasLookupRows) {
      try {
        if (meta.getKeystream().length > 0) {
          add = getFromCache(data.keyTypes, lu);
        } else {
          // Just take the first element in the hashtable...
          throw new KettleStepException(
              BaseMessages.getString(PKG, "StreamLookup.Log.GotRowWithoutKeys")); // $NON-NLS-1$
        }
      } catch (Exception e) {
        throw new KettleStepException(e);
      }
    }

    if (add == null) // nothing was found, unknown code: add the specified default value...
    {
      add = data.nullIf;
    }

    return RowDataUtil.addRowData(row, rowMeta.size(), add);
  }