package com.browseengine.bobo.facets.filter;
import java.io.IOException;
import org.apache.lucene.search.DocIdSet;
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.MultiValueFacetDataCache;
import com.browseengine.bobo.facets.filter.FacetOrFilter.FacetOrDocIdSetIterator;
import com.browseengine.bobo.util.BigNestedIntArray;
public class MultiValueORFacetFilter extends RandomAccessFilter {
private final FacetHandler<?> _facetHandler;
private final String[] _vals;
private final boolean _takeCompliment;
private final FacetValueConverter _valueConverter;
public MultiValueORFacetFilter(FacetHandler<?> facetHandler, String[] vals, boolean takeCompliment) {
this(facetHandler, vals, FacetValueConverter.DEFAULT, takeCompliment);
}
public MultiValueORFacetFilter(FacetHandler<?> facetHandler, String[] vals,
FacetValueConverter valueConverter, boolean takeCompliment) {
_facetHandler = facetHandler;
_vals = vals;
_valueConverter = valueConverter;
_takeCompliment = takeCompliment;
}
@Override
public double getFacetSelectivity(BoboSegmentReader reader) {
double selectivity = 0;
@SuppressWarnings("unchecked")
MultiValueFacetDataCache<String> dataCache = (MultiValueFacetDataCache<String>) _facetHandler
.getFacetData(reader);
int[] idxes = _valueConverter.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;
}
public final static class MultiValueOrFacetDocIdSetIterator extends FacetOrDocIdSetIterator {
private final BigNestedIntArray _nestedArray;
public MultiValueOrFacetDocIdSetIterator(MultiValueFacetDataCache<?> dataCache, OpenBitSet bs) {
super(dataCache, bs);
_nestedArray = dataCache._nestedArray;
}
@Override
final public int nextDoc() throws IOException {
return (_doc = (_doc < _maxID ? _nestedArray.findValues(_bitset, (_doc + 1), _maxID)
: NO_MORE_DOCS));
}
@Override
final public int advance(int id) throws IOException {
if (_doc < id) {
return (_doc = (id <= _maxID ? _nestedArray.findValues(_bitset, id, _maxID) : NO_MORE_DOCS));
}
return nextDoc();
}
}
@Override
public RandomAccessDocIdSet getRandomAccessDocIdSet(BoboSegmentReader reader) throws IOException {
@SuppressWarnings("unchecked")
final MultiValueFacetDataCache<String> dataCache = (MultiValueFacetDataCache<String>) _facetHandler
.getFacetData(reader);
final int[] index = _valueConverter.convert(dataCache, _vals);
final BigNestedIntArray nestedArray = dataCache._nestedArray;
final OpenBitSet bitset = new OpenBitSet(dataCache.valArray.size());
for (int i : index) {
bitset.fastSet(i);
}
if (_takeCompliment) {
// flip the bits
int size = dataCache.valArray.size();
for (int i = 0; i < size; ++i) {
bitset.fastFlip(i);
}
}
long count = bitset.cardinality();
if (count == 0) {
final DocIdSet empty = EmptyDocIdSet.getInstance();
return new RandomAccessDocIdSet() {
@Override
public boolean get(int docId) {
return false;
}
@Override
public DocIdSetIterator iterator() throws IOException {
return empty.iterator();
}
};
} else {
return new RandomAccessDocIdSet() {
@Override
public DocIdSetIterator iterator() {
return new MultiValueOrFacetDocIdSetIterator(dataCache, bitset);
}
@Override
final public boolean get(int docId) {
return nestedArray.contains(docId, bitset);
}
};
}
}
}