package com.browseengine.bobo.facets.filter;
import java.io.IOException;
import org.apache.lucene.search.DocIdSetIterator;
import com.browseengine.bobo.api.BoboSegmentReader;
import com.browseengine.bobo.docidset.EmptyDocIdSet;
import com.browseengine.bobo.docidset.RandomAccessDocIdSet;
import com.browseengine.bobo.facets.FacetHandler;
import com.browseengine.bobo.facets.data.FacetDataCache;
import com.browseengine.bobo.util.BigSegmentedArray;
public class CompactMultiValueFacetFilter extends RandomAccessFilter {
private final FacetHandler<FacetDataCache<?>> _facetHandler;
private final String[] _vals;
public CompactMultiValueFacetFilter(FacetHandler<FacetDataCache<?>> facetHandler, String val) {
this(facetHandler, new String[] { val });
}
public CompactMultiValueFacetFilter(FacetHandler<FacetDataCache<?>> facetHandler, String[] vals) {
_facetHandler = facetHandler;
_vals = vals;
}
@SuppressWarnings("unchecked")
@Override
public double getFacetSelectivity(BoboSegmentReader reader) {
double selectivity = 0;
FacetDataCache<String> dataCache = (FacetDataCache<String>) _facetHandler.getFacetData(reader);
int[] idxes = FacetDataCache.convert(dataCache, _vals);
if (idxes == null) {
return 0.0;
}
int accumFreq = 0;
for (int idx : idxes) {
accumFreq += dataCache.freqs[idx];
}
int total = reader.maxDoc();
selectivity = (double) accumFreq / (double) total;
if (selectivity > 0.999) {
selectivity = 1.0;
}
return selectivity;
}
private final static class CompactMultiValueFacetDocIdSetIterator extends DocIdSetIterator {
private final int _bits;
private int _doc;
private int _maxID;
private final BigSegmentedArray _orderArray;
public CompactMultiValueFacetDocIdSetIterator(FacetDataCache<?> dataCache, int[] index, int bits) {
_bits = bits;
_doc = Integer.MAX_VALUE;
_maxID = -1;
_orderArray = dataCache.orderArray;
for (int i : index) {
if (_doc > dataCache.minIDs[i]) {
_doc = dataCache.minIDs[i];
}
if (_maxID < dataCache.maxIDs[i]) {
_maxID = dataCache.maxIDs[i];
}
}
_doc--;
if (_doc < 0) _doc = -1;
}
@Override
public final int docID() {
return _doc;
}
@Override
public final int nextDoc() throws IOException {
return (_doc = (_doc < _maxID ? _orderArray.findBits(_bits, (_doc + 1), _maxID)
: NO_MORE_DOCS));
}
@Override
public final int advance(int id) throws IOException {
if (_doc < id) {
return (_doc = (id <= _maxID ? _orderArray.findBits(_bits, id, _maxID) : NO_MORE_DOCS));
}
return nextDoc();
}
@Override
public long cost() {
// TODO Auto-generated method stub
return 0;
}
}
@SuppressWarnings("unchecked")
@Override
public RandomAccessDocIdSet getRandomAccessDocIdSet(final BoboSegmentReader reader)
throws IOException {
final FacetDataCache<String> dataCache = (FacetDataCache<String>) _facetHandler
.getFacetData(reader);
final int[] indexes = FacetDataCache.convert(dataCache, _vals);
int bits;
bits = 0x0;
for (int i : indexes) {
bits |= 0x00000001 << (i - 1);
}
final int finalBits = bits;
final BigSegmentedArray orderArray = dataCache.orderArray;
if (indexes.length == 0) {
return EmptyDocIdSet.getInstance();
} else {
return new RandomAccessDocIdSet() {
@Override
public DocIdSetIterator iterator() {
return new CompactMultiValueFacetDocIdSetIterator(dataCache, indexes, finalBits);
}
@Override
final public boolean get(int docId) {
return (orderArray.get(docId) & finalBits) != 0x0;
}
};
}
}
}