package proj.zoie.example.service.impl;
import java.io.IOException;
import java.util.*;
import com.browseengine.bobo.api.*;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.Scorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.util.Version;
import proj.zoie.api.IndexReaderFactory;
import proj.zoie.api.ZoieException;
import proj.zoie.service.api.SearchHit;
import proj.zoie.service.api.SearchRequest;
import proj.zoie.service.api.SearchResult;
import proj.zoie.service.api.ZoieSearchService;
public class ExampleZoieSearchServiceImpl<R extends IndexReader> implements ZoieSearchService {
private static final Logger log = Logger.getLogger(ExampleZoieSearchServiceImpl.class);
private IndexReaderFactory<R>[] _idxReaderFactory;
public ExampleZoieSearchServiceImpl(IndexReaderFactory<R> idxReaderFactory1, IndexReaderFactory<R> idxReaderFactory2){
_idxReaderFactory = new IndexReaderFactory[] { idxReaderFactory1, idxReaderFactory2 };
}
public ExampleZoieSearchServiceImpl(IndexReaderFactory<R> idx) {
_idxReaderFactory = new IndexReaderFactory[] { idx };
}
private static Map<String,String[]> convert(Document doc)
{
Map<String,String[]> map = new HashMap<String,String[]>();
if (doc != null)
{
List<Fieldable> fields = (List<Fieldable>)doc.getFields();
Iterator<Fieldable> iter = fields.iterator();
while(iter.hasNext())
{
Fieldable fld = iter.next();
String fieldname = fld.name();
String[] val = doc.getValues(fieldname);
if(fieldname.equals("num_followers")) {
for(int i=0; i<val.length; i++) {
int j = 0;
for(j = 0; j<val[i].length(); j++) {
if(val[i].charAt(j) != '0') break;
}
val[i] = val[i].substring(j);
}
} else if(fieldname.equals("timestamp")) {
val[0] = new Date(1000 * Long.parseLong(val[0])).toString();
}
map.put(fieldname, val);
}
}
return map;
}
private boolean bobo = true;
public SearchResult search(SearchRequest req) throws ZoieException{
String queryString = req.getQuery();
Analyzer analyzer = _idxReaderFactory[0].getAnalyzer();
QueryParser qparser = new QueryParser(Version.LUCENE_CURRENT, "content", analyzer);
SearchResult result = new SearchResult();
List<List<R>> readers = new ArrayList<List<R>>();
MultiReader multiReader = null;
Searcher searcher = null;
try
{
Query q = null;
if (queryString == null || queryString.length() ==0)
{
q = new MatchAllDocsQuery();
}
else
{
q = qparser.parse(queryString);
}
List<R> allReaders = (List<R>)new LinkedList();
for(int i=0; i<_idxReaderFactory.length; i++) {
readers.add(_idxReaderFactory[i].getIndexReaders());
allReaders.addAll(readers.get(i));
}
ScoreDoc[] scoreDocs = null;
BrowseResult bResult;
if(bobo) {
BoboBrowser[] browser = new BoboBrowser[allReaders.size()];
int i=0;
for(R reader : allReaders) {
browser[i] = new BoboBrowser((BoboIndexReader) reader);
}
MultiBoboBrowser multiBobo = new MultiBoboBrowser(browser);
BrowseRequest br = new BrowseRequest();
FacetSpec nf = new FacetSpec();
nf.setMaxCount(6);
br.setFacetSpec("num_followers", nf);
br.setQuery(q);
br.setSort(new SortField[] {SortField.FIELD_DOC});
long start = System.nanoTime();
bResult = multiBobo.browse(br);
long end = System.nanoTime();
result.setTime((end-start)/1000000);
result.setTotalDocs(bResult.getTotalDocs());
result.setTotalHits(bResult.getNumHits());
} else {
multiReader = new MultiReader(allReaders.toArray(new IndexReader[allReaders.size()]), false);
searcher = new IndexSearcher(multiReader);
long start = System.nanoTime();
TopDocs docs = searcher.search(q, null, 10);
long end = System.nanoTime();
result.setTime(((end-start))/1000000);
result.setTotalDocs(multiReader.numDocs());
result.setTotalHits(docs.totalHits);
scoreDocs = docs.scoreDocs;
}
ArrayList<SearchHit> hitList = new ArrayList<SearchHit>(scoreDocs.length);
if(bobo) {
} else {
for (ScoreDoc scoreDoc : scoreDocs)
{
SearchHit hit=new SearchHit();
hit.setScore(scoreDoc.score);
int docid=scoreDoc.doc;
Document doc=multiReader.document(docid);
String content=doc.get("content");
Scorer qs=new QueryScorer(q);
SimpleHTMLFormatter formatter=new SimpleHTMLFormatter("<span class=\"hl\">","</span>");
Highlighter hl=new Highlighter(formatter,qs);
String[] fragments=hl.getBestFragments(analyzer, "content",content, 1);
Map<String,String[]> fields=convert(doc);
fields.put("fragment",fragments);
hit.setFields(fields);
hitList.add(hit);
}
}
result.setHits(hitList.toArray(new SearchHit[hitList.size()]));
System.out.println("queryString: " + queryString + "\n" + result.toString());
return result;
}
catch(Exception e)
{
log.error(e.getMessage(),e);
throw new ZoieException(e.getMessage(),e);
}
finally
{
try{
if (searcher!=null)
{
try {
searcher.close();
} catch (IOException e) {
log.error(e.getMessage(),e);
}
}
}
finally{
for(int i=0; i<_idxReaderFactory.length; i++) {
_idxReaderFactory[i].returnIndexReaders(readers.get(i));
}
}
}
}
}