package thaw.fcp;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import java.util.Hashtable;
import java.util.Vector;
import thaw.core.Logger;
/**
* This class is designed to handle a LOT of FCPTransferQuery
* without overloading the observer/observable model.
* FCPTransferQueries must be non-persistent !
* It's useful when you have a lot of ULPR to handle
* @author jflesch
*/
public class FCPMetaTransferQuery extends Observable implements Observer {
private final FCPQueueManager queueManager;
private final Hashtable idToQuery;
private final String idField;
public FCPMetaTransferQuery(FCPQueueManager queueManager) {
this(queueManager, "Identifier");
}
private FCPMetaTransferQuery(FCPQueueManager queueManager, String idField) {
this.queueManager = queueManager;
this.idToQuery = new Hashtable();
this.idField = idField;
queueManager.getQueryManager().addObserver(this);
}
private void add(String id, FCPTransferQuery query) {
synchronized(idToQuery) {
idToQuery.put(id, query);
}
}
/***
* Will call query.start() itself
* @param query
* @return
*/
public boolean start(FCPTransferQuery query) {
if (query == null)
return false;
/* safety check */
if (query.isPersistent()) {
Logger.error(this, "A persistent query was given to FCPMetaTransferQuery ! this should never happen !");
try {
throw new Exception("meh");
} catch(Exception e) {
e.printStackTrace();
}
return false;
}
/* safety check */
if (!(query instanceof Observer)) {
Logger.error(this, "A non-observer query ("+query.getClass().getName()+") was given to FCPMetaTransferQuery ! this should never happen !");
try {
throw new Exception("meh");
} catch(Exception e) {
e.printStackTrace();
}
return false;
}
/* here we start for real */
boolean r = query.start(queueManager);
if (r) {
/* Ugly hack to replace the query manager by the metaTransferQuery */
add(query.getIdentifier(), query);
query.addObserver(this);
queueManager.getQueryManager().deleteObserver((Observer)query);
}
return r;
}
private void remove(String id) {
synchronized(idToQuery) {
idToQuery.remove(id);
}
}
/**
* Will call query.stop() itself
* Can't work atm on non-persistent requests .... (node r1111)
* @param query
* @return
*/
public boolean stop(FCPTransferQuery query) {
query.deleteObserver(this);
boolean r = true;
if (!query.isFinished())
r = query.stop(queueManager);
if (r) {
remove(query.getIdentifier());
} else {
query.addObserver(this);
}
return r;
}
public void stopAll() {
Vector queries = new Vector();
synchronized(idToQuery) {
for (Iterator it = idToQuery.values().iterator(); it.hasNext() ; )
queries.add(it.next());
}
for (Iterator it = queries.iterator(); it.hasNext() ; ) {
FCPTransferQuery query = (FCPTransferQuery)it.next();
stop(query);
}
}
public void update(Observable o, Object param) {
if (o instanceof FCPQueryManager) {
FCPMessage msg = (FCPMessage)param;
String targetId;
if (msg != null && (targetId = msg.getValue(idField)) != null) {
Observer obs;
synchronized(idToQuery) {
obs = (Observer)(idToQuery.get(targetId));
}
if (obs != null) {
/* we redirect only to the target FCPTransferQuery */
obs.update(o, param);
}
}
} if (o instanceof FCPTransferQuery) {
FCPTransferQuery q = (FCPTransferQuery)o;
if (q.isFinished()) {
q.deleteObserver(this);
remove(q.getIdentifier());
}
setChanged();
notifyObservers(o);
}
}
}