package jas.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Observable;
/**
* A CommandProcessor represents a collection of CommandTargets. The CommandProcessor is Observable,
* and is normally Observed by the CommandTargetManager. When the CommandProcessor calls
* its notifyObservers method, the CommandTargetManager prompts each CommandSource currently
* attached to CommandTargets within the CommandProcessor to update their enabled/disabled status.
*
* Typically applications provide their own CommandProcessor(s) which extend this base class
* and which can handle a set of commands. By default CommandProcessor's acceptCommand method
* uses reflection to search for methods in the subClass which correspond to specific commands,
* although subclasses could also override the acceptCommand method to implement a different
* scheme. The default scheme looks for methods of type:
* <pre>
* public void onXXX()
* </pre>
* to handle the command XXX. Also
* <pre>
* public void enableXXX(JASState state)
* </pre>
* to determine if the command is active or not.
* @dependency jas.util.CommandProcessor$SimpleTarget creates
* @dependency jas.util.CommandProcessor$BooleanTarget creates
*/
public class CommandProcessor extends Observable
{
protected String translate(String command)
{
if (command.endsWith("..."))
command = command.substring(0,command.length()-3);
for (int i=command.indexOf(" "); i >= 0; i=command.indexOf(" "))
command = command.substring(0,i)+command.substring(i+1);
return command;
}
protected void setChanged()
{
super.setChanged();
notifyObservers();
}
protected void setManager(CommandTargetManager m)
{
}
/**
* The CommandTargetManager called acceptCommand to find out if this CommandProcessor
* can respond to the specified command. If it can it returns a CommandTarget for the command,
* otherwise it returns null.
*
*/
protected CommandTarget acceptCommand(String command)
{
String t = translate(command);
String c = "on"+t;
String e = "enable"+t;
Method mc,me;
try
{
mc = this.getClass().getMethod(c,noArg);
try
{
me = this.getClass().getMethod(e,simpleEnableArg);
}
catch (NoSuchMethodException x)
{
me = null;
}
try // Support for RadioMenuItem
{
if (me == null) me = this.getClass().getMethod(e,booleanEnableArg);
}
catch (NoSuchMethodException x)
{
me = null;
}
return new SimpleTarget(mc,me);
}
catch (NoSuchMethodException x)
{
}
try
{
mc = this.getClass().getMethod(c,boolArg);
try
{
me = this.getClass().getMethod(e,booleanEnableArg);
}
catch (NoSuchMethodException x)
{
me = null;
}
return new BooleanTarget(mc,me);
}
catch (NoSuchMethodException x)
{
}
return null;
}
protected void invoke(Method method,Object[] args)
throws IllegalAccessException,InvocationTargetException
{
method.invoke(this,args);
}
protected void invokeEnable(Method method,Object[] args)
throws IllegalAccessException,InvocationTargetException
{
invoke(method,args);
}
protected void invokeCommand(Method method,Object[] args)
throws IllegalAccessException,InvocationTargetException
{
invoke(method,args);
}
protected void invokeCommand(SimpleTarget t)
{
try
{
t.doCommand();
}
catch (CommandInvocationException x)
{
System.err.println("Error during command invocation: "+x.getTargetException());
}
}
protected void invokeCommand(BooleanTarget t, boolean arg)
{
try
{
t.doCommand(arg);
}
catch (CommandInvocationException x)
{
System.err.println("Error during command invocation: "+x.getTargetException());
}
}
private static final Class noArg[] = {};
private static final Object noArgs[] = {};
private static final Class boolArg[] = {java.lang.Boolean.TYPE};
private static final Class simpleEnableArg[] = {JASState.class};
private static final Class booleanEnableArg[] = {JASCheckboxState.class};
/**
* A SimpleTarget is an implementation of CommandTarget which implements its
*
*/
protected class SimpleTarget implements SimpleCommandTarget
{
SimpleTarget(Method command, Method enable)
{
m_command = command;
m_enable = enable;
}
public void invoke()
{
CommandProcessor.this.invokeCommand(this);
}
public void doCommand() throws CommandInvocationException
{
try
{
invokeCommand(m_command,noArgs);
}
catch (IllegalAccessException x)
{
throw new RuntimeException("IllegalAccessException during command invocation");
}
catch (InvocationTargetException x)
{
throw new CommandInvocationException(x.getTargetException());
}
}
public void enable(JASState state)
{
if (m_enable == null) state.setEnabled(true);
else
{
try
{
Object[] args = { state };
invokeEnable(m_enable, args);
}
catch (IllegalAccessException x)
{
state.setEnabled(false);
}
catch (InvocationTargetException x)
{
state.setEnabled(false);
}
}
}
public CommandProcessor getProcessor()
{
return CommandProcessor.this;
}
private Method m_command;
private Method m_enable;
}
protected class BooleanTarget implements BooleanCommandTarget
{
BooleanTarget(Method command, Method enable)
{
m_command = command;
m_enable = enable;
}
public void invoke(boolean arg)
{
CommandProcessor.this.invokeCommand(this,arg);
}
public void enable(JASState state)
{
if (m_enable == null) state.setEnabled(true);
else
{
try
{
Object[] args = { (JASCheckboxState) state };
invokeEnable(m_enable, args);
}
catch (IllegalAccessException x)
{
state.setEnabled(false);
}
catch (InvocationTargetException x)
{
state.setEnabled(false);
}
}
}
public void doCommand(boolean arg) throws CommandInvocationException
{
try
{
Object[] args = { new Boolean(arg) };
invokeCommand(m_command,args);
}
catch (IllegalAccessException x)
{
throw new RuntimeException("IllegalAccessException during command invocation");
}
catch (InvocationTargetException x)
{
throw new CommandInvocationException(x.getTargetException());
}
}
public CommandProcessor getProcessor()
{
return CommandProcessor.this;
}
private Method m_command;
private Method m_enable;
}
}