/*
* Copyright 2015 Hewlett-Packard Development Company, L.P.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
*/
package com.hp.autonomy.frontend.find.core.search;
import com.hp.autonomy.searchcomponents.core.search.DocumentsService;
import com.hp.autonomy.searchcomponents.core.search.GetContentRequest;
import com.hp.autonomy.searchcomponents.core.search.GetContentRequestBuilder;
import com.hp.autonomy.searchcomponents.core.search.GetContentRequestIndex;
import com.hp.autonomy.searchcomponents.core.search.GetContentRequestIndexBuilder;
import com.hp.autonomy.searchcomponents.core.search.QueryRequest;
import com.hp.autonomy.searchcomponents.core.search.QueryRequestBuilder;
import com.hp.autonomy.searchcomponents.core.search.QueryRestrictions;
import com.hp.autonomy.searchcomponents.core.search.QueryRestrictionsBuilder;
import com.hp.autonomy.searchcomponents.core.search.SearchResult;
import com.hp.autonomy.searchcomponents.core.search.SuggestRequest;
import com.hp.autonomy.searchcomponents.core.search.SuggestRequestBuilder;
import com.hp.autonomy.types.requests.Documents;
import org.apache.commons.collections4.ListUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.Serializable;
import java.util.List;
@Controller
@RequestMapping(DocumentsController.SEARCH_PATH)
public abstract class DocumentsController<RQ extends QueryRequest<Q>, RS extends SuggestRequest<Q>, RC extends GetContentRequest<T>, S extends Serializable, Q extends QueryRestrictions<S>, T extends GetContentRequestIndex<S>, R extends SearchResult, E extends Exception> {
public static final String SEARCH_PATH = "/api/public/search";
public static final String QUERY_PATH = "query-text-index/results";
public static final String TEXT_PARAM = "text";
public static final String RESULTS_START_PARAM = "start";
public static final String MAX_RESULTS_PARAM = "max_results";
public static final String SUMMARY_PARAM = "summary";
public static final String INDEXES_PARAM = "indexes";
public static final int MAX_SUMMARY_CHARACTERS = 250;
static final String SIMILAR_DOCUMENTS_PATH = "similar-documents";
static final String GET_DOCUMENT_CONTENT_PATH = "get-document-content";
static final String REFERENCE_PARAM = "reference";
static final String AUTO_CORRECT_PARAM = "auto_correct";
static final String QUERY_TYPE_PARAM = "queryType";
static final String DATABASE_PARAM = "database";
private static final String FIELD_TEXT_PARAM = "field_text";
private static final String SORT_PARAM = "sort";
private static final String MIN_DATE_PARAM = "min_date";
private static final String MAX_DATE_PARAM = "max_date";
private static final String HIGHLIGHT_PARAM = "highlight";
private static final String MIN_SCORE_PARAM = "min_score";
protected final DocumentsService<RQ, RS, RC, Q, R, E> documentsService;
private final ObjectFactory<? extends QueryRestrictionsBuilder<Q, S, ?>> queryRestrictionsBuilderFactory;
private final ObjectFactory<? extends QueryRequestBuilder<RQ, Q, ?>> queryRequestBuilderFactory;
private final ObjectFactory<? extends SuggestRequestBuilder<RS, Q, ?>> suggestRequestBuilderFactory;
private final ObjectFactory<? extends GetContentRequestBuilder<RC, T, ?>> getContentRequestBuilderFactory;
private final ObjectFactory<? extends GetContentRequestIndexBuilder<T, S, ?>> getContentRequestIndexBuilderFactory;
@SuppressWarnings("ConstructorWithTooManyParameters")
protected DocumentsController(final DocumentsService<RQ, RS, RC, Q, R, E> documentsService,
final ObjectFactory<? extends QueryRestrictionsBuilder<Q, S, ?>> queryRestrictionsBuilderFactory,
final ObjectFactory<? extends QueryRequestBuilder<RQ, Q, ?>> queryRequestBuilderFactory,
final ObjectFactory<? extends SuggestRequestBuilder<RS, Q, ?>> suggestRequestBuilderFactory,
final ObjectFactory<? extends GetContentRequestBuilder<RC, T, ?>> getContentRequestBuilderFactory,
final ObjectFactory<? extends GetContentRequestIndexBuilder<T, S, ?>> getContentRequestIndexBuilderFactory) {
this.documentsService = documentsService;
this.queryRestrictionsBuilderFactory = queryRestrictionsBuilderFactory;
this.queryRequestBuilderFactory = queryRequestBuilderFactory;
this.suggestRequestBuilderFactory = suggestRequestBuilderFactory;
this.getContentRequestBuilderFactory = getContentRequestBuilderFactory;
this.getContentRequestIndexBuilderFactory = getContentRequestIndexBuilderFactory;
}
protected abstract <EX> EX throwException(final String message) throws E;
protected abstract void addParams(final GetContentRequestBuilder<RC, T, ?> request);
@SuppressWarnings("MethodWithTooManyParameters")
@RequestMapping(value = QUERY_PATH, method = RequestMethod.GET)
@ResponseBody
public Documents<R> query(
@RequestParam(TEXT_PARAM) final String queryText,
@RequestParam(value = RESULTS_START_PARAM, defaultValue = "1") final int resultsStart,
@RequestParam(MAX_RESULTS_PARAM) final int maxResults,
@RequestParam(SUMMARY_PARAM) final String summary,
@RequestParam(value = INDEXES_PARAM, required = false) final List<S> databases,
@RequestParam(value = FIELD_TEXT_PARAM, defaultValue = "") final String fieldText,
@RequestParam(value = SORT_PARAM, required = false) final String sort,
@RequestParam(value = MIN_DATE_PARAM, required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) final DateTime minDate,
@RequestParam(value = MAX_DATE_PARAM, required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) final DateTime maxDate,
@RequestParam(value = HIGHLIGHT_PARAM, defaultValue = "true") final boolean highlight,
@RequestParam(value = MIN_SCORE_PARAM, defaultValue = "0") final int minScore,
@RequestParam(value = AUTO_CORRECT_PARAM, defaultValue = "true") final boolean autoCorrect,
@RequestParam(value = QUERY_TYPE_PARAM, defaultValue = "MODIFIED") final String queryType
) throws E {
final Q queryRestrictions = queryRestrictionsBuilderFactory.getObject()
.queryText(queryText)
.fieldText(fieldText)
.databases(ListUtils.emptyIfNull(databases))
.minDate(minDate)
.maxDate(maxDate)
.minScore(minScore)
.build();
final RQ queryRequest = queryRequestBuilderFactory.getObject()
.queryRestrictions(queryRestrictions)
.start(resultsStart)
.maxResults(maxResults)
.summaryCharacters(MAX_SUMMARY_CHARACTERS)
.highlight(highlight)
.autoCorrect(autoCorrect)
.summary(summary)
.sort(sort)
.queryType(QueryRequest.QueryType.valueOf(queryType))
.build();
return documentsService.queryTextIndex(queryRequest);
}
@SuppressWarnings("MethodWithTooManyParameters")
@RequestMapping(value = SIMILAR_DOCUMENTS_PATH, method = RequestMethod.GET)
@ResponseBody
public Documents<R> findSimilar(
@RequestParam(REFERENCE_PARAM) final String reference,
@RequestParam(value = RESULTS_START_PARAM, defaultValue = "1") final int resultsStart,
@RequestParam(MAX_RESULTS_PARAM) final int maxResults,
@RequestParam(SUMMARY_PARAM) final String summary,
@RequestParam(value = INDEXES_PARAM, required = false) final List<S> databases,
@RequestParam(value = FIELD_TEXT_PARAM, defaultValue = "") final String fieldText,
@RequestParam(value = SORT_PARAM, required = false) final String sort,
@RequestParam(value = MIN_DATE_PARAM, required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) final DateTime minDate,
@RequestParam(value = MAX_DATE_PARAM, required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) final DateTime maxDate,
@RequestParam(value = HIGHLIGHT_PARAM, defaultValue = "true") final boolean highlight,
@RequestParam(value = MIN_SCORE_PARAM, defaultValue = "0") final int minScore
) throws E {
final Q queryRestrictions = queryRestrictionsBuilderFactory.getObject()
.fieldText(fieldText)
.databases(ListUtils.emptyIfNull(databases))
.minDate(minDate)
.maxDate(maxDate)
.minScore(minScore)
.build();
final RS suggestRequest = suggestRequestBuilderFactory.getObject()
.reference(reference)
.queryRestrictions(queryRestrictions)
.start(resultsStart)
.maxResults(maxResults)
.summaryCharacters(MAX_SUMMARY_CHARACTERS)
.highlight(highlight)
.summary(summary)
.sort(sort)
.build();
return documentsService.findSimilar(suggestRequest);
}
@RequestMapping(value = GET_DOCUMENT_CONTENT_PATH, method = RequestMethod.GET)
@ResponseBody
public R getDocumentContent(
@RequestParam(REFERENCE_PARAM) final String reference,
@RequestParam(DATABASE_PARAM) final S database
) throws E {
final T getContentRequestIndex = getContentRequestIndexBuilderFactory.getObject()
.index(database)
.reference(reference)
.build();
final GetContentRequestBuilder<RC, T, ?> requestBuilder = getContentRequestBuilderFactory.getObject()
.indexAndReferences(getContentRequestIndex);
addParams(requestBuilder);
final RC getContentRequest = requestBuilder.build();
final List<R> results = documentsService.getDocumentContent(getContentRequest);
return results.isEmpty() ? throwException("No content found for document with reference " + reference + " in database " + database) : results.get(0);
}
}