@Override
  @Transactional
  public HDocument saveDocument(
      String projectSlug,
      String iterationSlug,
      Resource sourceDoc,
      Set<String> extensions,
      boolean copyTrans) {
    // Only active iterations allow the addition of a document
    HProjectIteration hProjectIteration = projectIterationDAO.getBySlug(projectSlug, iterationSlug);

    // Check permission
    identity.checkPermission(hProjectIteration, "import-template");

    String docId = sourceDoc.getName();

    HDocument document = documentDAO.getByDocIdAndIteration(hProjectIteration, docId);
    HLocale hLocale = this.localeServiceImpl.validateSourceLocale(sourceDoc.getLang());

    boolean changed = false;
    int nextDocRev;
    if (document == null) { // must be a create operation
      nextDocRev = 1;
      changed = true;
      // TODO check that entity name matches id parameter
      document = new HDocument(sourceDoc.getName(), sourceDoc.getContentType(), hLocale);
      document.setProjectIteration(hProjectIteration);
      hProjectIteration.getDocuments().put(docId, document);
      document = documentDAO.makePersistent(document);
    } else if (document.isObsolete()) { // must also be a create operation
      nextDocRev = document.getRevision() + 1;
      changed = true;
      document.setObsolete(false);
      // not sure if this is needed
      hProjectIteration.getDocuments().put(docId, document);
    } else { // must be an update operation
      nextDocRev = document.getRevision() + 1;
    }

    changed |=
        resourceUtils.transferFromResource(sourceDoc, document, extensions, hLocale, nextDocRev);
    documentDAO.flush();

    long actorId = authenticatedAccount.getPerson().getId();
    if (changed) {
      documentUploadedEvent.fireAfterSuccess(
          new DocumentUploadedEvent(actorId, document.getId(), true, hLocale.getLocaleId()));
      clearStatsCacheForUpdatedDocument(document);
    }

    if (copyTrans && nextDocRev == 1) {
      copyTranslations(document);
    }

    return document;
  }