NIHVIVO-2425 Write autocomplete results to the response's writer directly without merging to a Freemarker template.
This commit is contained in:
parent
3745c37cc9
commit
12e68942fc
2 changed files with 54 additions and 45 deletions
|
@ -28,22 +28,22 @@ import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.TermQuery;
|
import org.apache.lucene.search.TermQuery;
|
||||||
import org.apache.lucene.search.TopDocs;
|
import org.apache.lucene.search.TopDocs;
|
||||||
import org.apache.lucene.search.WildcardQuery;
|
import org.apache.lucene.search.WildcardQuery;
|
||||||
|
import org.apache.lucene.util.Version;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
|
||||||
import com.hp.hpl.jena.sparql.lib.org.json.JSONObject;
|
import com.hp.hpl.jena.sparql.lib.org.json.JSONObject;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.ajax.VitroAjaxController;
|
import edu.cornell.mannlib.vitro.webapp.controller.ajax.VitroAjaxController;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.flags.PortalFlag;
|
import edu.cornell.mannlib.vitro.webapp.flags.PortalFlag;
|
||||||
import edu.cornell.mannlib.vitro.webapp.search.SearchException;
|
import edu.cornell.mannlib.vitro.webapp.search.SearchException;
|
||||||
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc.VitroLuceneTermNames;
|
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc.VitroLuceneTermNames;
|
||||||
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory;
|
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneSetup;
|
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneSetup;
|
||||||
import freemarker.template.Configuration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AutocompleteController is used to generate autocomplete content
|
* AutocompleteController generates autocomplete content
|
||||||
* through a Lucene search.
|
* through a Lucene search.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Log log = LogFactory.getLog(AutocompleteController.class);
|
private static final Log log = LogFactory.getLog(AutocompleteController.class);
|
||||||
|
|
||||||
private static final String TEMPLATE_DEFAULT = "autocompleteResults.ftl";
|
//private static final String TEMPLATE_DEFAULT = "autocompleteResults.ftl";
|
||||||
|
|
||||||
private static String QUERY_PARAMETER_NAME = "term";
|
private static String QUERY_PARAMETER_NAME = "term";
|
||||||
|
|
||||||
|
@ -69,9 +69,6 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
protected void doRequest(VitroRequest vreq, HttpServletResponse response)
|
protected void doRequest(VitroRequest vreq, HttpServletResponse response)
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
|
|
||||||
Configuration config = getFreemarkerConfiguration(vreq);
|
|
||||||
PortalFlag portalFlag = vreq.getPortalFlag();
|
PortalFlag portalFlag = vreq.getPortalFlag();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -84,7 +81,7 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
Query query = getQuery(vreq, portalFlag, analyzer, qtxt);
|
Query query = getQuery(vreq, portalFlag, analyzer, qtxt);
|
||||||
if (query == null ) {
|
if (query == null ) {
|
||||||
log.debug("query for '" + qtxt +"' is null.");
|
log.debug("query for '" + qtxt +"' is null.");
|
||||||
doNoQuery(map, config, vreq, response);
|
doNoQuery(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.debug("query for '" + qtxt +"' is " + query.toString());
|
log.debug("query for '" + qtxt +"' is " + query.toString());
|
||||||
|
@ -100,22 +97,22 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
try{
|
try{
|
||||||
wait(150);
|
wait(150);
|
||||||
topDocs = searcherForRequest.search(query,null,maxHitSize);
|
topDocs = searcherForRequest.search(query,null,maxHitSize);
|
||||||
}catch (Exception ex){
|
}catch (Exception e){
|
||||||
log.error(ex);
|
log.error(e, e);
|
||||||
doFailedSearch(map, config, vreq, response);
|
doNoSearchResults(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( topDocs == null || topDocs.scoreDocs == null){
|
if( topDocs == null || topDocs.scoreDocs == null){
|
||||||
log.error("topDocs for a search was null");
|
log.error("topDocs for a search was null");
|
||||||
doFailedSearch(map, config, vreq, response);
|
doNoSearchResults(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hitsLength = topDocs.scoreDocs.length;
|
int hitsLength = topDocs.scoreDocs.length;
|
||||||
if ( hitsLength < 1 ){
|
if ( hitsLength < 1 ){
|
||||||
doFailedSearch(map, config, vreq, response);
|
doNoSearchResults(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.debug("found "+hitsLength+" hits");
|
log.debug("found "+hitsLength+" hits");
|
||||||
|
@ -135,18 +132,20 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(results);
|
Collections.sort(results);
|
||||||
map.put("results", results);
|
|
||||||
writeTemplate(TEMPLATE_DEFAULT, map, config, vreq, response);
|
|
||||||
|
|
||||||
} catch (TemplateProcessingException e) {
|
// map.put("results", results);
|
||||||
log.error(e, e);
|
// writeTemplate(TEMPLATE_DEFAULT, map, config, vreq, response);
|
||||||
} catch (Throwable e) {
|
|
||||||
log.error("AutocompleteController(): " + e);
|
JSONArray jsonArray = new JSONArray();
|
||||||
try {
|
for (SearchResult result : results) {
|
||||||
doSearchError(map, config, vreq, response);
|
jsonArray.put(result.toMap());
|
||||||
} catch (TemplateProcessingException e1) {
|
|
||||||
log.error(e1.getMessage(), e1);
|
|
||||||
}
|
}
|
||||||
|
response.getWriter().write(jsonArray.toString());
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error(e, e);
|
||||||
|
doSearchError(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,27 +264,26 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
// indicated in the query string.
|
// indicated in the query string.
|
||||||
// The analyzer is needed so that we use the same analyzer on the search queries as
|
// The analyzer is needed so that we use the same analyzer on the search queries as
|
||||||
// was used on the text that was indexed.
|
// was used on the text that was indexed.
|
||||||
QueryParser qp = new QueryParser(searchField,analyzer);
|
QueryParser qp = new QueryParser(Version.LUCENE_29, searchField,analyzer);
|
||||||
//this sets the query parser to AND all of the query terms it finds.
|
//this sets the query parser to AND all of the query terms it finds.
|
||||||
qp.setDefaultOperator(QueryParser.AND_OPERATOR);
|
qp.setDefaultOperator(QueryParser.AND_OPERATOR);
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doNoQuery(Map<String, Object> map, Configuration config, HttpServletRequest request,
|
private void doNoQuery(HttpServletResponse response) throws IOException {
|
||||||
HttpServletResponse response) throws TemplateProcessingException {
|
|
||||||
writeTemplate(TEMPLATE_DEFAULT, map, config, request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doFailedSearch(Map<String, Object> map, Configuration config, HttpServletRequest request,
|
|
||||||
HttpServletResponse response) throws TemplateProcessingException {
|
|
||||||
writeTemplate(TEMPLATE_DEFAULT, map, config, request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doSearchError(Map<String, Object> map, Configuration config, HttpServletRequest request,
|
|
||||||
HttpServletResponse response) throws TemplateProcessingException {
|
|
||||||
// For now, we are not sending an error message back to the client because with the default autocomplete configuration it
|
// For now, we are not sending an error message back to the client because with the default autocomplete configuration it
|
||||||
// chokes.
|
// chokes.
|
||||||
writeTemplate(TEMPLATE_DEFAULT, map, config, request, response);
|
doNoSearchResults(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doSearchError(HttpServletResponse response) throws IOException {
|
||||||
|
// For now, we are not sending an error message back to the client because with the default autocomplete configuration it
|
||||||
|
// chokes.
|
||||||
|
doNoSearchResults(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doNoSearchResults(HttpServletResponse response) throws IOException {
|
||||||
|
response.getWriter().write("[]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int MAX_QUERY_LENGTH = 500;
|
public static final int MAX_QUERY_LENGTH = 500;
|
||||||
|
@ -295,20 +293,31 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
private String uri;
|
private String uri;
|
||||||
|
|
||||||
SearchResult(String label, String uri) {
|
SearchResult(String label, String uri) {
|
||||||
this.label = JSONObject.quote(label);
|
this.label = label;
|
||||||
this.uri = JSONObject.quote(uri);
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getJsonLabel() {
|
||||||
|
return JSONObject.quote(label);
|
||||||
|
}
|
||||||
|
|
||||||
public String getUri() {
|
public String getUri() {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getJson() {
|
public String getJsonUri() {
|
||||||
return "{ \"label\": \"" + label + "\", " + "\"uri\": \"" + uri + "\" }";
|
return JSONObject.quote(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> toMap() {
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
map.put("label", label);
|
||||||
|
map.put("uri", uri);
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(Object o) throws ClassCastException {
|
public int compareTo(Object o) throws ClassCastException {
|
||||||
|
@ -316,7 +325,7 @@ public class AutocompleteController extends VitroAjaxController {
|
||||||
throw new ClassCastException("Error in SearchResult.compareTo(): expected SearchResult object.");
|
throw new ClassCastException("Error in SearchResult.compareTo(): expected SearchResult object.");
|
||||||
}
|
}
|
||||||
SearchResult sr = (SearchResult) o;
|
SearchResult sr = (SearchResult) o;
|
||||||
return label.compareTo(sr.getLabel());
|
return label.compareToIgnoreCase(sr.getLabel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
[
|
[
|
||||||
<#if results??>
|
<#if results??>
|
||||||
<#list results as result>
|
<#list results as result>
|
||||||
<#-- result.label and result.uri are already quoted -->
|
<#-- result.jsonLabel and result.jsonUri are already quoted -->
|
||||||
{ "label": ${result.label}, "uri": ${result.uri} }<#if result_has_next>,</#if>
|
{ "label": ${result.jsonLabel}, "uri": ${result.jsonUri} }<#if result_has_next>,</#if>
|
||||||
</#list>
|
</#list>
|
||||||
</#if>
|
</#if>
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Reference in a new issue