package monty.solr.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.flexible.aqp.AqpTestAbstractCase;
import org.apache.lucene.search.Query;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.QParser;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SyntaxError;
import org.getopt.luke.DocReconstructor;
import org.getopt.luke.DocReconstructor.Reconstructed;
import org.getopt.luke.GrowableStringArray;
import org.junit.BeforeClass;
public class MontySolrQueryTestCase extends MontySolrAbstractTestCase {
protected static AqpTestAbstractCase tp = new AqpTestAbstractCase() {
@Override
public void setUp() throws Exception {
super.setUp();
}
@Override
public void tearDown() throws Exception {
super.tearDown();
}
};
private int idValue = 0;
@Override
public void setUp() throws Exception {
super.setUp();
tp.setUp();
}
@Override
public void tearDown() throws Exception {
tp.tearDown();
super.tearDown();
}
public QParser getParser(SolrQueryRequest req) throws SyntaxError, InstantiationException, IllegalAccessException, SecurityException, IllegalArgumentException, NoSuchMethodException, InvocationTargetException {
SolrParams params = req.getParams();
String query = params.get(CommonParams.Q);
String defType = params.get(QueryParsing.DEFTYPE);
QParser qParser = QParser.getParser(query, defType, req);
// if of type AqpQueryParser - set the debug
try {
Class<? extends QParser> clazz = qParser.getClass();
Method getParser = clazz.getDeclaredMethod("getParser");
if (getParser != null) {
Method setDebug = getParser.getReturnType().getDeclaredMethod("setDebug", boolean.class);
Object arglist[] = new Object[1];
arglist[0] = this.tp.debugParser;
Object parser = getParser.invoke(qParser);
setDebug.invoke(parser, arglist);
}
}
catch (Exception e){
// pass
}
return qParser;
}
public static SolrQueryRequest req(String... q) {
boolean clean = true;
for (String x: q) {
if (q.equals("debugQuery")) {
clean = false;
}
}
if (clean) {
String[] nq = new String[q.length+2];
int i =0;
for (;i<q.length;i++) {
nq[i] = q[i];
}
nq[i++] = "debugQuery";
nq[i++] = tp.debugParser ? "true" : "false";
q = nq;
}
return SolrTestCaseJ4.req(q);
}
public Query assertQueryEquals(SolrQueryRequest req, String expected, Class<?> clazz)
throws Exception {
QParser qParser = getParser(req);
String query = req.getParams().get(CommonParams.Q);
Query q = qParser.parse();
String actual = q.toString("field");
if (!actual.equals(expected)) {
tp.debugFail(query, expected, actual);
}
if (clazz != null) {
if (!q.getClass().isAssignableFrom(clazz)) {
tp.debugFail(actual, expected, "Query is not: " + clazz + " but: " + q.getClass() + q.toString());
}
}
return q;
}
public void assertQueryParseException(SolrQueryRequest req) throws Exception {
try {
getParser(req).parse();
} catch (SyntaxError expected) {
return;
}
tp.debugFail("ParseException expected, not thrown");
}
public void setDebug(boolean v) {
tp.setDebug(v);
}
/*
* This is only for printing/debugging, DO NOT use this for testing!!!
* This method can go away
*/
public void dumpDoc(Integer docId, String...fields) throws Exception {
//DirectoryReader reader = h.getCore().getSearcher().get().getIndexReader();
SolrQueryRequest sr = req();
//IndexReader reader = req.getSearcher().getIndexReader();
IndexReader reader = sr.getSearcher().getTopReaderContext().reader();
int[] docs;
if (docId == null) {
docs = new int[reader.numDocs()];
for (int i=0;i<docs.length;i++) {
docs[i] = i;
}
}
else {
docs = new int[]{docId};
}
DocReconstructor reconstructor = new DocReconstructor(reader, fields, 10);
Reconstructed d;
for (Integer dd: docs) {
System.out.println("===========================");
d = reconstructor.reconstruct(dd);
Set<String> fldMap = new HashSet<String>();
for (String f: fields) {
fldMap.add(f);
}
System.out.println("STORED FIELDS: " + dd);
Map<String, IndexableField[]> sf = d.getStoredFields();
for (Entry<String, IndexableField[]> es : sf.entrySet()) {
String fld = es.getKey();
if (fldMap.size() > 0 && !fldMap.contains(fld)) {
continue;
}
System.out.println("field="+fld);
IndexableField[] val = es.getValue();
int j=0;
for (IndexableField v : val) {
System.out.println(" " + j + "\t: " + v.stringValue());
j++;
}
}
//if (true) continue;
System.out.println("INDEXED FIELDS: " + dd);
Map<String, GrowableStringArray> rf = d.getReconstructedFields();
for (Entry<String, GrowableStringArray> es : rf.entrySet()) {
String fld = es.getKey();
if (fldMap.size() > 0 && !fldMap.contains(fld)) {
continue;
}
System.out.println(fld);
System.out.println(docToString(es.getValue(), "\n"));
}
}
sr.close();
}
private String docToString(GrowableStringArray doc, String separator) {
StringBuffer sb = new StringBuffer();
String sNull = "null";
int k = 0, m = 0;
for (int j = 0; j < doc.size(); j++) {
if (doc.get(j) == null)
k++;
else {
if (sb.length() > 0) sb.append(separator);
if (m > 0 && m % 5 == 0) sb.append('\n');
if (k > 0) {
sb.append(sNull + "_" + k + separator);
k = 0;
m++;
}
sb.append(j + "\t:");
sb.append(doc.get(j));
m++;
}
}
return sb.toString();
}
public String addDocs(String[] fields, String...values) {
ArrayList<String> vals = new ArrayList<String>(Arrays.asList(values));
String[] fieldsVals = new String[fields.length*(values.length*2)];
int i = 0;
for (String f: fields) {
for (String v: values) {
fieldsVals[i++] = f;
fieldsVals[i++] = v;
}
}
return addDocs(fieldsVals);
}
public String addDocs(String... fieldsAndValues) {
ArrayList<String> fVals = new ArrayList<String>(Arrays.asList(fieldsAndValues));
if (fVals.indexOf("id") == -1 || fVals.indexOf("id")%2==1) {
fVals.add("id");
fVals.add(Integer.toString(incrementId()));
}
if (fVals.indexOf("bibcode") == -1 || fVals.indexOf("bibcode")%2==1) {
fVals.add("bibcode");
String bibc = ("AAAAA........" + Integer.toString(idValue));
fVals.add(bibc.substring(bibc.length()-13, bibc.length()));
}
String[] newVals = new String[fVals.size()];
for (int i=0;i<fVals.size();i++) {
newVals[i] = fVals.get(i);
}
return super.adoc(newVals);
}
public int incrementId() {
return idValue++;
}
public static String[] formatSynonyms(String[] strings) {
String[] newLines = new String[strings.length];
int nl = 0;
for (String line : strings) {
StringBuilder out = new StringBuilder();
String[] kv = line.split("=>");
for (int i=0;i<kv.length;i++) {
if (i>0) out.append("=>");
String[] names = kv[i].split(";");
for (int j=0;j<names.length;j++) {
if (j>0) out.append(",");
out.append(names[j].trim().replace(" ", "\\ ").replace(",", "\\,"));
}
}
newLines[nl++] = out.toString();
}
return newLines;
}
}