package com.browseengine.bobo.util;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.apache.lucene.util.PriorityQueue;
public class SearchResultMerger<T> {
private SearchResultMerger() {
}
public static class MergedIterator<T> implements Iterator<T> {
private class IteratorCtx {
public Iterator<T> _iterator;
public T _curVal;
public IteratorCtx(Iterator<T> iterator) {
_iterator = iterator;
_curVal = null;
}
public boolean fetch() {
if (_iterator.hasNext()) {
_curVal = _iterator.next();
return true;
}
_curVal = null;
return false;
}
}
@SuppressWarnings("rawtypes")
private final PriorityQueue _queue;
@SuppressWarnings("unchecked")
public MergedIterator(final List<Iterator<T>> sources, final Comparator<T> comparator) {
_queue = new PriorityQueue<Object>(sources.size()) {
@Override
protected boolean lessThan(Object o1, Object o2) {
T v1 = ((IteratorCtx) o1)._curVal;
T v2 = ((IteratorCtx) o2)._curVal;
return (comparator.compare(v1, v2) < 0);
}
};
for (Iterator<T> iterator : sources) {
IteratorCtx ctx = new IteratorCtx(iterator);
if (ctx.fetch()) _queue.add(ctx);
}
}
@Override
public boolean hasNext() {
return _queue.size() > 0;
}
@Override
@SuppressWarnings("unchecked")
public T next() {
IteratorCtx ctx = (IteratorCtx) _queue.top();
T val = ctx._curVal;
if (ctx.fetch()) {
_queue.updateTop();
} else {
_queue.pop();
}
return val;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
public static <T> Iterator<T> mergeIterator(List<Iterator<T>> results, Comparator<T> comparator) {
return new MergedIterator<T>(results, comparator);
}
public static <T> ArrayList<T> mergeResult(int offset, int count, List<Iterator<T>> results,
Comparator<T> comparator) {
Iterator<T> mergedIter = mergeIterator(results, comparator);
for (int c = 0; c < offset && mergedIter.hasNext(); c++) {
mergedIter.next();
}
ArrayList<T> mergedList = new ArrayList<T>();
for (int c = 0; c < count && mergedIter.hasNext(); c++) {
mergedList.add(mergedIter.next());
}
return mergedList;
}
}