public DataNode elementToDataNode(final RepositoryElementInterface element)
      throws KettleException {
    TransMeta transMeta = (TransMeta) element;

    DataNode rootNode = new DataNode(NODE_TRANS);

    DataNode stepsNode = rootNode.addNode(NODE_STEPS);

    if (transMeta.getPrivateTransformationDatabases() != null) {
      // save all private transformations database name http://jira.pentaho.com/browse/PPP-3405
      DataNode privateDatabaseNode = rootNode.addNode(NODE_TRANS_PRIVATE_DATABASES);
      for (String privateDatabase : transMeta.getPrivateTransformationDatabases()) {
        privateDatabaseNode.addNode(privateDatabase);
      }
    }
    // Also save all the steps in the transformation!
    //
    int stepNr = 0;
    for (StepMeta step : transMeta.getSteps()) {
      stepNr++;
      DataNode stepNode =
          stepsNode.addNode(
              sanitizeNodeName(step.getName()) + "_" + stepNr + EXT_STEP); // $NON-NLS-1$

      // Store the main data
      //
      stepNode.setProperty(PROP_NAME, step.getName());
      stepNode.setProperty(PROP_DESCRIPTION, step.getDescription());
      stepNode.setProperty(PROP_STEP_TYPE, step.getStepID());
      stepNode.setProperty(PROP_STEP_DISTRIBUTE, step.isDistributes());
      stepNode.setProperty(
          PROP_STEP_ROW_DISTRIBUTION,
          step.getRowDistribution() == null ? null : step.getRowDistribution().getCode());
      stepNode.setProperty(PROP_STEP_COPIES, step.getCopies());
      stepNode.setProperty(PROP_STEP_COPIES_STRING, step.getCopiesString());
      stepNode.setProperty(PROP_STEP_GUI_LOCATION_X, step.getLocation().x);
      stepNode.setProperty(PROP_STEP_GUI_LOCATION_Y, step.getLocation().y);
      stepNode.setProperty(PROP_STEP_GUI_DRAW, step.isDrawn());

      // Also save the step group attributes map
      //
      AttributesMapUtil.saveAttributesMap(stepNode, step);

      // Save the step metadata using the repository save method, NOT XML
      // That is because we want to keep the links to databases, conditions, etc by ID, not name.
      //
      StepMetaInterface stepMetaInterface = step.getStepMetaInterface();
      DataNode stepCustomNode = new DataNode(NODE_STEP_CUSTOM);
      Repository proxy = new RepositoryProxy(stepCustomNode);
      compatibleSaveRep(stepMetaInterface, proxy, null, null);
      stepMetaInterface.saveRep(proxy, proxy.getMetaStore(), null, null);
      stepNode.addNode(stepCustomNode);

      // Save the partitioning information by reference as well...
      //
      StepPartitioningMeta partitioningMeta = step.getStepPartitioningMeta();
      if (partitioningMeta != null
          && partitioningMeta.getPartitionSchema() != null
          && partitioningMeta.isPartitioned()) {
        DataNodeRef ref =
            new DataNodeRef(partitioningMeta.getPartitionSchema().getObjectId().getId());
        stepNode.setProperty(PROP_PARTITIONING_SCHEMA, ref);
        stepNode.setProperty(
            PROP_PARTITIONING_METHOD, partitioningMeta.getMethodCode()); // method of partitioning
        if (partitioningMeta.getPartitioner() != null) {
          DataNode partitionerCustomNode = new DataNode(NODE_PARTITIONER_CUSTOM);
          proxy = new RepositoryProxy(partitionerCustomNode);
          partitioningMeta.getPartitioner().saveRep(proxy, null, null);
          stepNode.addNode(partitionerCustomNode);
        }
      }

      // Save the clustering information as well...
      //
      stepNode.setProperty(
          PROP_CLUSTER_SCHEMA,
          step.getClusterSchema() == null
              ? ""
              : step.getClusterSchema() //$NON-NLS-1$
                  .getName());

      // Save the error hop metadata
      //
      StepErrorMeta stepErrorMeta = step.getStepErrorMeta();
      if (stepErrorMeta != null) {
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_SOURCE_STEP,
            stepErrorMeta.getSourceStep() != null
                ? stepErrorMeta.getSourceStep().getName()
                : ""); //$NON-NLS-1$
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_TARGET_STEP,
            stepErrorMeta.getTargetStep() != null
                ? stepErrorMeta.getTargetStep().getName()
                : ""); //$NON-NLS-1$
        stepNode.setProperty(PROP_STEP_ERROR_HANDLING_IS_ENABLED, stepErrorMeta.isEnabled());
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_NR_VALUENAME, stepErrorMeta.getNrErrorsValuename());
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_DESCRIPTIONS_VALUENAME,
            stepErrorMeta.getErrorDescriptionsValuename());
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_FIELDS_VALUENAME, stepErrorMeta.getErrorFieldsValuename());
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_CODES_VALUENAME, stepErrorMeta.getErrorCodesValuename());
        stepNode.setProperty(PROP_STEP_ERROR_HANDLING_MAX_ERRORS, stepErrorMeta.getMaxErrors());
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_MAX_PCT_ERRORS, stepErrorMeta.getMaxPercentErrors());
        stepNode.setProperty(
            PROP_STEP_ERROR_HANDLING_MIN_PCT_ROWS, stepErrorMeta.getMinPercentRows());
      }
    }

    // Save the notes
    //
    DataNode notesNode = rootNode.addNode(NODE_NOTES);
    notesNode.setProperty(PROP_NR_NOTES, transMeta.nrNotes());
    for (int i = 0; i < transMeta.nrNotes(); i++) {
      NotePadMeta note = transMeta.getNote(i);
      DataNode noteNode = notesNode.addNode(NOTE_PREFIX + i);

      noteNode.setProperty(PROP_XML, note.getXML());
    }

    // Finally, save the hops
    //
    DataNode hopsNode = rootNode.addNode(NODE_HOPS);
    hopsNode.setProperty(PROP_NR_HOPS, transMeta.nrTransHops());
    for (int i = 0; i < transMeta.nrTransHops(); i++) {
      TransHopMeta hop = transMeta.getTransHop(i);
      DataNode hopNode = hopsNode.addNode(TRANS_HOP_PREFIX + i);
      hopNode.setProperty(TRANS_HOP_FROM, hop.getFromStep().getName());
      hopNode.setProperty(TRANS_HOP_TO, hop.getToStep().getName());
      hopNode.setProperty(TRANS_HOP_ENABLED, hop.isEnabled());
    }

    // Parameters
    //
    String[] paramKeys = transMeta.listParameters();
    DataNode paramsNode = rootNode.addNode(NODE_PARAMETERS);
    paramsNode.setProperty(PROP_NR_PARAMETERS, paramKeys == null ? 0 : paramKeys.length);

    for (int idx = 0; idx < paramKeys.length; idx++) {
      DataNode paramNode = paramsNode.addNode(TRANS_PARAM_PREFIX + idx);
      String key = paramKeys[idx];
      String description = transMeta.getParameterDescription(paramKeys[idx]);
      String defaultValue = transMeta.getParameterDefault(paramKeys[idx]);

      paramNode.setProperty(PARAM_KEY, key != null ? key : ""); // $NON-NLS-1$
      paramNode.setProperty(PARAM_DEFAULT, defaultValue != null ? defaultValue : ""); // $NON-NLS-1$
      paramNode.setProperty(PARAM_DESC, description != null ? description : ""); // $NON-NLS-1$
    }

    // Let's not forget to save the details of the transformation itself.
    // This includes logging information, parameters, etc.
    //
    saveTransformationDetails(rootNode, transMeta);

    return rootNode;
  }