private void renameLinks(
      XWikiDocument document, DocumentReference oldTarget, DocumentReference newTarget)
      throws XWikiException {
    DocumentReference currentDocumentReference = document.getDocumentReference();

    // We support only the syntaxes for which there is an available renderer.
    if (!this.contextComponentManagerProvider
        .get()
        .hasComponent(BlockRenderer.class, document.getSyntax().toIdString())) {
      this.logger.warn(
          "We can't rename the links from [{}] "
              + "because there is no renderer available for its syntax [{}].",
          currentDocumentReference,
          document.getSyntax());
      return;
    }

    XDOM xdom = document.getXDOM();
    List<Block> blocks = linkedResourceHelper.getBlocks(xdom);

    boolean modified = false;
    for (Block block : blocks) {
      try {
        modified |= renameLink(block, currentDocumentReference, oldTarget, newTarget);
      } catch (InvalidArgumentException e) {
        continue;
      }
    }

    if (modified) {
      document.setContent(xdom);
      saveDocumentPreservingContentAuthor(document, "Renamed back-links.", false);
      this.logger.info(
          "The links from [{}] that were targeting [{}] have been updated to target [{}].",
          document.getDocumentReferenceWithLocale(),
          oldTarget,
          newTarget);
    } else {
      this.logger.info("No back-links to update in [{}].", currentDocumentReference);
    }
  }
  private void updateRelativeLinks(XWikiDocument document, DocumentReference oldDocumentReference)
      throws XWikiException {
    // We support only the syntaxes for which there is an available renderer.
    if (!this.contextComponentManagerProvider
        .get()
        .hasComponent(BlockRenderer.class, document.getSyntax().toIdString())) {
      this.logger.warn(
          "We can't update the relative links from [{}]"
              + " because there is no renderer available for its syntax [{}].",
          document.getDocumentReference(),
          document.getSyntax());
      return;
    }

    DocumentReference newDocumentReference = document.getDocumentReference();

    XDOM xdom = document.getXDOM();
    List<Block> blocks = linkedResourceHelper.getBlocks(xdom);

    boolean modified = false;
    for (Block block : blocks) {
      ResourceReference resourceReference = linkedResourceHelper.getResourceReference(block);
      if (resourceReference == null) {
        // Skip invalid blocks.
        continue;
      }

      ResourceType resourceType = resourceReference.getType();

      // TODO: support ATTACHMENT as well.
      if (!ResourceType.DOCUMENT.equals(resourceType) && !ResourceType.SPACE.equals(resourceType)) {
        // We are currently only interested in Document or Space references.
        continue;
      }

      // current link, use the old document's reference to fill in blanks.
      EntityReference oldLinkReference =
          this.resourceReferenceResolver.resolve(resourceReference, null, oldDocumentReference);
      // new link, use the new document's reference to fill in blanks.
      EntityReference newLinkReference =
          this.resourceReferenceResolver.resolve(resourceReference, null, newDocumentReference);

      // If the new and old link references don`t match, then we must update the relative link.
      if (!newLinkReference.equals(oldLinkReference)) {
        modified = true;

        // Serialize the old (original) link relative to the new document's location, in compact
        // form.
        String serializedLinkReference =
            this.compactEntityReferenceSerializer.serialize(oldLinkReference, newDocumentReference);

        // Update the reference in the XDOM.
        linkedResourceHelper.setResourceReferenceString(block, serializedLinkReference);
      }
    }

    if (modified) {
      document.setContent(xdom);
      saveDocumentPreservingContentAuthor(document, "Updated the relative links.", true);
      this.logger.info("Updated the relative links from [{}].", document.getDocumentReference());
    } else {
      this.logger.info("No relative links to update in [{}].", document.getDocumentReference());
    }
  }
  @Override
  public SolrInputDocument getSolrDocument(EntityReference entityReference)
      throws SolrIndexException, IllegalArgumentException {
    DocumentReference documentReference = new DocumentReference(entityReference);

    XWikiContext context = getXWikiContext();

    try {
      SolrInputDocument solrDocument = new SolrInputDocument();

      XWikiDocument translatedDocument = getTranslatedDocument(documentReference);

      solrDocument.addField(Fields.ID, getId(documentReference));
      addDocumentFields(documentReference, solrDocument);
      solrDocument.addField(Fields.TYPE, documentReference.getType().name());
      solrDocument.addField(Fields.FULLNAME, compactSerializer.serialize(documentReference));

      // Convert the XWiki syntax of document to plain text.
      WikiPrinter printer = new DefaultWikiPrinter();
      renderer.render(translatedDocument.getXDOM(), printer);

      // Same for document title
      String plainTitle = translatedDocument.getRenderedTitle(Syntax.PLAIN_1_0, context);

      // Get the rendered plain text title.
      solrDocument.addField(Fields.TITLE /* + USCORE + language */, plainTitle);
      solrDocument.addField(Fields.DOCUMENT_CONTENT /* + USCORE + language */, printer.toString());
      solrDocument.addField(Fields.VERSION, translatedDocument.getVersion());

      solrDocument.addField(
          Fields.AUTHOR, serializer.serialize(translatedDocument.getAuthorReference()));
      solrDocument.addField(
          Fields.CREATOR, serializer.serialize(translatedDocument.getCreatorReference()));
      solrDocument.addField(Fields.CREATIONDATE, translatedDocument.getCreationDate());
      solrDocument.addField(Fields.DATE, translatedDocument.getContentUpdateDate());

      // Document translations have their own hidden fields
      solrDocument.setField(Fields.HIDDEN, translatedDocument.isHidden());

      // Index the Comments and Objects in general. Use the original document to get the comment
      // objects since the
      // translated document is just a lightweight object containing the translated content and
      // title.

      // FIXME: What about the fact that all translations have the same comments? The field will get
      // copied to
      // each version. Maybe we should handle specially the original document.
      XWikiDocument originalDocument = getDocument(documentReference);

      // Comments. TODO: Is this particular handling of comments actually useful?
      addComments(solrDocument, originalDocument);

      // Objects
      for (Map.Entry<DocumentReference, List<BaseObject>> objects :
          originalDocument.getXObjects().entrySet()) {
        for (BaseObject object : objects.getValue()) {
          this.addObjectContent(solrDocument, object);
        }
      }

      return solrDocument;
    } catch (Exception e) {
      throw new SolrIndexException(
          String.format(
              "Failed to get input document for '%s'", serializer.serialize(documentReference)),
          e);
    }
  }