/** | |
* | |
*/ | |
package org.eclipse.smila.solr; | |
import java.io.UnsupportedEncodingException; | |
import java.net.URLDecoder; | |
import java.net.URLEncoder; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Map.Entry; | |
import org.apache.commons.collections.MapUtils; | |
import org.apache.commons.lang.NotImplementedException; | |
import org.apache.commons.lang.NullArgumentException; | |
import org.apache.commons.lang.StringUtils; | |
import org.apache.solr.client.solrj.response.SolrResponseBase; | |
import org.apache.solr.common.util.NamedList; | |
import org.eclipse.smila.datamodel.Any; | |
import org.eclipse.smila.datamodel.AnyMap; | |
import org.eclipse.smila.datamodel.AnySeq; | |
import org.eclipse.smila.datamodel.DataFactory; | |
import org.eclipse.smila.datamodel.InvalidValueTypeException; | |
import org.eclipse.smila.datamodel.Value; | |
import org.eclipse.smila.datamodel.util.AnyUtil; | |
import org.eclipse.smila.solr.query.QueryStringConstants; | |
/** | |
* @author pwissel | |
* | |
*/ | |
public class SolrUtils { | |
public static final String ESCAPE_CHARS = "+-&|!(){}[]^~*?:\\\"/"; | |
public static final String ESCAPE_CHARS_WS = ESCAPE_CHARS + QueryStringConstants.WHITESPACE; | |
/** The query wrapper filter string. */ | |
public static final String QUERY_WRAPPER_FILTER = "QueryWrapperFilter"; | |
public enum LocalParamsMode { | |
ADD, OVERWRITE, IGNORE; | |
} | |
/** | |
* | |
*/ | |
private SolrUtils() { | |
// prevent instance creation | |
} | |
public static boolean isErrorResponse(final SolrResponseBase response) { | |
return response.getStatus() != 0; | |
} | |
public static String escape(final String string) { | |
return escape(string, ESCAPE_CHARS); | |
} | |
public static String escapeWS(final String string) { | |
return escape(string, ESCAPE_CHARS_WS); | |
} | |
public static String escape(final String string, String escapeChars) { | |
if (StringUtils.isEmpty(string)) { | |
return string; | |
} | |
final int length = string.length(); | |
final StringBuilder buf = new StringBuilder(length * 2); | |
for (int i = 0; i < length; i++) { | |
final char ch = string.charAt(i); | |
if (escapeChars.indexOf(ch) >= 0) { | |
buf.append('\\'); | |
} | |
buf.append(ch); | |
} | |
if (buf.length() != string.length()) { | |
return buf.toString(); | |
} | |
return string; | |
} | |
public static String getPerFieldParameter(final String fieldName, final String parameterName) { | |
return new StringBuilder(SolrConstants.PER_FIELD).append(QueryStringConstants.PERIOT).append(fieldName) | |
.append(QueryStringConstants.PERIOT).append(parameterName).toString(); | |
} | |
public static StringBuilder writeLocalParams(final AnyMap localParams) { | |
return writeLocalParams(new StringBuilder(), localParams); | |
} | |
public static StringBuilder writeLocalParams(final StringBuilder sb, final AnyMap localParams) { | |
if (sb == null) { | |
throw new NullArgumentException("sb"); | |
} | |
if (MapUtils.isEmpty(localParams)) { | |
return sb; | |
} | |
// open localParams -> {! | |
sb.append(QueryStringConstants.BRACKET_CURLY_OPEN); | |
sb.append(QueryStringConstants.EXCLAMATION_MARK); | |
// append all key value pairs followed by space | |
for (final Entry<String, Any> localParam : localParams.entrySet()) { | |
final String key = localParam.getKey(); | |
sb.append(key); | |
sb.append(QueryStringConstants.EQUAL); | |
final Any value = localParam.getValue(); | |
String val = null; | |
if (value.isValue()) { | |
val = value.asValue().asString(); | |
} else if (value.isSeq()) { | |
final List<String> vals = value.asSeq().asStrings(); | |
val = StringUtils.join(vals, QueryStringConstants.COMMA); | |
} | |
sb.append(val); | |
sb.append(QueryStringConstants.WHITESPACE); | |
} | |
// remove the last space and close localParams -> } | |
sb.deleteCharAt(sb.length() - 1); | |
sb.append(QueryStringConstants.BRACKET_CURLY_CLOSE); | |
return sb; | |
} | |
public static StringBuilder addLocalParams(final String value, final AnyMap localParams) { | |
final StringBuilder sb = writeLocalParams(localParams); | |
return sb.append(value); | |
} | |
public static AnyMap putLocalParam(final AnyMap config, final String param, final String value, | |
final boolean create) { | |
return putLocalParam(config, param, value, create, LocalParamsMode.IGNORE); | |
} | |
public static AnyMap putLocalParam(final AnyMap config, final String param, final String value, | |
final boolean create, final LocalParamsMode mode) { | |
if (config == null) { | |
throw new NullArgumentException("config"); | |
} | |
if (param == null) { | |
throw new NullArgumentException("param"); | |
} | |
final AnyMap localParams = config.getMap(SolrConstants.LOCAL_PARAMS, create); | |
if (localParams != null) { | |
switch (mode) { | |
case ADD: | |
final Value val = DataFactory.DEFAULT.autoConvertValue(value); | |
localParams.add(param, val); | |
break; | |
case OVERWRITE: | |
localParams.put(param, value); | |
break; | |
case IGNORE: | |
if (!localParams.containsKey(param)) { | |
localParams.put(param, value); | |
} | |
break; | |
default: | |
throw new NotImplementedException(mode.toString()); | |
} | |
} | |
return localParams; | |
} | |
public static AnyMap parseNamedList(final NamedList<?> list) { | |
final AnyMap target = DataFactory.DEFAULT.createAnyMap(); | |
SolrUtils.parseNamedList(list, target); | |
return target; | |
} | |
public static void parseNamedList(final NamedList<?> list, final AnyMap target) { | |
SolrUtils.parseNamedList(list, target, target.getFactory()); | |
} | |
public static void parseNamedList(final NamedList<?> list, final AnyMap target, final DataFactory factory) { | |
if (target == null) { | |
return; | |
} | |
for (int i = 0; i < list.size(); i++) { | |
final String name = list.getName(i); | |
final Object obj = list.getVal(i); | |
if (obj instanceof NamedList<?>) { | |
final NamedList<?> sub = (NamedList<?>) obj; | |
final AnyMap child = target.getMap(name, true); | |
parseNamedList(sub, child, factory); | |
} else if (obj instanceof ArrayList<?>) { | |
final ArrayList<?> sub = (ArrayList<?>) obj; | |
final AnySeq child = target.getSeq(name, true); | |
SolrUtils.parseArrayList(sub, child, factory); | |
} else { | |
try { | |
final Any value = AnyUtil.objectToAny(obj); | |
target.put(name, value); | |
} catch (InvalidValueTypeException exception) { | |
; // ignore | |
} | |
} | |
} | |
} | |
public static void parseArrayList(final ArrayList<?> list, final AnySeq target, final DataFactory factory) { | |
if (target == null || factory == null) { | |
return; | |
} | |
for (Object obj : list) { | |
if (obj instanceof NamedList<?>) { | |
final NamedList<?> sub = (NamedList<?>) obj; | |
final AnyMap child = factory.createAnyMap(); | |
target.add(child); | |
parseNamedList(sub, child, factory); | |
} else if (obj instanceof ArrayList<?>) { | |
final ArrayList<?> sub = (ArrayList<?>) obj; | |
final AnySeq child = factory.createAnySeq(); | |
target.add(child); | |
parseArrayList(sub, child, factory); | |
} else { | |
try { | |
final Any value = AnyUtil.objectToAny(obj); | |
target.add(value); | |
} catch (InvalidValueTypeException exception) { | |
; // ignore | |
} | |
} | |
} | |
} | |
/** | |
* Convert a lucene QueryWrapperFilter to a query filter for solr. | |
* | |
* @param luceneFilter | |
* the filter. | |
* @return the solr query filter. | |
*/ | |
public static String getSolrQueryFilter(String luceneFilter) { | |
luceneFilter = StringUtils.remove(luceneFilter, QUERY_WRAPPER_FILTER); | |
luceneFilter = StringUtils.replace(luceneFilter, "\\", "\\\\"); | |
return luceneFilter; | |
} | |
/** | |
* return 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 solr query string | |
*/ | |
public static String getConstQueryOnField(String fieldName, String constant) { | |
return fieldName + ":\"" + escape(constant) + '"'; | |
} | |
/** | |
* returns an escaped query string of the form {@code (<field>:<token>)}. The given token is fully escaped, i.e. | |
* including spaces. | |
* | |
* @param fieldName | |
* must not contain whitespace, but this is not checked! | |
* @param token | |
* the search token | |
* @return the solr query string | |
*/ | |
public static String getTokenQueryOnField(String fieldName, String token) { | |
return "(" + fieldName + ":" + escape(token, ESCAPE_CHARS_WS) + ')'; | |
} | |
/** | |
* 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"); | |
} | |
/** | |
* decode a query from application/x-www-form-urlencoded format. | |
* | |
* @param query | |
* the query. | |
* @return the urlencoded query. | |
* @throws UnsupportedEncodingException | |
* UnsupportedEncodingException. | |
*/ | |
public static String decodeQuery(String query) throws UnsupportedEncodingException { | |
return URLDecoder.decode(query, "UTF-8"); | |
} | |
} |