package org.freehep.util.commanddispatcher;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Observer;
import java.util.Set;
/**
* A CommandTargetManager manages a set of CommandSources and a set of CommandGroups,
* and figure out the wiring from the CommandSources to the CommandTargets within the CommandGroups.
* The CommandGroups can be dynamically added and removed from the CommandTargetManager,
* as sets of commands become available or not.
*
* @author Tony Johnson (tonyj@slac.stanford.edu)
* @version $Id:
*/
public class CommandTargetManager
{
private Set groups = new HashSet();
private Set sources = new HashSet();
private boolean started = false;
public synchronized void add(CommandGroup group)
{
if (groups.add(group) && started)
{
for (Iterator i = sources.iterator(); i.hasNext();)
{
CommandSource s = (CommandSource) i.next();
String command = s.getCommand();
CommandTarget target = group.acceptCommand(command);
if (target != null)
{
CommandTarget existingTarget = s.getTarget();
if (existingTarget == null)
{
if (s.setTarget(target) && s instanceof Observer)
group.addObserver((Observer) s);
}
else if (existingTarget instanceof MultiTarget)
{
((MultiTarget) existingTarget).add(target);
}
else
{
if (s instanceof Observer)
existingTarget.getGroup().deleteObserver((Observer) s);
MultiTarget multi = new MultiTarget(command);
multi.add(existingTarget);
multi.add(target);
if (s.setTarget(multi) && s instanceof Observer)
multi.getGroup().addObserver((Observer) s);
}
}
}
}
group.setManager(this);
}
public synchronized void add(CommandSource source)
{
if (sources.add(source) && started)
{
linkCommandSource(source);
}
}
/**
* Override this method to provide custom handling of errors generated during command
* processing.
*/
public void handleCommandError(Throwable x)
{
System.err.println("Error during command invocation");
x.printStackTrace();
}
public synchronized void remove(CommandGroup group)
{
if (groups.remove(group) && started)
{
for (Iterator i = sources.iterator(); i.hasNext();)
{
CommandSource s = (CommandSource) i.next();
CommandTarget target = s.getTarget();
if (target != null)
{
if (target.getGroup() == group)
{
s.clearTarget();
if (s instanceof Observer)
group.deleteObserver((Observer) s);
}
else if (target instanceof MultiTarget)
{
((MultiTarget) target).removeGroup(group);
}
}
}
}
group.setManager(null);
}
public synchronized void remove(CommandSource source)
{
if (sources.remove(source) && started)
{
CommandTarget t = source.getTarget();
if (t != null)
{
source.clearTarget();
if (source instanceof Observer) t.getGroup().deleteObserver((Observer) source);
}
}
}
public synchronized void start()
{
started = true;
for (Iterator i = sources.iterator(); i.hasNext();)
{
linkCommandSource((CommandSource) i.next());
}
}
/**
* Dump the state of the manager for debug purposes
*/
public void dump(PrintStream out)
{
Dumper dumper = new Dumper(started, sources, groups);
dumper.dump(out);
}
/**
* This method links the CommandSource to any CommandGroup it hits
* that contains a CommandTarget that accepts the CommandSource.
*/
private void linkCommandSource(CommandSource s)
{
String command = s.getCommand();
CommandTarget theTarget = null;
for (Iterator i = groups.iterator(); i.hasNext();)
{
CommandGroup g = (CommandGroup) i.next();
CommandTarget t = g.acceptCommand(command);
if (t != null)
{
if (theTarget == null)
theTarget = t;
else if (theTarget instanceof MultiTarget)
((MultiTarget) theTarget).add(t);
else
{
MultiTarget multi = new MultiTarget(command);
multi.add(theTarget);
multi.add(t);
theTarget = multi;
}
}
}
if (theTarget != null)
{
if (s.setTarget(theTarget) && s instanceof Observer)
theTarget.getGroup().addObserver((Observer) s);
}
}
}