public String getXML() {
    StringBuffer retval = new StringBuffer(500);

    retval.append("    ").append(XMLHandler.addTagValue("filename", filename));
    retval.append("    ").append(XMLHandler.addTagValue("filename_field", filenameField));
    retval.append("    ").append(XMLHandler.addTagValue("rownum_field", rowNumField));
    retval.append("    ").append(XMLHandler.addTagValue("include_filename", includingFilename));
    retval.append("    ").append(XMLHandler.addTagValue("separator", delimiter));
    retval.append("    ").append(XMLHandler.addTagValue("enclosure", enclosure));
    retval.append("    ").append(XMLHandler.addTagValue("header", headerPresent));
    retval.append("    ").append(XMLHandler.addTagValue("buffer_size", bufferSize));
    retval.append("    ").append(XMLHandler.addTagValue("lazy_conversion", lazyConversionActive));
    retval.append("    ").append(XMLHandler.addTagValue("add_filename_result", isaddresult));
    retval.append("    ").append(XMLHandler.addTagValue("parallel", runningInParallel));
    retval.append("    ").append(XMLHandler.addTagValue("encoding", encoding));

    retval.append("    <fields>").append(Const.CR);
    for (int i = 0; i < inputFields.length; i++) {
      TextFileInputField field = inputFields[i];

      retval.append("      <field>").append(Const.CR);
      retval.append("        ").append(XMLHandler.addTagValue("name", field.getName()));
      retval
          .append("        ")
          .append(XMLHandler.addTagValue("type", ValueMeta.getTypeDesc(field.getType())));
      retval.append("        ").append(XMLHandler.addTagValue("format", field.getFormat()));
      retval
          .append("        ")
          .append(XMLHandler.addTagValue("currency", field.getCurrencySymbol()));
      retval.append("        ").append(XMLHandler.addTagValue("decimal", field.getDecimalSymbol()));
      retval.append("        ").append(XMLHandler.addTagValue("group", field.getGroupSymbol()));
      retval.append("        ").append(XMLHandler.addTagValue("length", field.getLength()));
      retval.append("        ").append(XMLHandler.addTagValue("precision", field.getPrecision()));
      retval
          .append("        ")
          .append(
              XMLHandler.addTagValue("trim_type", ValueMeta.getTrimTypeCode(field.getTrimType())));
      retval.append("      </field>").append(Const.CR);
    }
    retval.append("    </fields>").append(Const.CR);

    return retval.toString();
  }
  public void saveRep(Repository rep, long id_transformation, long id_step) throws KettleException {
    try {
      rep.saveStepAttribute(id_transformation, id_step, "filename", filename);
      rep.saveStepAttribute(id_transformation, id_step, "filename_field", filenameField);
      rep.saveStepAttribute(id_transformation, id_step, "rownum_field", rowNumField);
      rep.saveStepAttribute(id_transformation, id_step, "include_filename", includingFilename);
      rep.saveStepAttribute(id_transformation, id_step, "separator", delimiter);
      rep.saveStepAttribute(id_transformation, id_step, "enclosure", enclosure);
      rep.saveStepAttribute(id_transformation, id_step, "buffer_size", bufferSize);
      rep.saveStepAttribute(id_transformation, id_step, "header", headerPresent);
      rep.saveStepAttribute(id_transformation, id_step, "lazy_conversion", lazyConversionActive);
      rep.saveStepAttribute(id_transformation, id_step, "add_filename_result", isaddresult);
      rep.saveStepAttribute(id_transformation, id_step, "parallel", runningInParallel);
      rep.saveStepAttribute(id_transformation, id_step, "encoding", encoding);

      for (int i = 0; i < inputFields.length; i++) {
        TextFileInputField field = inputFields[i];

        rep.saveStepAttribute(id_transformation, id_step, i, "field_name", field.getName());
        rep.saveStepAttribute(
            id_transformation, id_step, i, "field_type", ValueMeta.getTypeDesc(field.getType()));
        rep.saveStepAttribute(id_transformation, id_step, i, "field_format", field.getFormat());
        rep.saveStepAttribute(
            id_transformation, id_step, i, "field_currency", field.getCurrencySymbol());
        rep.saveStepAttribute(
            id_transformation, id_step, i, "field_decimal", field.getDecimalSymbol());
        rep.saveStepAttribute(id_transformation, id_step, i, "field_group", field.getGroupSymbol());
        rep.saveStepAttribute(id_transformation, id_step, i, "field_length", field.getLength());
        rep.saveStepAttribute(
            id_transformation, id_step, i, "field_precision", field.getPrecision());
        rep.saveStepAttribute(
            id_transformation,
            id_step,
            i,
            "field_trim_type",
            ValueMeta.getTrimTypeCode(field.getTrimType()));
      }
    } catch (Exception e) {
      throw new KettleException(
          "Unable to save step information to the repository for id_step=" + id_step, e);
    }
  }
  public void getFields(
      RowMetaInterface rowMeta,
      String origin,
      RowMetaInterface[] info,
      StepMeta nextStep,
      VariableSpace space)
      throws KettleStepException {
    rowMeta.clear(); // Start with a clean slate, eats the input

    for (int i = 0; i < inputFields.length; i++) {
      TextFileInputField field = inputFields[i];

      ValueMetaInterface valueMeta = new ValueMeta(field.getName(), field.getType());
      valueMeta.setConversionMask(field.getFormat());
      valueMeta.setLength(field.getLength());
      valueMeta.setPrecision(field.getPrecision());
      valueMeta.setConversionMask(field.getFormat());
      valueMeta.setDecimalSymbol(field.getDecimalSymbol());
      valueMeta.setGroupingSymbol(field.getGroupSymbol());
      valueMeta.setCurrencySymbol(field.getCurrencySymbol());
      valueMeta.setTrimType(field.getTrimType());
      if (lazyConversionActive)
        valueMeta.setStorageType(ValueMetaInterface.STORAGE_TYPE_BINARY_STRING);
      valueMeta.setStringEncoding(space.environmentSubstitute(encoding));

      // In case we want to convert Strings...
      // Using a copy of the valueMeta object means that the inner and outer representation format
      // is the same.
      // Preview will show the data the same way as we read it.
      // This layout is then taken further down the road by the metadata through the transformation.
      //
      ValueMetaInterface storageMetadata = valueMeta.clone();
      storageMetadata.setType(ValueMetaInterface.TYPE_STRING);
      storageMetadata.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);
      storageMetadata.setLength(
          -1, -1); // we don't really know the lengths of the strings read in advance.
      valueMeta.setStorageMetadata(storageMetadata);

      valueMeta.setOrigin(origin);

      rowMeta.addValueMeta(valueMeta);
    }

    if (!Const.isEmpty(filenameField) && includingFilename) {
      ValueMetaInterface filenameMeta =
          new ValueMeta(filenameField, ValueMetaInterface.TYPE_STRING);
      filenameMeta.setOrigin(origin);
      if (lazyConversionActive) {
        filenameMeta.setStorageType(ValueMetaInterface.STORAGE_TYPE_BINARY_STRING);
        filenameMeta.setStorageMetadata(
            new ValueMeta(filenameField, ValueMetaInterface.TYPE_STRING));
      }
      rowMeta.addValueMeta(filenameMeta);
    }

    if (!Const.isEmpty(rowNumField)) {
      ValueMetaInterface rowNumMeta = new ValueMeta(rowNumField, ValueMetaInterface.TYPE_INTEGER);
      rowNumMeta.setLength(10);
      rowNumMeta.setOrigin(origin);
      rowMeta.addValueMeta(rowNumMeta);
    }
  }