blob: a399d20138dca481980a8b46d034ac1ba590a651 [file] [log] [blame]
/**
*
*/
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");
}
}