@Override
 @Async
 @Transactional
 public Future<HDocument> saveDocumentAsync(
     String projectSlug,
     String iterationSlug,
     Resource sourceDoc,
     Set<String> extensions,
     boolean copyTrans,
     boolean lock,
     AsyncTaskHandle<HDocument> handle) {
   // TODO Use the pased in handle
   return AsyncTaskResult.taskResult(
       saveDocument(projectSlug, iterationSlug, sourceDoc, extensions, copyTrans, lock));
 }
  @Override
  @Async
  public Future<Void> startMergeTranslations(
      String sourceProjectSlug,
      String sourceVersionSlug,
      String targetProjectSlug,
      String targetVersionSlug,
      boolean useNewerTranslation,
      MergeTranslationsTaskHandle handle) {

    HProjectIteration sourceVersion =
        projectIterationDAO.getBySlug(sourceProjectSlug, sourceVersionSlug);

    if (sourceVersion == null) {
      log.error("Cannot find source version of {}:{}", sourceProjectSlug, sourceVersionSlug);
      return AsyncTaskResult.taskResult();
    }

    HProjectIteration targetVersion =
        projectIterationDAO.getBySlug(targetProjectSlug, targetVersionSlug);

    if (targetVersion == null) {
      log.error("Cannot find target version of {}:{}", targetProjectSlug, targetVersionSlug);
      return AsyncTaskResult.taskResult();
    }

    if (isVersionsEmpty(sourceVersion, targetVersion)) {
      return AsyncTaskResult.taskResult();
    }

    if (getSupportedLocales(targetProjectSlug, targetVersionSlug).isEmpty()) {
      log.error(
          "No locales enabled in target version of {} [{}]", targetProjectSlug, targetVersionSlug);
      return AsyncTaskResult.taskResult();
    }

    Optional<MergeTranslationsTaskHandle> taskHandleOpt = Optional.fromNullable(handle);

    if (taskHandleOpt.isPresent()) {
      prepareMergeTranslationsHandle(sourceVersion, targetVersion, taskHandleOpt.get());
    }

    Stopwatch overallStopwatch = Stopwatch.createStarted();
    log.info(
        "merge translations start: from {} to {}",
        sourceProjectSlug + ":" + sourceVersionSlug,
        targetProjectSlug + ":" + targetVersionSlug);

    int startCount = 0;
    int totalCount = getTotalMatchCount(sourceVersion.getId(), targetVersion.getId());

    List<HLocale> supportedLocales =
        getSupportedLocales(targetVersion.getProject().getSlug(), targetVersion.getSlug());

    while (startCount < totalCount) {
      int processedCount =
          mergeTranslationBatch(
              sourceVersion,
              targetVersion,
              supportedLocales,
              useNewerTranslation,
              startCount,
              TEXTFLOWS_PER_BATCH);
      if (taskHandleOpt.isPresent()) {
        taskHandleOpt.get().increaseProgress(processedCount);
      }

      startCount += TEXTFLOWS_PER_BATCH;
      textFlowDAO.clear();
    }
    versionStateCacheImpl.clearVersionStatsCache(targetVersion.getId());
    log.info(
        "merge translation end: from {} to {}, {}",
        sourceProjectSlug + ":" + sourceVersionSlug,
        targetProjectSlug + ":" + targetVersionSlug,
        overallStopwatch);

    return AsyncTaskResult.taskResult();
  }