protected void connectToSubJobOutputFields(
      JobExecutorMeta meta,
      JobMeta subJobMeta,
      IMetaverseNode subTransNode,
      IComponentDescriptor descriptor) {

    if (meta.getResultRowsTargetStep() != null) {
      String outputStep = meta.getResultRowsTargetStep();

      for (int i = 0; i < meta.getResultRowsField().length; i++) {
        String fieldName = meta.getResultRowsField()[i];
        IMetaverseNode outNode = getOutputs().findNode(outputStep, fieldName);
        // TODO
        /* if ( outNode != null ) {
          // add link, if needed, from sub tran result fields to the node just created
           linkResultFieldToSubTrans( outNode, subJobMeta, subTransNode, descriptor );
        }*/
      }
    }
  }
  @Override
  protected void customAnalyze(JobExecutorMeta meta, IMetaverseNode node)
      throws MetaverseAnalyzerException {

    String jobPath = meta.getFileName();
    JobMeta subJobMeta = null;
    Repository repo = parentTransMeta.getRepository();

    switch (meta.getSpecificationMethod()) {
      case FILENAME:
        jobPath = parentTransMeta.environmentSubstitute(meta.getFileName());
        try {
          String normalized = KettleAnalyzerUtil.normalizeFilePath(jobPath);

          subJobMeta = getSubJobMeta(parentTransMeta, normalized);
          jobPath = normalized;

        } catch (Exception e) {
          throw new MetaverseAnalyzerException(
              "Sub transformation can not be found - " + jobPath, e);
        }
        break;
      case REPOSITORY_BY_NAME:
        if (repo != null) {
          String dir = parentTransMeta.environmentSubstitute(meta.getDirectoryPath());
          String file = parentTransMeta.environmentSubstitute(meta.getJobName());
          try {
            RepositoryDirectoryInterface rdi = repo.findDirectory(dir);
            subJobMeta = repo.loadJob(file, rdi, null, null);
            String filename =
                subJobMeta.getFilename() == null ? subJobMeta.toString() : subJobMeta.getFilename();
            jobPath = filename + "." + subJobMeta.getDefaultExtension();
          } catch (KettleException e) {
            throw new MetaverseAnalyzerException(
                "Sub transformation can not be found in repository - " + file, e);
          }
        } else {
          throw new MetaverseAnalyzerException(
              "Not connected to a repository, can't get the transformation");
        }
        break;
      case REPOSITORY_BY_REFERENCE:
        if (repo != null) {
          try {
            subJobMeta = repo.loadJob(meta.getJobObjectId(), null);
            String filename =
                subJobMeta.getFilename() == null ? subJobMeta.toString() : subJobMeta.getFilename();
            jobPath = filename + "." + subJobMeta.getDefaultExtension();
          } catch (KettleException e) {
            throw new MetaverseAnalyzerException(
                "Sub transformation can not be found by reference - " + meta.getJobObjectId(), e);
          }
        } else {
          throw new MetaverseAnalyzerException(
              "Not connected to a repository, can't get the transformation");
        }
        break;
    }

    // analyze the sub trans?

    IComponentDescriptor ds =
        new MetaverseComponentDescriptor(
            subJobMeta.getName(),
            DictionaryConst.NODE_TYPE_JOB,
            descriptor.getNamespace().getParentNamespace());

    IMetaverseNode jobNode = createNodeFromDescriptor(ds);
    jobNode.setProperty(DictionaryConst.PROPERTY_NAMESPACE, ds.getNamespaceId());
    jobNode.setProperty(DictionaryConst.PROPERTY_PATH, jobPath);
    jobNode.setLogicalIdGenerator(DictionaryConst.LOGICAL_ID_GENERATOR_DOCUMENT);

    metaverseBuilder.addLink(node, DictionaryConst.LINK_EXECUTES, jobNode);

    connectToSubJobOutputFields(meta, subJobMeta, jobNode, descriptor);

    node.setProperty(JOB_TO_EXECUTE, jobPath);

    if (StringUtils.isNotEmpty(meta.getExecutionResultTargetStep())) {
      node.setProperty(EXECUTION_RESULTS_TARGET, meta.getExecutionResultTargetStep());
    }

    /* TODO remove? if ( StringUtils.isNotEmpty( meta.getOutputRowsSourceStep() ) ) {
      node.setProperty( OUTPUT_ROWS_TARGET, meta.getOutputRowsSourceStep() );
    }*/

    if (StringUtils.isNotEmpty(meta.getResultFilesTargetStep())) {
      node.setProperty(RESULT_FILES_TARGET, meta.getResultFilesTargetStep());
    }
  }