private static Result getFlowHistory(Version version) {
    DynamicForm form = Form.form().bindFromRequest(request());
    String partialFlowDefId = form.get(FLOW_DEF_ID);
    partialFlowDefId = (partialFlowDefId != null) ? partialFlowDefId.trim() : null;

    boolean hasSparkJob = false;

    String graphType = form.get("select-graph-type");

    // get the graph type
    if (graphType == null) {
      graphType = "resources";
    }

    if (!Utils.isSet(partialFlowDefId)) {
      if (version.equals(Version.NEW)) {
        return ok(flowHistoryPage
            .render(partialFlowDefId, graphType, flowHistoryResults.render(null, null, null, null)));
      } else {
        return ok(
            oldFlowHistoryPage.render(partialFlowDefId, graphType, oldFlowHistoryResults.render(null, null, null, null)));
      }
    }

    IdUrlPair flowDefPair = bestSchedulerInfoMatchGivenPartialId(partialFlowDefId, AppResult.TABLE.FLOW_DEF_ID);

    List<AppResult> results;

    if (graphType.equals("time") || graphType.equals("resources")) {

      // if graph type is time or resources, we don't need the result from APP_HEURISTIC_RESULTS
      results = AppResult.find.select(
          AppResult.getSearchFields() + "," + AppResult.TABLE.FLOW_EXEC_ID + "," + AppResult.TABLE.FLOW_EXEC_URL + ","
              + AppResult.TABLE.JOB_DEF_ID + "," + AppResult.TABLE.JOB_DEF_URL + "," + AppResult.TABLE.JOB_NAME)
          .where()
          .eq(AppResult.TABLE.FLOW_DEF_ID, flowDefPair.getId())
          .order()
          .desc(AppResult.TABLE.FINISH_TIME)
          .setMaxRows(JOB_HISTORY_LIMIT)
          .findList();
    } else {

      // Fetch available flow executions with latest JOB_HISTORY_LIMIT mr jobs.
      results = AppResult.find.select(
          AppResult.getSearchFields() + "," + AppResult.TABLE.FLOW_EXEC_ID + "," + AppResult.TABLE.FLOW_EXEC_URL + ","
              + AppResult.TABLE.JOB_DEF_ID + "," + AppResult.TABLE.JOB_DEF_URL + "," + AppResult.TABLE.JOB_NAME)
          .where()
          .eq(AppResult.TABLE.FLOW_DEF_ID, flowDefPair.getId())
          .order()
          .desc(AppResult.TABLE.FINISH_TIME)
          .setMaxRows(JOB_HISTORY_LIMIT)
          .fetch(AppResult.TABLE.APP_HEURISTIC_RESULTS, AppHeuristicResult.getSearchFields())
          .findList();
    }
    if (results.size() == 0) {
      return notFound("Unable to find record for flow def id: " + flowDefPair.getId());
    }

    for (AppResult result : results) {
      if (result.jobType.equals("Spark")) {
        hasSparkJob = true;
      }
    }

    Map<IdUrlPair, List<AppResult>> flowExecIdToJobsMap = ControllerUtil
        .limitHistoryResults(ControllerUtil.groupJobs(results, ControllerUtil.GroupBy.FLOW_EXECUTION_ID),
            results.size(), MAX_HISTORY_LIMIT);

    // Compute flow execution data
    List<AppResult> filteredResults = new ArrayList<AppResult>();     // All jobs starting from latest execution
    List<Long> flowExecTimeList = new ArrayList<Long>();         // To map executions to resp execution time
    Map<IdUrlPair, Map<IdUrlPair, List<AppResult>>> executionMap =
        new LinkedHashMap<IdUrlPair, Map<IdUrlPair, List<AppResult>>>();
    for (Map.Entry<IdUrlPair, List<AppResult>> entry : flowExecIdToJobsMap.entrySet()) {

      // Reverse the list content from desc order of finish time to increasing order so that when grouping we get
      // the job list in the order of completion.
      List<AppResult> mrJobsList = Lists.reverse(entry.getValue());

      // Flow exec time is the finish time of the last mr job in the flow
      flowExecTimeList.add(mrJobsList.get(mrJobsList.size() - 1).finishTime);

      filteredResults.addAll(mrJobsList);
      executionMap.put(entry.getKey(), ControllerUtil.groupJobs(mrJobsList, ControllerUtil.GroupBy.JOB_DEFINITION_ID));
    }

    // Calculate unique list of jobs (job def url) to maintain order across executions. List will contain job def urls
    // from latest execution first followed by any other extra job def url that may appear in previous executions.
    final Map<IdUrlPair, String> idPairToJobNameMap = new ListOrderedMap() ;

    Map<IdUrlPair, List<AppResult>> filteredTempMap =
        ControllerUtil.groupJobs(filteredResults, ControllerUtil.GroupBy.JOB_DEFINITION_ID);

    List<Map.Entry<IdUrlPair, List<AppResult>>> filteredMapList =
        new LinkedList<Map.Entry<IdUrlPair, List<AppResult>>>( filteredTempMap.entrySet() );

    Collections.sort(filteredMapList, new Comparator<Map.Entry<IdUrlPair, List<AppResult>>>() {
      @Override
      public int compare(Map.Entry<IdUrlPair, List<AppResult>> idUrlPairListMap, Map.Entry<IdUrlPair, List<AppResult>> t1) {
        return ( new Long(idUrlPairListMap.getValue().get(0).finishTime)).compareTo(t1.getValue().get(0).finishTime);
      }
    });


    for (Map.Entry<IdUrlPair, List<AppResult>> entry : filteredMapList) {
      idPairToJobNameMap.put(entry.getKey(), entry.getValue().get(0).jobName);
    }

    if (version.equals(Version.NEW)) {
      if (graphType.equals("heuristics")) {
        return ok(flowHistoryPage.render(flowDefPair.getId(), graphType,
            flowHistoryResults.render(flowDefPair, executionMap, idPairToJobNameMap, flowExecTimeList)));
      } else if (graphType.equals("resources") || graphType.equals("time")) {
          return ok(flowHistoryPage.render(flowDefPair.getId(), graphType, flowMetricsHistoryResults
              .render(flowDefPair, graphType, executionMap, idPairToJobNameMap, flowExecTimeList)));
      }
    } else {
      if (graphType.equals("heuristics")) {
        return ok(oldFlowHistoryPage.render(flowDefPair.getId(), graphType,
            oldFlowHistoryResults.render(flowDefPair, executionMap, idPairToJobNameMap, flowExecTimeList)));
      } else if (graphType.equals("resources") || graphType.equals("time")) {
        if (hasSparkJob) {
          return notFound("Cannot plot graph for " + graphType + " since it contains a spark job. " + graphType
              + " graphs are not supported for spark right now");
        } else {
          return ok(oldFlowHistoryPage.render(flowDefPair.getId(), graphType, oldFlowMetricsHistoryResults
                  .render(flowDefPair, graphType, executionMap, idPairToJobNameMap, flowExecTimeList)));
        }
      }
    }
    return notFound("Unable to find graph type: " + graphType);
  }
Returns the flowHistory based on the version provided

@param version Can be either new or old
@return The flowhistory page based on the version provided
app/controllers/Application.java