package com.browseengine.bobo.facets.filter;
import java.io.IOException;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.util.OpenBitSet;
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 FacetOrFilter extends RandomAccessFilter {
protected final FacetHandler<FacetDataCache<?>> _facetHandler;
protected final String[] _vals;
private final boolean _takeCompliment;
private final FacetValueConverter _valueConverter;
public FacetOrFilter(FacetHandler<FacetDataCache<?>> facetHandler, String[] vals) {
this(facetHandler, vals, false);
}
public FacetOrFilter(FacetHandler<FacetDataCache<?>> facetHandler, String[] vals,
boolean takeCompliment) {
this(facetHandler, vals, takeCompliment, FacetValueConverter.DEFAULT);
}
public FacetOrFilter(FacetHandler<FacetDataCache<?>> facetHandler, String[] vals,
boolean takeCompliment, FacetValueConverter valueConverter) {
_facetHandler = facetHandler;
_vals = vals;
_takeCompliment = takeCompliment;
_valueConverter = valueConverter;
}
@Override
public double getFacetSelectivity(BoboSegmentReader reader) {
double selectivity = 0;
FacetDataCache<?> dataCache = _facetHandler.getFacetData(reader);
int accumFreq = 0;
for (String value : _vals) {
int idx = dataCache.valArray.indexOf(value);
if (idx < 0) {
continue;
}
accumFreq += dataCache.freqs[idx];
}
int total = reader.maxDoc();
selectivity = (double) accumFreq / (double) total;
if (selectivity > 0.999) {
selectivity = 1.0;
}
if (_takeCompliment) {
selectivity = 1.0 - selectivity;
}
return selectivity;
}
@Override
public RandomAccessDocIdSet getRandomAccessDocIdSet(BoboSegmentReader reader) throws IOException {
if (_vals.length == 0) {
return EmptyDocIdSet.getInstance();
} else {
return new FacetOrRandomAccessDocIdSet(_facetHandler, reader, _vals, _valueConverter,
_takeCompliment);
}
}
public static class FacetOrRandomAccessDocIdSet extends RandomAccessDocIdSet {
private final OpenBitSet _bitset;
private final BigSegmentedArray _orderArray;
private final FacetDataCache<?> _dataCache;
private final int[] _index;
@SuppressWarnings("unchecked") FacetOrRandomAccessDocIdSet(
FacetHandler<FacetDataCache<?>> facetHandler,
BoboSegmentReader reader, String[] vals, FacetValueConverter valConverter,
boolean takeCompliment) {
_dataCache = facetHandler.getFacetData(reader);
_orderArray = _dataCache.orderArray;
_index = valConverter.convert(((FacetDataCache<String>) _dataCache), vals);
_bitset = new OpenBitSet(_dataCache.valArray.size());
for (int i : _index) {
_bitset.fastSet(i);
}
if (takeCompliment) {
// flip the bits
for (int i = 0; i < _dataCache.valArray.size(); ++i) {
_bitset.fastFlip(i);
}
}
}
@Override
public boolean get(int docId) {
return _bitset.fastGet(_orderArray.get(docId));
}
@Override
public DocIdSetIterator iterator() throws IOException {
return new FacetOrDocIdSetIterator(_dataCache, _bitset);
}
}
public static class FacetOrDocIdSetIterator extends DocIdSetIterator {
protected int _doc;
protected final FacetDataCache<?> _dataCache;
protected int _maxID;
protected final OpenBitSet _bitset;
protected final BigSegmentedArray _orderArray;
public FacetOrDocIdSetIterator(FacetDataCache<?> dataCache, OpenBitSet bitset) {
_dataCache = dataCache;
_orderArray = dataCache.orderArray;
_bitset = bitset;
_doc = Integer.MAX_VALUE;
_maxID = -1;
int size = _dataCache.valArray.size();
for (int i = 0; i < size; ++i) {
if (!bitset.fastGet(i)) {
continue;
}
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
final public int docID() {
return _doc;
}
@Override
public int nextDoc() throws IOException {
return (_doc = (_doc < _maxID ? _orderArray.findValues(_bitset, (_doc + 1), _maxID)
: NO_MORE_DOCS));
}
@Override
public int advance(int id) throws IOException {
if (_doc < id) {
return (_doc = (id <= _maxID ? _orderArray.findValues(_bitset, id, _maxID) : NO_MORE_DOCS));
}
return nextDoc();
}
@Override
public long cost() {
// TODO Auto-generated method stub
return 0;
}
}
}