package com.browseengine.bobo.facets.attribute;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import com.browseengine.bobo.api.BoboBrowser;
import com.browseengine.bobo.api.BoboMultiReader;
import com.browseengine.bobo.api.BoboSegmentReader;
import com.browseengine.bobo.api.BrowseFacet;
import com.browseengine.bobo.api.BrowseRequest;
import com.browseengine.bobo.api.BrowseResult;
import com.browseengine.bobo.api.BrowseSelection;
import com.browseengine.bobo.api.BrowseSelection.ValueOperation;
import com.browseengine.bobo.api.FacetAccessible;
import com.browseengine.bobo.api.FacetSpec;
import com.browseengine.bobo.api.FacetSpec.FacetSortSpec;
import com.browseengine.bobo.facets.FacetHandler;
import com.browseengine.bobo.facets.filter.RandomAccessFilter;
public class AttributesFacetHandlerTest extends TestCase {
private RAMDirectory directory;
private Analyzer analyzer;
private final List<FacetHandler<?>> facetHandlers;
private AttributesFacetHandler attributesFacetHandler;
private BoboBrowser browser;
private BoboMultiReader boboReader;
private Map<String, String> selectionProperties;
static final String AttributeHandlerName = "attributes";
public AttributesFacetHandlerTest(String name) {
super(name);
facetHandlers = new LinkedList<FacetHandler<?>>();
}
private void addMetaDataField(Document doc, String name, String[] vals) {
for (String val : vals) {
Field field = new StringField(name, val, Store.NO);
doc.add(field);
}
}
@Override
protected void setUp() throws Exception {
directory = new RAMDirectory();
analyzer = new WhitespaceAnalyzer(Version.LUCENE_43);
selectionProperties = new HashMap<String, String>();
IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_43, analyzer);
conf.setOpenMode(OpenMode.CREATE);
IndexWriter writer = new IndexWriter(directory, conf);
writer.addDocument(doc("prop1=val1", "prop2=val1", "prop5=val1"));
writer.addDocument(doc("prop1=val2", "prop3=val1", "prop7=val7"));
writer.addDocument(doc("prop1=val2", "prop3=val2", "prop3=val3"));
writer.addDocument(doc("prop1=val1", "prop2=val1"));
writer.addDocument(doc("prop1=val1", "prop2=val1"));
writer.addDocument(doc("prop1=val1", "prop2=val1", "prop4=val2", "prop4=val3"));
writer.commit();
attributesFacetHandler = new AttributesFacetHandler(AttributeHandlerName, AttributeHandlerName,
null, null, new HashMap<String, String>());
facetHandlers.add(attributesFacetHandler);
DirectoryReader reader = DirectoryReader.open(directory);
boboReader = BoboMultiReader.getInstance(reader, facetHandlers);
for (BoboSegmentReader subReader : boboReader.getSubReaders()) {
attributesFacetHandler.loadFacetData(subReader);
}
browser = new BoboBrowser(boboReader);
}
private Document doc(String... terms) {
Document doc = new Document();
addMetaDataField(doc, AttributeHandlerName, terms);
return doc;
}
public BrowseRequest createRequest(int minHitCount, String... terms) {
return createRequest(minHitCount, ValueOperation.ValueOperationOr, terms);
}
public BrowseRequest createRequest(int minHitCount, BrowseSelection.ValueOperation operation,
String... terms) {
BrowseRequest req = new BrowseRequest();
BrowseSelection sel = new BrowseSelection(AttributeHandlerName);
for (String term : terms) {
sel.addValue(term);
}
sel.setSelectionProperties(selectionProperties);
sel.setSelectionOperation(operation);
req.addSelection(sel);
req.setCount(50);
FacetSpec fs = new FacetSpec();
fs.setMinHitCount(minHitCount);
req.setFacetSpec(AttributeHandlerName, fs);
return req;
}
public void test1Filter() throws Exception {
BrowseRequest request = createRequest(1, "prop3");
RandomAccessFilter randomAccessFilter = attributesFacetHandler.buildFilter(request
.getSelection(AttributeHandlerName));
DocIdSetIterator iterator = randomAccessFilter.getDocIdSet(
boboReader.getSubReaders().get(0).getContext(), null).iterator();
int docId = iterator.nextDoc();
int[] docIds = new int[2];
int i = 0;
while (docId != DocIdSetIterator.NO_MORE_DOCS) {
docIds[i] = docId;
i++;
docId = iterator.nextDoc();
}
assertEquals(Arrays.toString(new int[] { 1, 2 }), Arrays.toString(docIds));
BrowseResult res = browser.browse(request);
assertEquals(res.getNumHits(), 2);
FacetAccessible fa = res.getFacetAccessor(AttributeHandlerName);
List<BrowseFacet> facets = fa.getFacets();
System.out.println(facets);
assertEquals(3, facets.size());
BrowseFacet facet = facets.get(0);
assertEquals(1, facet.getFacetValueHitCount());
}
public void test2PropertyRetrieval() throws Exception {
BrowseRequest request = createRequest(1, "prop3");
BrowseResult res = browser.browse(request);
assertEquals(res.getNumHits(), 2);
assertEquals(res.getHits()[0].getDocid(), 1);
assertEquals(res.getHits()[1].getDocid(), 2);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 3);
assertEquals(facets.get(0).getValue(), "prop3=val1");
assertEquals(facets.get(0).getFacetValueHitCount(), 1);
assertEquals(facets.get(2).getValue(), "prop3=val3");
assertEquals(facets.get(2).getFacetValueHitCount(), 1);
}
public void test3PropertyInEachDocRetrieval() throws Exception {
BrowseRequest request = createRequest(1, "prop1");
BrowseResult res = browser.browse(request);
assertEquals(res.getNumHits(), 6);
assertEquals(res.getHits()[0].getDocid(), 0);
assertEquals(res.getHits()[5].getDocid(), 5);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 2);
assertEquals(facets.get(0).getValue(), "prop1=val1");
assertEquals(facets.get(0).getFacetValueHitCount(), 4);
assertEquals(facets.get(1).getValue(), "prop1=val2");
assertEquals(facets.get(1).getFacetValueHitCount(), 2);
}
public void test4PropertyInFirstDocRetrieval() throws Exception {
BrowseRequest request = createRequest(1, "prop5");
BrowseResult res = browser.browse(request);
assertEquals(res.getNumHits(), 1);
assertEquals(res.getHits()[0].getDocid(), 0);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 1);
assertEquals(facets.get(0).getValue(), "prop5=val1");
assertEquals(facets.get(0).getFacetValueHitCount(), 1);
}
public void test5PropertyInLastDocRetrieval() throws Exception {
BrowseRequest request = createRequest(1, "prop4");
BrowseResult res = browser.browse(request);
System.out.println(res);
assertEquals(res.getNumHits(), 1);
assertEquals(res.getHits()[0].getDocid(), 5);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 2);
assertEquals(facets.get(0).getValue(), "prop4=val2");
assertEquals(facets.get(0).getFacetValueHitCount(), 1);
assertEquals(facets.get(1).getValue(), "prop4=val3");
assertEquals(facets.get(1).getFacetValueHitCount(), 1);
}
public void test6NonExisitngPropertyDocRetrieval() throws Exception {
BrowseRequest request = createRequest(1, "propMissing");
BrowseResult res = browser.browse(request);
assertEquals(res.getNumHits(), 0);
}
public void test7AndProperties() throws Exception {
BrowseRequest request = createRequest(1, ValueOperation.ValueOperationAnd, "prop1", "prop3");
BrowseResult res = browser.browse(request);
System.out.println(res);
assertEquals(res.getNumHits(), 2);
assertEquals(res.getHits()[0].getDocid(), 1);
assertEquals(res.getHits()[1].getDocid(), 2);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 4);
assertEquals(facets.get(0).getValue(), "prop1=val2");
assertEquals(facets.get(0).getFacetValueHitCount(), 2);
assertEquals(facets.get(1).getValue(), "prop3=val1");
assertEquals(facets.get(1).getFacetValueHitCount(), 1);
}
public void test9ModifiedNumberOfFacetsPerKey() throws Exception {
modifiedSetup();
BrowseRequest request = createRequest(1, ValueOperation.ValueOperationOr);
request.getFacetSpec(AttributeHandlerName).setOrderBy(FacetSortSpec.OrderHitsDesc);
BrowseResult res = browser.browse(request);
System.out.println(res);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 6);
assertEquals(facets.get(0).getValue(), "prop1=val1");
assertEquals(facets.get(0).getFacetValueHitCount(), 4);
assertEquals(facets.get(1).getValue(), "prop2=val1");
assertEquals(facets.get(1).getFacetValueHitCount(), 4);
assertEquals(facets.get(2).getValue(), "prop3=val1");
assertEquals(facets.get(2).getFacetValueHitCount(), 1);
}
public void test8AndPropertiesPlsExclusion() throws Exception {
BrowseRequest request = createRequest(1, ValueOperation.ValueOperationAnd, "prop1", "prop3");
request.getSelection(AttributeHandlerName).addNotValue("prop7");
BrowseResult res = browser.browse(request);
System.out.println(res);
assertEquals(res.getNumHits(), 1);
assertEquals(res.getHits()[0].getDocid(), 2);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 3);
assertEquals(facets.get(0).getValue(), "prop1=val2");
assertEquals(facets.get(0).getFacetValueHitCount(), 1);
assertEquals(facets.get(1).getValue(), "prop3=val2");
assertEquals(facets.get(1).getFacetValueHitCount(), 1);
assertEquals(facets.get(2).getValue(), "prop3=val3");
assertEquals(facets.get(2).getFacetValueHitCount(), 1);
}
public void test10ModifiedNumberOfFacetsPerKeyInSelection() throws Exception {
modifiedSetup();
selectionProperties.put(AttributesFacetHandler.MAX_FACETS_PER_KEY_PROP_NAME, "2");
BrowseRequest request = createRequest(1, ValueOperation.ValueOperationOr, "prop1", "prop2",
"prop3", "prop4", "prop5", "prop6", "prop7");
request.getFacetSpec(AttributeHandlerName).setOrderBy(FacetSortSpec.OrderHitsDesc);
BrowseResult res = browser.browse(request);
System.out.println(res);
List<BrowseFacet> facets = res.getFacetAccessor(AttributeHandlerName).getFacets();
assertEquals(facets.size(), 9);
assertEquals(facets.get(0).getValue(), "prop1=val1");
assertEquals(facets.get(0).getFacetValueHitCount(), 4);
assertEquals(facets.get(1).getValue(), "prop2=val1");
assertEquals(facets.get(1).getFacetValueHitCount(), 4);
assertEquals(facets.get(2).getValue(), "prop1=val2");
assertEquals(facets.get(2).getFacetValueHitCount(), 2);
assertEquals(facets.get(3).getValue(), "prop3=val1");
assertEquals(facets.get(3).getFacetValueHitCount(), 1);
}
private void modifiedSetup() throws CorruptIndexException, LockObtainFailedException, IOException {
directory = new RAMDirectory();
analyzer = new WhitespaceAnalyzer(Version.LUCENE_43);
IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_43, analyzer);
conf.setOpenMode(OpenMode.CREATE);
IndexWriter writer = new IndexWriter(directory, conf);
writer.addDocument(doc("prop1=val1", "prop2=val1", "prop5=val1"));
writer.addDocument(doc("prop1=val2", "prop3=val1", "prop7=val7"));
writer.addDocument(doc("prop1=val2", "prop3=val2", "prop3=val3"));
writer.addDocument(doc("prop1=val1", "prop2=val1"));
writer.addDocument(doc("prop1=val1", "prop2=val1"));
writer.addDocument(doc("prop1=val1", "prop2=val1", "prop4=val2", "prop4=val3"));
writer.commit();
HashMap<String, String> facetProps = new HashMap<String, String>();
facetProps.put(AttributesFacetHandler.MAX_FACETS_PER_KEY_PROP_NAME, "1");
attributesFacetHandler = new AttributesFacetHandler(AttributeHandlerName, AttributeHandlerName,
null, null, facetProps);
facetHandlers.add(attributesFacetHandler);
DirectoryReader reader = DirectoryReader.open(directory);
boboReader = BoboMultiReader.getInstance(reader, facetHandlers);
for (BoboSegmentReader subReader : boboReader.getSubReaders()) {
attributesFacetHandler.loadFacetData(subReader);
}
browser = new BoboBrowser(boboReader);
}
}