package com.browseengine.bobo.facets.impl; import java.io.IOException; import java.util.Arrays; import java.util.Comparator; import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.apache.lucene.util.Bits; import com.browseengine.bobo.api.BoboSegmentReader; import com.browseengine.bobo.facets.data.FacetDataCache; import com.browseengine.bobo.facets.data.FacetDataFetcher; import com.browseengine.bobo.facets.data.TermFixedLengthLongArrayListFactory; import com.browseengine.bobo.facets.data.TermListFactory; import com.browseengine.bobo.facets.data.TermStringList; import com.browseengine.bobo.facets.data.TermValueList; import com.browseengine.bobo.util.BigIntArray; import com.browseengine.bobo.util.BigSegmentedArray; public class VirtualSimpleFacetHandler extends SimpleFacetHandler { protected FacetDataFetcher _facetDataFetcher; public VirtualSimpleFacetHandler(String name, String indexFieldName, TermListFactory<?> termListFactory, FacetDataFetcher facetDataFetcher, Set<String> dependsOn) { super(name, null, termListFactory, dependsOn); _facetDataFetcher = facetDataFetcher; } public VirtualSimpleFacetHandler(String name, TermListFactory<?> termListFactory, FacetDataFetcher facetDataFetcher, Set<String> dependsOn) { this(name, null, termListFactory, facetDataFetcher, dependsOn); } @Override public FacetDataCache<?> load(BoboSegmentReader reader) throws IOException { TreeMap<Object, LinkedList<Integer>> dataMap = null; LinkedList<Integer> docList = null; int nullMinId = -1; int nullMaxId = -1; int nullFreq = 0; int doc = -1; Bits liveDocs = reader.getLiveDocs(); for (int i = 0; i < reader.maxDoc(); ++i) { if (liveDocs != null && !liveDocs.get(i)) { continue; } doc = i; Object val = _facetDataFetcher.fetch(reader, doc); if (val == null) { if (nullMinId < 0) nullMinId = doc; nullMaxId = doc; ++nullFreq; continue; } if (dataMap == null) { // Initialize. if (val instanceof long[]) { if (_termListFactory == null) _termListFactory = new TermFixedLengthLongArrayListFactory( ((long[]) val).length); dataMap = new TreeMap<Object, LinkedList<Integer>>(new Comparator<Object>() { @Override public int compare(Object big, Object small) { if (((long[]) big).length != ((long[]) small).length) { throw new RuntimeException("" + Arrays.asList(((long[]) big)) + " and " + Arrays.asList(((long[]) small)) + " have different length."); } long r = 0; for (int i = 0; i < ((long[]) big).length; ++i) { r = ((long[]) big)[i] - ((long[]) small)[i]; if (r != 0) break; } if (r > 0) return 1; else if (r < 0) return -1; return 0; } }); } else if (val instanceof Comparable) { dataMap = new TreeMap<Object, LinkedList<Integer>>(); } else { dataMap = new TreeMap<Object, LinkedList<Integer>>(new Comparator<Object>() { @Override public int compare(Object big, Object small) { return String.valueOf(big).compareTo(String.valueOf(small)); } }); } } docList = dataMap.get(val); if (docList == null) { docList = new LinkedList<Integer>(); dataMap.put(val, docList); } docList.add(doc); } _facetDataFetcher.cleanup(reader); int maxDoc = reader.maxDoc(); int size = dataMap == null ? 1 : (dataMap.size() + 1); BigSegmentedArray order = new BigIntArray(maxDoc); TermValueList<?> list = _termListFactory == null ? new TermStringList(size) : _termListFactory .createTermList(size); int[] freqs = new int[size]; int[] minIDs = new int[size]; int[] maxIDs = new int[size]; list.add(null); freqs[0] = nullFreq; minIDs[0] = nullMinId; maxIDs[0] = nullMaxId; if (dataMap != null) { int i = 1; Integer docId; for (Map.Entry<Object, LinkedList<Integer>> entry : dataMap.entrySet()) { list.add(list.format(entry.getKey())); docList = entry.getValue(); freqs[i] = docList.size(); minIDs[i] = docList.get(0); while ((docId = docList.poll()) != null) { doc = docId; order.add(docId, i); } maxIDs[i] = doc; ++i; } } list.seal(); @SuppressWarnings({ "rawtypes", "unchecked" }) FacetDataCache<?> dataCache = new FacetDataCache(order, list, freqs, minIDs, maxIDs, TermCountSize.large); return dataCache; } }