/** * */ 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.RandomAccessDocIdSet; import com.browseengine.bobo.facets.FacetHandler; import com.browseengine.bobo.facets.data.FacetDataCache; import com.browseengine.bobo.facets.impl.GeoSimpleFacetHandler; import com.browseengine.bobo.util.BigSegmentedArray; public final class GeoSimpleFacetFilter extends RandomAccessFilter { private final FacetHandler<FacetDataCache<?>> _latFacetHandler; private final FacetHandler<FacetDataCache<?>> _longFacetHandler; private final String _latRangeString; private final String _longRangeString; /** * @param latHandler * @param longHandler * @param latRangeString * @param longRangeString */ public GeoSimpleFacetFilter(FacetHandler<FacetDataCache<?>> latHandler, FacetHandler<FacetDataCache<?>> longHandler, String latRangeString, String longRangeString) { _latFacetHandler = latHandler; _longFacetHandler = longHandler; _latRangeString = latRangeString; _longRangeString = longRangeString; } private final static class GeoSimpleDocIdSetIterator extends DocIdSetIterator { private int _doc = -1; private int _minID = Integer.MAX_VALUE; private int _maxID = -1; private final int _latStart; private final int _latEnd; private final int _longStart; private final int _longEnd; private final BigSegmentedArray _latOrderArray; GeoSimpleDocIdSetIterator(int latStart, int latEnd, int longStart, int longEnd, FacetDataCache<?> latDataCache, FacetDataCache<?> longDataCache) { _latStart = latStart; _longStart = longStart; _latEnd = latEnd; _longEnd = longEnd; for (int i = latStart; i <= latEnd; ++i) { _minID = Math.min(_minID, latDataCache.minIDs[i]); _maxID = Math.max(_maxID, latDataCache.maxIDs[i]); } for (int i = longStart; i <= longEnd; ++i) { _minID = Math.min(_minID, longDataCache.minIDs[i]); _maxID = Math.max(_maxID, longDataCache.maxIDs[i]); } _doc = Math.max(-1, _minID - 1); _latOrderArray = latDataCache.orderArray; } @Override final public int docID() { return _doc; } @Override final public int nextDoc() throws IOException { int latIndex; int longIndex; while (++_doc < _maxID) { // not yet reached end latIndex = _latOrderArray.get(_doc); longIndex = _latOrderArray.get(_doc); if ((latIndex >= _latStart && latIndex <= _latEnd) && (longIndex >= _longStart && longIndex <= _longEnd)) return _doc; } return DocIdSetIterator.NO_MORE_DOCS; } @Override final public int advance(int id) throws IOException { if (_doc < id) { _doc = id - 1; } int latIndex; int longIndex; while (++_doc < _maxID) { // not yet reached end latIndex = _latOrderArray.get(_doc); longIndex = _latOrderArray.get(_doc); if ((latIndex >= _latStart && latIndex <= _latEnd) && (longIndex >= _longStart && longIndex <= _longEnd)) { return _doc; } } return DocIdSetIterator.NO_MORE_DOCS; } @Override public long cost() { // TODO Auto-generated method stub return 0; } } @Override public RandomAccessDocIdSet getRandomAccessDocIdSet(BoboSegmentReader reader) throws IOException { final FacetDataCache<?> latDataCache = _latFacetHandler.getFacetData(reader); final FacetDataCache<?> longDataCache = _longFacetHandler.getFacetData(reader); final int[] latRange = FacetRangeFilter.parse(latDataCache, _latRangeString); final int[] longRange = FacetRangeFilter.parse(longDataCache, _longRangeString); if ((latRange == null) || (longRange == null)) return null; return new RandomAccessDocIdSet() { int _latStart = latRange[0]; int _latEnd = latRange[1]; int _longStart = longRange[0]; int _longEnd = longRange[1]; @Override final public boolean get(int docid) { int latIndex = latDataCache.orderArray.get(docid); int longIndex = longDataCache.orderArray.get(docid); return latIndex >= _latStart && latIndex <= _latEnd && longIndex >= _longStart && longIndex <= _longEnd; } @Override public DocIdSetIterator iterator() { return new GeoSimpleDocIdSetIterator(_latStart, _latEnd, _longStart, _longEnd, latDataCache, longDataCache); } }; } public static int[] parse(FacetDataCache<?> latDataCache, FacetDataCache<?> longDataCache, String rangeString) { GeoSimpleFacetHandler.GeoLatLonRange range = GeoSimpleFacetHandler.GeoLatLonRange .parse(rangeString); // ranges[0] is latRangeStart, ranges[1] is latRangeEnd, ranges[2] is longRangeStart, ranges[3] // is longRangeEnd String latLower = String.valueOf(range.latStart); String latUpper = String.valueOf(range.latEnd); String longLower = String.valueOf(range.lonStart); String longUpper = String.valueOf(range.lonEnd); int latStart, latEnd, longStart, longEnd; if (latLower == null) latStart = 1; else { latStart = latDataCache.valArray.indexOf(latLower); if (latStart < 0) { latStart = -(latStart + 1); } } if (longLower == null) longStart = 1; else { longStart = longDataCache.valArray.indexOf(longLower); if (longStart < 0) { longStart = -(longStart + 1); } } if (latUpper == null) { latEnd = latDataCache.valArray.size() - 1; } else { latEnd = latDataCache.valArray.indexOf(latUpper); if (latEnd < 0) { latEnd = -(latEnd + 1); latEnd = Math.max(0, latEnd - 1); } } if (longUpper == null) { longEnd = longDataCache.valArray.size() - 1; } else { longEnd = longDataCache.valArray.indexOf(longUpper); if (longEnd < 0) { longEnd = -(longEnd + 1); longEnd = Math.max(0, longEnd - 1); } } return new int[] { latStart, latEnd, longStart, longEnd }; } }