@Override
  public ContentDocument getContentDocumentByPath(String path, Locale locale) {
    Navigation navigation = this.getNavigation(locale);

    NavigationElement navigationElement = navigation.getNavigationElementByPath(path);
    if (navigationElement == null || StringUtils.isEmpty(navigationElement.getDocumentId())) {
      return null;
    }

    Map<String, String> linkTranslationMap = navigation.getLinkTranslationMap();
    return this.getContentDocument(
        navigationElement.getDocumentId(), locale, createRelativizer(path), linkTranslationMap);
  }
  @Override
  public ContentDocument getContentDocumentById(String id, String relativizer, Locale locale) {
    Navigation navigation = this.getNavigation(locale);

    // check if the document exists
    NavigationElement navigationElement = navigation.getNavigationElementByDocumentId(id);
    if (navigationElement == null || StringUtils.isEmpty(navigationElement.getDocumentId())) {
      return null;
    }

    Map<String, String> linkTranslationMap = navigation.getLinkTranslationMap();
    return this.getContentDocument(id, locale, relativizer, linkTranslationMap);
  }
  @Override
  public NavigationElement[] getMenuNavigationElementsForPath(String path, Locale locale) {
    NavigationElement currentElement = this.getNavigation(locale).getNavigationElementByPath(path);

    if (currentElement == null) {
      return new NavigationElement[0];
    }

    // navigate to the element one above the root element
    while (currentElement.getParent() != null && !currentElement.getParent().isRoot()) {
      currentElement = currentElement.getParent();
    }

    // add the navigation element at the first level and its children
    List<NavigationElement> elements = new ArrayList<NavigationElement>();
    if (StringUtils.isNotBlank(currentElement.getDocumentId())) {
      elements.add(currentElement);
    }
    for (NavigationElement currentChildElement : currentElement.getChildren()) {
      if (StringUtils.isNotBlank(currentChildElement.getDocumentId())) {
        elements.add(currentChildElement);
      }
    }

    return elements.toArray(new NavigationElement[elements.size()]);
  }
  private ContentDocument getContentDocument(
      String documentId,
      Locale locale,
      String pathRelativizer,
      Map<String, String> linkRewriteTranslationTable) {
    ContentDocument contentDocument =
        this.contentDocumentDao.get(
            documentId, locale, pathRelativizer, linkRewriteTranslationTable);

    // add the navigation path to the content document
    NavigationElement navEl =
        this.getNavigation(locale).getNavigationElementByDocumentId(documentId);
    if (navEl != null) {
      contentDocument.setPath(navEl.getPath());
    }
    contentDocument.setNavigationElement(navEl);

    return contentDocument;
  }
  @Override
  public List<ContentDocument> find(String query, Locale locale) {
    List<String> docIds = this.contentDocumentDao.find(query, locale);

    // check if the result documents is part of the navigation
    List<String> existingDocIds = new ArrayList<String>();
    Navigation navigation = this.getNavigation(locale);
    for (String docId : docIds) {
      NavigationElement navigationElement = navigation.getNavigationElementByDocumentId(docId);

      if (navigationElement != null && StringUtils.isNotEmpty(navigationElement.getDocumentId())) {
        existingDocIds.add(docId);
      }
    }

    // load the document
    List<ContentDocument> results = new ArrayList<ContentDocument>();
    for (String documentId : existingDocIds) {
      results.add(this.getContentDocument(documentId, locale, "", null));
    }

    return results;
  }