/**
   * Generate HTextFlowTarget query with matching HTextFlow contents, HTextFlowTarget locale,
   * HTextFlowTarget state = Approved
   *
   * @param query
   * @param sourceLocale
   * @param targetLocale
   * @param queryText
   * @param multiQueryText
   * @param contentFields
   * @return
   * @throws ParseException
   */
  private org.apache.lucene.search.Query generateQuery(
      TransMemoryQuery query,
      LocaleId sourceLocale,
      LocaleId targetLocale,
      String queryText,
      String[] multiQueryText,
      String contentFields[],
      boolean useTargetIndex)
      throws ParseException {
    org.apache.lucene.search.Query contentQuery;
    // Analyzer determined by the language
    String analyzerDefName =
        TextContainerAnalyzerDiscriminator.getAnalyzerDefinitionName(sourceLocale.getId());
    Analyzer analyzer = entityManager.getSearchFactory().getAnalyzer(analyzerDefName);

    if (query.getSearchType() == SearchType.FUZZY_PLURAL) {
      int queriesSize = multiQueryText.length;
      if (queriesSize > contentFields.length) {
        log.warn(
            "query contains {} fields, but we only index {}", queriesSize, contentFields.length);
      }
      String[] searchFields = new String[queriesSize];
      System.arraycopy(contentFields, 0, searchFields, 0, queriesSize);

      contentQuery =
          MultiFieldQueryParser.parse(LUCENE_VERSION, multiQueryText, searchFields, analyzer);
    } else {
      MultiFieldQueryParser parser =
          new MultiFieldQueryParser(LUCENE_VERSION, contentFields, analyzer);
      contentQuery = parser.parse(queryText);
    }

    if (useTargetIndex) {
      TermQuery localeQuery =
          new TermQuery(new Term(IndexFieldLabels.LOCALE_ID_FIELD, targetLocale.getId()));

      TermQuery newStateQuery =
          new TermQuery(
              new Term(IndexFieldLabels.CONTENT_STATE_FIELD, ContentState.New.toString()));
      TermQuery needReviewStateQuery =
          new TermQuery(
              new Term(IndexFieldLabels.CONTENT_STATE_FIELD, ContentState.NeedReview.toString()));
      TermQuery rejectedReviewStateQuery =
          new TermQuery(
              new Term(IndexFieldLabels.CONTENT_STATE_FIELD, ContentState.Rejected.toString()));

      BooleanQuery targetQuery = new BooleanQuery();
      targetQuery.add(contentQuery, Occur.MUST);
      targetQuery.add(localeQuery, Occur.MUST);

      targetQuery.add(newStateQuery, Occur.MUST_NOT);
      targetQuery.add(needReviewStateQuery, Occur.MUST_NOT);
      targetQuery.add(rejectedReviewStateQuery, Occur.MUST_NOT);

      return targetQuery;
    } else {
      return contentQuery;
    }
  }
  @Override
  public List<Object[]> getSearchResult(
      TransMemoryQuery query,
      LocaleId sourceLocale,
      LocaleId targetLocale,
      final int maxResult,
      boolean useTargetIndex)
      throws ParseException {
    String queryText = null;
    String[] multiQueryText = null;

    switch (query.getSearchType()) {
        // 'Lucene' in the editor
      case RAW:
        queryText = query.getQueries().get(0);
        if (StringUtils.isBlank(queryText)) {
          return new ArrayList<Object[]>();
        }
        break;

        // 'Fuzzy' in the editor
      case FUZZY:
        queryText = QueryParser.escape(query.getQueries().get(0));
        if (StringUtils.isBlank(queryText)) {
          return new ArrayList<Object[]>();
        }
        break;

        // 'Phrase' in the editor
      case EXACT:
        queryText = "\"" + QueryParser.escape(query.getQueries().get(0)) + "\"";
        if (StringUtils.isBlank(queryText)) {
          return new ArrayList<Object[]>();
        }
        break;

        // 'Fuzzy' in the editor, plus it is a plural entry
      case FUZZY_PLURAL:
        multiQueryText = new String[query.getQueries().size()];
        for (int i = 0; i < query.getQueries().size(); i++) {
          multiQueryText[i] = QueryParser.escape(query.getQueries().get(i));
          if (StringUtils.isBlank(multiQueryText[i])) {
            return new ArrayList<Object[]>();
          }
        }
        break;
      default:
        throw new RuntimeException("Unknown query type: " + query.getSearchType());
    }

    FullTextQuery ftQuery;
    if (useTargetIndex) {
      org.apache.lucene.search.Query textQuery =
          generateQuery(
              query,
              sourceLocale,
              targetLocale,
              queryText,
              multiQueryText,
              IndexFieldLabels.TF_CONTENT_FIELDS,
              useTargetIndex);
      ftQuery = entityManager.createFullTextQuery(textQuery, HTextFlowTarget.class);
    } else {
      org.apache.lucene.search.Query textQuery =
          generateQuery(
              query,
              sourceLocale,
              targetLocale,
              queryText,
              multiQueryText,
              IndexFieldLabels.CONTENT_FIELDS,
              useTargetIndex);
      ftQuery = entityManager.createFullTextQuery(textQuery, HTextFlow.class);
      Filter filter = translationStateCacheImpl.getFilter(targetLocale);
      ftQuery.setFilter(filter);
    }

    ftQuery.setProjection(FullTextQuery.SCORE, FullTextQuery.THIS);
    @SuppressWarnings("unchecked")
    List<Object[]> matches = ftQuery.setMaxResults(maxResult).getResultList();
    return matches;
  }