ResultListener listener =
new ResultListener()
{
// single thread listener calls
private AsyncDispatcher dispatcher = new AsyncDispatcher( 5000 );
final private Map<Engine,List<Result[]>> pending_results = new HashMap<Engine,List<Result[]>>();
final private Map<Engine,Set<String>> result_hashes = new HashMap<Engine, Set<String>>();
public void
contentReceived(
final Engine engine,
final String content )
{
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{
original_listener.contentReceived( engine, content );
}
});
}
public void
matchFound(
final Engine engine,
final String[] fields )
{
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{
original_listener.matchFound( engine, fields );
}
});
}
public void
resultsReceived(
final Engine engine,
final Result[] results )
{
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{
Result[] results_to_return = null;
if ( batch_millis > 0 ){
List<Result[]> list = pending_results.get( engine );
if ( list == null ){
results_to_return = results;
pending_results.put( engine, new ArrayList<Result[]>());
new DelayedEvent(
"SearchBatcher",
batch_millis,
new AERunnable()
{
public void
runSupport()
{
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{
batchResultsComplete( engine );
}
});
}
});
}else{
list.add( results );
}
}else{
results_to_return = results;
}
if ( results_to_return != null ){
results_to_return = truncateResults( engine, results_to_return, max_results_per_engine );
original_listener.resultsReceived( engine, results_to_return );
}
}
});
}
public void
resultsComplete(
final Engine engine )
{
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{
if ( batch_millis > 0 ){
batchResultsComplete( engine );
}
original_listener.resultsComplete( engine );
}
});
}
protected void
batchResultsComplete(
Engine engine )
{
List<Result[]> list = pending_results.remove( engine );
if ( list != null ){
List<Result> x = new ArrayList<Result>();
for ( Result[] y: list ){
x.addAll( Arrays.asList( y ));
}
Result[] results = x.toArray( new Result[ x.size()]);
results = truncateResults( engine, results, max_results_per_engine );
original_listener.resultsReceived( engine, results );
}
}
protected Result[]
truncateResults(
Engine engine,
Result[] a_results,
int max )
{
Set<String> hash_set = result_hashes.get( engine );
if ( hash_set == null ){
hash_set = new HashSet<String>();
result_hashes.put( engine, hash_set );
}
List<Result> results = new ArrayList<Result>( a_results.length );
for ( Result r: a_results ){
String name = r.getName();
if ( name == null || name.trim().length() == 0 ){
continue;
}
if ( rem_dups ){
String hash = r.getHash();
if ( hash == null ||
hash.length() == 0 ){
results.add( r );
}else{
if ( !hash_set.contains( hash )){
results.add( r );
hash_set.add( hash );
}
}
}else{
results.add( r );
}
}
if ( max < results.size() ){
log( "Truncating search results for " + engine.getName() + " from " + results.size() + " to " + max );
Collections.sort(
results,
new Comparator<Result>()
{
Map<Result,Float> ranks = new HashMap<Result, Float>();
public int
compare(
Result r1,
Result r2)
{
Float rank1 = (Float)ranks.get(r1);
if ( rank1 == null ){
rank1 = new Float(r1.getRank());
ranks.put( r1, rank1 );
}
Float rank2 = (Float)ranks.get(r2);
if ( rank2 == null ){
rank2 = new Float(r2.getRank());
ranks.put( r2, rank2 );
}
return( -rank1.compareTo( rank2 ));
}
});
Result[] x = new Result[max];
int pos = 0;
while( pos < max ){
x[pos] = results.get( pos );
pos++;
}
return( x );
}else{
return( results.toArray( new Result[ results.size()] ));
}
}
public void
engineFailed(
final Engine engine,
final Throwable e )
{
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{
original_listener.engineFailed( engine, e );
}
});
}
public void
engineRequiresLogin(
final Engine engine,
final Throwable e )
{
dispatcher.dispatch(
new AERunnable()
{
public void
runSupport()
{