/********************************************************************************************************************* | |
* Copyright (c) 2008, 2012 Attensity Europe GmbH and brox IT Solutions GmbH. All rights reserved. This program and the | |
* accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this | |
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: Andreas Weber (Attensity Europe GmbH), Thomas Menzel (brox IT Solution GmbH) - initial implementation | |
**********************************************************************************************************************/ | |
package org.eclipse.smila.solr.util; | |
import static org.apache.commons.lang.StringUtils.isEmpty; | |
import java.io.UnsupportedEncodingException; | |
import java.net.URLDecoder; | |
import java.net.URLEncoder; | |
import java.util.List; | |
import org.apache.commons.lang.StringUtils; | |
import org.apache.solr.client.solrj.SolrServerException; | |
import org.apache.solr.client.solrj.response.SolrResponseBase; | |
import org.eclipse.smila.datamodel.Value; | |
/** Provide extensions/simplifications for handling SolrQuery. */ | |
public final class SolrQueryUtils { | |
/** Lucene/Solr operator for OR query parts. */ | |
public static final String OR_SEPARATOR = " "; | |
/** The query wrapper filter string. */ | |
public static final String QUERY_WRAPPER_FILTER = "QueryWrapperFilter"; | |
/** chars, that if part of a term need to be escaped when searching. */ | |
public static final String ESCAPE_CHARS = "+-&|!(){}[]^~*?:\\\""; | |
/** chars, that if part of a term need to be escaped when searching. including space */ | |
public static final String ESCAPE_CHARS_WS = ESCAPE_CHARS + " "; | |
/** avoid instatiiation. */ | |
private SolrQueryUtils() { | |
} | |
/** | |
* @param q | |
* the query to add the field query part to. | |
* @param field | |
* the field name to add the query part for | |
* @param values | |
* the field value alternatives to match in the search | |
*/ | |
public static void appendFieldQueryPart(final StringBuilder q, final String field, final List<Value> values) { | |
if (field != null && values != null && !(values.isEmpty())) { | |
if (q.length() > 0) { | |
q.append(OR_SEPARATOR); | |
} | |
q.append(field).append(':'); | |
if (values.size() > 1) { | |
final StringBuilder multiValue = new StringBuilder(); | |
multiValue.append("("); | |
for (final Value v : values) { | |
if (multiValue.length() > 1) { | |
multiValue.append(OR_SEPARATOR); | |
} | |
multiValue.append(v); | |
} | |
multiValue.append(")"); | |
q.append(multiValue); | |
} else { | |
q.append(values.get(0)); | |
} | |
} | |
} | |
/** | |
* Encode a query into application/x-www-form-urlencoded format. | |
* | |
* @param query | |
* the query. | |
* @return the urlencoded query. | |
* @throws UnsupportedEncodingException | |
* UnsupportedEncodingException. | |
*/ | |
public static String encodeQuery(String query) throws UnsupportedEncodingException { | |
return URLEncoder.encode(query, "UTF-8"); | |
} | |
public static String decodeQuery(String query) throws UnsupportedEncodingException { | |
return URLDecoder.decode(query, "UTF-8"); | |
} | |
/** | |
* Escapes all chars with a special meaning to the lucene query parser. Spaces are not escaped. | |
* | |
* @param query | |
* the query. | |
* @return the query after escaping. | |
* @see SolrQueryUtils#ESCAPE_CHARS | |
* @see SolrQueryUtils# toConstQueryOnField(String, String) | |
*/ | |
public static String escapeQuery(String query) { | |
return escapeQuery(query, ESCAPE_CHARS); | |
} | |
/** | |
* Escapes the given chars in the given query by prepending '\'. | |
* | |
* @param query | |
* the query, if empty nothing happens and it is returned as is. | |
* @param escapeChars | |
* the chars to escape | |
* @return the string | |
*/ | |
public static String escapeQuery(String query, final String escapeChars) { | |
/* NOTE: this method has been impl'ed in regard to performance | tmenzel @ May 23, 2011 */ | |
if (isEmpty(query)) { | |
return query; | |
} | |
final int strLength = query.length(); | |
final StringBuilder buf = new StringBuilder(strLength * 2); // can only get twice as big thru injecting '\' | |
for (int i = 0; i < strLength; i++) { | |
final char ch = query.charAt(i); | |
if (escapeChars.indexOf(ch) >= 0) { | |
buf.append('\\'); | |
} | |
buf.append(ch); | |
} | |
if (buf.length() != query.length()) { | |
return buf.toString(); | |
} | |
return query; | |
} | |
/** | |
* returns true if response indicates an error. | |
* | |
* @see http://lucene.472066.n3.nabble.com/Response-status-td490876.html | |
*/ | |
public static boolean responseStatusIsError(final SolrResponseBase response) throws SolrServerException { | |
return response.getStatus() != 0; | |
} | |
/** | |
* Convert a lucene QueryWrapperFilter to a query filter for solr. | |
* | |
* @param filter | |
* the filter. | |
* @return the solr query filter. | |
*/ | |
public static String toSolrQueryFilter(String filter) { | |
filter = StringUtils.remove(filter, QUERY_WRAPPER_FILTER); | |
filter = StringUtils.replace(filter, "\\", "\\\\"); | |
return filter; | |
} | |
/** | |
* creates a query string on the given field for a constant which must be searched "as is", i.e. escaping fo chars and | |
* wrapping in quotes | |
* | |
* @param fieldName | |
* must not contain whitespace, but this is not checked! | |
* @param constant | |
* the constant | |
* @return the lucen query string | |
*/ | |
public static String toConstQueryOnField(String fieldName, String constant) { | |
return fieldName + ":\"" + escapeQuery(constant) + '"'; | |
} | |
/** | |
* returns an escaped query string of the form {@code (<field>:<token>)}. The given token is fully escaped, i.e. | |
* including spaces. | |
* | |
* | |
*/ | |
public static String toTokenQueryOnField(String fieldName, String token) { | |
return "(" + fieldName + ":" + escapeQuery(token, ESCAPE_CHARS_WS) + ')'; | |
} | |
} |