package jadex.commons.service;
import jadex.commons.Future;
import jadex.commons.IFuture;
import jadex.commons.concurrent.CounterResultListener;
import jadex.commons.concurrent.DelegationResultListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* A service container is a simple infrastructure for a collection of
* services. It allows for starting/shutdowning the container and fetching
* service by their type/name.
*/
public class BasicServiceContainer implements IServiceContainer
{
//-------- attributes --------
/** The map of platform services. */
protected Map services;
/** The platform name. */
protected Object id;
/** True, if the container is started. */
protected boolean started;
//-------- constructors --------
/**
* Create a new service container.
*/
public BasicServiceContainer(Object id)
{
this.id = id;
}
//-------- interface methods --------
/**
* Get all services of a type.
* @param type The class.
* @return The corresponding services.
*/
public IFuture getServices(ISearchManager manager, IVisitDecider decider, IResultSelector selector, Collection results)
{
return manager.searchServices(this, decider, selector, services!=null ? services : Collections.EMPTY_MAP, results);
}
/**
* Get the parent service container.
* @return The parent container.
*/
public IFuture getParent()
{
return new Future(null);
}
/**
* Get the children container.
* @return The children container.
*/
public IFuture getChildren()
{
return new Future(null);
}
/**
* Get the globally unique id of the provider.
* @return The id of this provider.
*/
public Object getId()
{
return id;
}
//-------- methods --------
/**
* Add a service to the container.
* @param id The name.
* @param service The service.
*/
public IFuture addService(IInternalService service)
{
final Future ret = new Future();
// System.out.println("Adding service: " + name + " " + type + " " + service);
synchronized(this)
{
Collection tmp = services!=null? (Collection)services.get(service.getServiceIdentifier().getServiceType()): null;
if(tmp == null)
{
tmp = Collections.synchronizedList(new ArrayList());
if(services==null)
services = Collections.synchronizedMap(new LinkedHashMap());
services.put(service.getServiceIdentifier().getServiceType(), tmp);
}
tmp.add(service);
if(started)
{
service.startService().addResultListener(new DelegationResultListener(ret));
}
else
{
ret.setResult(null);
}
}
return ret;
}
/**
* Removes a service from the platform (shutdowns also the service).
* @param id The name.
* @param service The service.
*/
public IFuture removeService(IServiceIdentifier sid)
{
Future ret = new Future();
if(sid==null)
{
ret.setException(new IllegalArgumentException("Service identifier nulls."));
return ret;
}
// System.out.println("Removing service: " + type + " " + service);
synchronized(this)
{
Collection tmp = services!=null? (Collection)services.get(sid.getServiceType()): null;
IInternalService service = null;
if(tmp!=null)
{
for(Iterator it=tmp.iterator(); it.hasNext() && service==null; )
{
IInternalService tst = (IInternalService)it.next();
if(tst.getServiceIdentifier().equals(sid))
{
service = tst;
tmp.remove(service);
if(started)
{
service.shutdownService().addResultListener(new DelegationResultListener(ret));
}
else
{
ret.setResult(null);
}
}
}
}
if(service==null)
{
ret.setException(new IllegalArgumentException("Service not found: "+sid));
return ret;
}
if(tmp.isEmpty())
services.remove(sid.getServiceType());
}
return ret;
}
//-------- internal methods --------
/**
* Start the service.
*/
public IFuture start()
{
assert !started;
started = true;
final Future ret = new Future();
// Start the services.
if(services!=null && services.size()>0)
{
List allservices = new ArrayList();
for(Iterator it=services.values().iterator(); it.hasNext(); )
{
allservices.addAll((Collection)it.next());
}
CounterResultListener crl = new CounterResultListener(allservices.size(), new DelegationResultListener(ret));
for(Iterator it=allservices.iterator(); it.hasNext(); )
{
((IInternalService)it.next()).startService().addResultListener(crl);
}
}
else
{
ret.setResult(null);
}
return ret;
}
/**
* Shutdown the service.
*/
public IFuture shutdown()
{
assert started;
started = false;
// Thread.dumpStack();
// System.out.println("shutdown called: "+getName());
final Future ret = new Future();
// Stop the services.
if(services!=null && services.size()>0)
{
List allservices = new ArrayList();
for(Iterator it=services.values().iterator(); it.hasNext(); )
{
allservices.addAll((Collection)it.next());
}
CounterResultListener crl = new CounterResultListener(allservices.size(), new DelegationResultListener(ret));
for(Iterator it=allservices.iterator(); it.hasNext(); )
{
((IInternalService)it.next()).shutdownService().addResultListener(crl);
}
}
else
{
ret.setResult(null);
}
return ret;
}
/**
* Get the string representation.
* @return The string representation.
*/
public String toString()
{
return "BasicServiceContainer(name="+getId()+")";
}
/**
* Get the hashcode.
* @return The hashcode.
*/
public int hashCode()
{
return ((id == null) ? 0 : id.hashCode());
}
/**
* Test if the object eqquals another one.
* @param obj The object.
* @return true, if both are equal.
*/
public boolean equals(Object obj)
{
return obj instanceof IServiceContainer && ((IServiceContainer)obj).getId().equals(getId());
}
}