/*
* Created on Jun 20, 2008
* Created by Paul Gardner
*
* Copyright 2008 Vuze, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
package com.aelitis.azureus.core.metasearch.impl.plugin;
import java.io.IOException;
import java.util.*;
import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.utils.search.SearchInstance;
import org.gudy.azureus2.plugins.utils.search.SearchObserver;
import org.gudy.azureus2.plugins.utils.search.SearchProvider;
import org.gudy.azureus2.plugins.utils.search.SearchResult;
import com.aelitis.azureus.core.metasearch.*;
import com.aelitis.azureus.core.metasearch.impl.*;
public class
PluginEngine
extends EngineImpl
{
private static int[][] FIELD_MAP = {
{ SearchResult.PR_CATEGORY, Engine.FIELD_CATEGORY },
{ SearchResult.PR_COMMENTS, Engine.FIELD_COMMENTS },
{ SearchResult.PR_CONTENT_TYPE, Engine.FIELD_CONTENT_TYPE },
{ SearchResult.PR_DETAILS_LINK, Engine.FIELD_CDPLINK },
{ SearchResult.PR_DOWNLOAD_BUTTON_LINK, Engine.FIELD_DOWNLOADBTNLINK },
{ SearchResult.PR_DOWNLOAD_LINK, Engine.FIELD_TORRENTLINK },
{ SearchResult.PR_DRM_KEY, Engine.FIELD_DRMKEY },
{ SearchResult.PR_LEECHER_COUNT, Engine.FIELD_PEERS },
{ SearchResult.PR_NAME, Engine.FIELD_NAME },
{ SearchResult.PR_PLAY_LINK, Engine.FIELD_PLAYLINK },
{ SearchResult.PR_PRIVATE, Engine.FIELD_PRIVATE },
{ SearchResult.PR_PUB_DATE, Engine.FIELD_DATE },
{ SearchResult.PR_SEED_COUNT, Engine.FIELD_SEEDS },
{ SearchResult.PR_SIZE, Engine.FIELD_SIZE },
{ SearchResult.PR_SUPER_SEED_COUNT, Engine.FIELD_SUPERSEEDS },
{ SearchResult.PR_VOTES, Engine.FIELD_VOTES },
};
public static EngineImpl
importFromBEncodedMap(
MetaSearchImpl meta_search,
Map map )
throws IOException
{
return( new PluginEngine( meta_search, map ));
}
private SearchProvider provider;
public
PluginEngine(
MetaSearchImpl _meta_search,
long _id,
SearchProvider _provider )
{
super( _meta_search, Engine.ENGINE_TYPE_PLUGIN, _id, 0, 1.0f, (String)_provider.getProperty( SearchProvider.PR_NAME ));
provider = _provider;
setSource( ENGINE_SOURCE_LOCAL );
}
protected
PluginEngine(
MetaSearchImpl _meta_search,
Map _map )
throws IOException
{
super( _meta_search, _map );
// recovery from when incorrectly defaulted to 0.0
if ( getRankBias() == 0.0f ){
setRankBias( 1.0f );
}
setSource( ENGINE_SOURCE_LOCAL );
}
public Map
exportToBencodedMap()
throws IOException
{
return( exportToBencodedMap( false ));
}
public Map
exportToBencodedMap(
boolean generic )
throws IOException
{
Map res = new HashMap();
super.exportToBencodedMap( res, generic );
return( res );
}
public void
setProvider(
SearchProvider _provider )
{
provider = _provider;
}
public SearchProvider
getProvider()
{
return( provider );
}
protected boolean
useAccuracyForRank()
{
if ( provider == null ){
return( false );
}
Boolean val = (Boolean)provider.getProperty( SearchProvider.PR_USE_ACCURACY_FOR_RANK );
if ( val == null ){
return( false );
}
return( val.booleanValue());
}
public boolean
isActive()
{
return( provider != null && super.isActive());
}
public String
getNameEx()
{
return( super.getName() + ": (plugin)" );
}
public String
getDownloadLinkCSS()
{
if ( provider == null ){
return( null );
}
return((String)provider.getProperty( SearchProvider.PR_DOWNLOAD_LINK_LOCATOR ));
}
public boolean
supportsField(
int field )
{
if ( provider == null ){
return( false );
}
int[] supports = (int[])provider.getProperty( SearchProvider.PR_SUPPORTS_RESULT_FIELDS );
if ( supports == null ){
return( true );
}
for (int i=0;i<FIELD_MAP.length;i++){
int[] entry = FIELD_MAP[i];
if ( entry[1] == field ){
for (int j=0;j<supports.length;j++){
if ( supports[j] == entry[0] ){
return( true );
}
}
break;
}
}
return( false );
}
public boolean
supportsContext(
String context_key )
{
return( false );
}
public boolean
isShareable()
{
return( false );
}
public String
getIcon()
{
if ( provider == null ){
return( null );
}
return((String)provider.getProperty( SearchProvider.PR_ICON_URL ));
}
public String
getReferer()
{
if ( provider == null ){
return( null );
}
return((String)provider.getProperty( SearchProvider.PR_REFERER ));
}
protected Result[]
searchSupport(
SearchParameter[] params,
Map searchContext,
final int desired_max_matches,
final int absolute_max_matches,
String headers,
final ResultListener listener )
throws SearchException
{
if ( provider == null ){
provider = getMetaSearch().resolveProvider( this );
if ( provider == null ){
return( new Result[0] );
}
}
Map search_parameters = new HashMap();
String term = null;
for (int i=0;i<params.length;i++){
SearchParameter param = params[i];
String pattern = param.getMatchPattern();
String value = param.getValue();
if ( pattern.equals( "s" )){
term = value;
search_parameters.put( SearchProvider.SP_SEARCH_TERM, value );
}else if ( pattern.equals( "m" )){
search_parameters.put( SearchProvider.SP_MATURE, new Boolean(value ));
}else{
Debug.out( "Unrecognised search parameter '" + pattern + "=" + value + "' ignored" );
}
}
final String f_term = term;
try{
final List<PluginResult> results = new ArrayList<PluginResult>();
final AESemaphore sem = new AESemaphore( "waiter" );
provider.search(
search_parameters,
new SearchObserver()
{
private boolean complete = false;
public void
resultReceived(
SearchInstance search,
SearchResult result )
{
PluginResult p_result = new PluginResult( PluginEngine.this, result, f_term );
synchronized( this ){
if ( complete ){
return;
}
results.add( p_result );
}
if ( listener != null ){
listener.resultsReceived( PluginEngine.this, new Result[]{ p_result });
}
synchronized( this ){
if ( absolute_max_matches >= 0 && results.size() >= absolute_max_matches ){
complete = true;
sem.release();
}
}
}
public void
cancelled()
{
sem.release();
}
public void
complete()
{
sem.release();
}
public Object
getProperty(
int property )
{
if ( property == PR_MAX_RESULTS_WANTED ){
return( new Long( desired_max_matches ));
}
return( null );
}
});
sem.reserve();
if ( listener != null ){
listener.resultsComplete( this );
}
return((Result[])results.toArray(new Result[results.size()]));
}catch( Throwable e ){
throw( new SearchException( "Search failed", e ));
}
}
}