package jadex.commons.service;
import jadex.commons.ComposedFilter;
import jadex.commons.IFilter;
import jadex.commons.Tuple;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Select one or more services according to a filter.
*/
public class BasicResultSelector implements IResultSelector
{
//-------- attributes --------
/** The type. */
protected IFilter filter;
/** The one result flag. */
protected boolean oneresult;
/** The only local services flag. */
protected boolean remote;
//-------- constructors --------
/**
* Create a type result listener.
*/
public BasicResultSelector()
{
}
/**
* Create a type result listener.
*/
public BasicResultSelector(IFilter filter)
{
this(filter, true);
}
/**
* Create a type result listener.
*/
public BasicResultSelector(IFilter filter, boolean oneresult)
{
this(filter, oneresult, false);
}
/**
* Create a type result listener.
*/
public BasicResultSelector(IFilter filter, boolean oneresult, boolean remote)
{
this.filter = filter;
this.oneresult = oneresult;
this.remote = remote;
}
//-------- methods --------
/**
* Called for each searched service provider node.
* @param services The provided services (class->list of services).
* @param results The collection to which results should be added.
*/
public void selectServices(Map servicemap, Collection results)
{
IFilter fil = filter;
if(!remote)
{
if(fil!=null)
{
fil = new ComposedFilter(new IFilter[]{filter, ProxyFilter.PROXYFILTER}, ComposedFilter.AND);
}
else
{
fil = ProxyFilter.PROXYFILTER;
}
}
IService[] services = generateServiceArray(servicemap);
if(services!=null)
{
// if(services.length>0)
// System.out.println("adding: "+SUtil.arrayToString(services)+" "+this);
if(oneresult && services.length>0)
{
for(int i=0; i<services.length; i++)
{
if(fil.filter(services[i]))
{
results.add(services[i]);
break;
}
}
}
else
{
// if(services.length>0)
// System.out.println("adding: "+SUtil.arrayToString(services)+" "+this);
for(int i=0; i<services.length; i++)
{
if(fil.filter(services[i]) && !results.contains(services[i]))
{
// if(services[i].getClass().getName().indexOf("Shop")!=-1)
// System.out.println("add: "+services[i]+" to: "+results);
results.add(services[i]);
}
}
}
}
}
/**
* Get all services of the map as linear collection.
*/
public IService[] generateServiceArray(Map servicemap)
{
List ret = new ArrayList();
Object[] keys = servicemap.keySet().toArray();
for(int i=0; i<keys.length; i++)
{
Collection coll = (Collection)servicemap.get(keys[i]);
if(coll!=null)
{
Object[] vals = coll.toArray();
for(int j=0; j<vals.length; j++)
{
ret.add(vals[j]);
}
}
}
return (IService[])ret.toArray(new IService[ret.size()]);
}
/**
* Get the result.
* Called once after search is finished.
* @param results The collection of selected services.
* @return A single service or a list of services.
*/
public Object getResult(Collection results)
{
Object ret = oneresult? results.size()>0? results.toArray()[0]: null: results;
return ret;
}
/**
* Test if the search result is sufficient to stop the search.
* @param results The collection of selected services.
* @return True, if the search should be stopped.
*/
public boolean isFinished(Collection results)
{
return oneresult && results.size()>0;
}
/**
* Get the cache key.
* Needs to identify this element with respect to its important features so that
* two equal elements should return the same key.
*/
public Object getCacheKey()
{
return new Tuple(new Object[]{this.getClass().getName(), filter,
oneresult? Boolean.TRUE: Boolean.FALSE, remote? Boolean.TRUE: Boolean.FALSE});
}
/**
* Get the filter.
* @return the filter.
*/
public IFilter getFilter()
{
return filter;
}
/**
* Set the filter.
* @param filter The filter to set.
*/
public void setFilter(IFilter filter)
{
this.filter = filter;
}
/**
* Get the oneresult.
* @return the oneresult.
*/
public boolean isOneResult()
{
return oneresult;
}
/**
* Set the oneresult.
* @param oneresult The oneresult to set.
*/
public void setOneResult(boolean oneresult)
{
this.oneresult = oneresult;
}
// NOTE! This methods currently must be commented for remote searches
// to work. Otherwise, remote=true will lead to cache hits of proxies.
// /**
// * Get the remote.
// * @return the remote.
// */
// public boolean isRemote()
// {
// return remote;
// }
//
// /**
// * Set the remote.
// * @param remote The remote to set.
// */
// public void setRemote(boolean remote)
// {
// this.remote = remote;
// }
/**
* Get the string representation.
*/
public String toString()
{
return getClass().getName()+"(filter=" + filter + ", oneresult=" + oneresult+ ", remote=" + remote + ")";
}
}