/**
* License Agreement for OpenSearchServer
*
* Copyright (C) 2014-2015 Emmanuel Keller / Jaeksoft
*
* http://www.open-search-server.com
*
* This file is part of OpenSearchServer.
*
* OpenSearchServer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenSearchServer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenSearchServer.
* If not, see <http://www.gnu.org/licenses/>.
**/
package com.jaeksoft.searchlib.renderer.filter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.collections.CollectionUtils;
import com.jaeksoft.searchlib.facet.FacetCounter;
import com.jaeksoft.searchlib.query.ParseException;
import com.jaeksoft.searchlib.request.AbstractSearchRequest;
import com.jaeksoft.searchlib.util.StringUtils;
public class RendererFilterQueries {
final Map<String, Set<String>> filterTerms;
final Map<String, String> filterQueries;
public RendererFilterQueries() {
filterTerms = new TreeMap<String, Set<String>>();
filterQueries = new TreeMap<String, String>();
}
public Set<String> getTermSet(String fieldName) {
Set<String> queries = filterTerms.get(fieldName);
if (queries != null)
return queries;
queries = new TreeSet<String>();
filterTerms.put(fieldName, queries);
return queries;
}
public Set<String> getTermsFilterSet() {
return filterTerms.keySet();
}
public boolean isEmpty() {
for (String filterQuery : filterQueries.values())
if (!StringUtils.isEmpty(filterQuery))
return false;
for (Set<String> termSet : filterTerms.values())
if (!termSet.isEmpty())
return false;
return true;
}
public boolean isEmpty(String fieldName) {
Set<String> queries = filterTerms.get(fieldName);
if (queries == null)
return true;
return queries.isEmpty();
}
private void addTerm(String fieldName, String[] values) {
if (values == null)
return;
Set<String> queries = getTermSet(fieldName);
for (String value : values)
queries.add(value);
}
private void removeTerm(String fieldName, String[] values) {
if (values == null)
return;
Set<String> queries = getTermSet(fieldName);
for (String value : values)
queries.remove(value);
}
private void setQuery(String fieldName, String query) {
if (StringUtils.isEmpty(query))
filterQueries.remove(fieldName);
else
filterQueries.put(fieldName, query);
}
public void applyServletRequest(HttpServletRequest servletRequest) {
if (servletRequest.getParameter("fqc") != null) {
filterQueries.clear();
filterTerms.clear();
}
Enumeration<String> en = servletRequest.getParameterNames();
if (en != null) {
while (en.hasMoreElements()) {
String parm = en.nextElement();
if (parm.startsWith("fqa."))
addTerm(parm.substring(4),
servletRequest.getParameterValues(parm));
if (parm.startsWith("fqr."))
removeTerm(parm.substring(4),
servletRequest.getParameterValues(parm));
if (parm.startsWith("fq."))
setQuery(parm.substring(4),
servletRequest.getParameter(parm));
}
}
}
public void applyToSearchRequest(AbstractSearchRequest searchRequest)
throws ParseException {
for (Map.Entry<String, Set<String>> entry : filterTerms.entrySet()) {
String fieldName = entry.getKey();
Set<String> queries = entry.getValue();
if (CollectionUtils.isEmpty(queries))
continue;
if (queries.size() == 1) {
searchRequest.addTermFilter(fieldName, queries.iterator()
.next(), false);
continue;
}
StringBuilder sb = new StringBuilder(fieldName);
sb.append(":(");
boolean bFirst = true;
for (String query : queries) {
if (bFirst)
bFirst = false;
else
sb.append(" OR ");
sb.append('"');
sb.append(StringUtils.replace(query, "\"", "\\\""));
sb.append('"');
}
sb.append(')');
searchRequest.addFilter(sb.toString(), false);
}
for (String query : filterQueries.values())
searchRequest.addFilter(query, false);
}
private boolean contains(String fieldName, String query) {
if (query == null)
return false;
String q = filterQueries.get(fieldName);
if (q == null)
return false;
return q.equals(query);
}
private boolean containsAny(String fieldName, String term) {
if (term == null)
return false;
Set<String> termSet = filterTerms.get(fieldName);
if (termSet == null)
return false;
return termSet.contains(term);
}
private boolean containsAny(String fieldName, Collection<String> terms) {
if (terms == null)
return false;
Set<String> termSet = filterTerms.get(fieldName);
if (termSet == null)
return false;
for (String term : terms)
if (termSet.contains(term))
return true;
return false;
}
public boolean contains(String fieldName, RendererFilterItem filterItem) {
if (filterItem.isQuery())
return contains(fieldName, filterItem.getQuery());
if (filterItem.isTerms())
return containsAny(fieldName, filterItem.getTerms());
return false;
}
public boolean contains(String fieldName,
Map.Entry<String, FacetCounter> facetItem) {
return containsAny(fieldName, facetItem.getKey());
}
private StringBuilder append(StringBuilder sb, boolean current,
String fieldName, String term) throws UnsupportedEncodingException {
sb.append("&");
if (current)
sb.append("fqr.");
else
sb.append("fqa.");
sb.append(URLEncoder.encode(fieldName, "UTF-8"));
sb.append('=');
sb.append(URLEncoder.encode(term, "UTF-8"));
return sb;
}
private String getFilterParamQuery(boolean current, String fieldName,
String query) throws UnsupportedEncodingException {
if (query == null)
return StringUtils.EMPTY;
return StringUtils.fastConcat("&fq.",
URLEncoder.encode(fieldName, "UTF-8"), '=',
URLEncoder.encode(query, "UTF-8"));
}
public String getFilterClearParam(String fieldName)
throws UnsupportedEncodingException {
return StringUtils.fastConcat("&fqc.",
URLEncoder.encode(fieldName, "UTF-8"));
}
private String getFilterParam(boolean current, String fieldName,
Collection<String> terms) throws UnsupportedEncodingException {
if (terms == null)
return StringUtils.EMPTY;
StringBuilder sb = new StringBuilder();
for (String term : terms)
append(sb, current, fieldName, term);
return sb.toString();
}
public String getFilterParamTerm(boolean current, String fieldName,
String term) throws UnsupportedEncodingException {
if (term == null)
return StringUtils.EMPTY;
return append(new StringBuilder(), current, fieldName, term).toString();
}
public String getFilterParam(boolean current, String fieldName,
RendererFilterItem filterItem) throws UnsupportedEncodingException {
if (filterItem.isQuery())
return getFilterParamQuery(current, fieldName,
filterItem.getQuery());
if (filterItem.isTerms())
return getFilterParam(current, fieldName, filterItem.getTerms());
return StringUtils.EMPTY;
}
public String getFilterParam(boolean current, String fieldName,
Map.Entry<String, FacetCounter> facetItem)
throws UnsupportedEncodingException {
return getFilterParamTerm(current, fieldName, facetItem.getKey());
}
}