sim.engine.MethodStep Maven / Gradle / Ivy
Show all versions of mason Show documentation
/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.engine;
import java.lang.reflect.*;
import sim.util.*;
/**
A Steppable which calls an underlying method using Java's reflection system. The underlying method can either have no arguments
or have one argumen (SimState), and is specified by its name as a String.
You can use MethodStep to call methods on classes that aren't Steppables. For example, if you have an object myObject
and wish to submit both its foo and bar methods (no arguments) to be called at various times when the Schedule
sees fit, you might do this:
MyClass myObject = ... ;
schedule.scheduleRepeating( ... , new MethodStep(myObject, "foo"), ...);
schedule.scheduleRepeating( ... , new MethodStep(myObject, "bar"), ...);
This will call the foo() method and bar() method to be called at the appropriate times on myObject.
You can also use MethodStep to pop up objects which aren't Steppables by their nature. For example:
JFrame myJFrame = ... ;
schedule.schedule( ... , new MethodStep(myJFrame, "show"), ...);
MethodStep can also be called on methods which expect to be passed in the Steppable's SimState argument. When
the MethodStep is called, it passes its argument to them. You do this by adding a true to the constructor:
MyClass myObject = ... ;
schedule.scheduleRepeating( ... , new MethodStep(myObject, "baz", true), ...);
schedule.scheduleRepeating( ... , new MethodStep(myObject, "quux", true), ...);
This will call the baz(SimState) method and quux(SimState) method to be called at the appropriate times on myObject.
This method is mostly to help in ease of porting: but it's not good Java. Reflection is slow and violates all sorts of design
contracts -- generally speaking, you should use anonymous Steppables intead. For example, the examples above could have instead been
written this way:
final MyClass myObject = ... ;
final JFrame myJFrame = ... ;
schedule.scheduleRepeating( ... , new Steppable() { public void step(SimState state) { myObject.foo() } }, ...);
schedule.scheduleRepeating( ... , new Steppable() { public void step(SimState state) { myObject.foo() } }, ...);
schedule.schedule( ... , new Steppable() { public void step(SimState state) { myJFrame.show() } }, ...);
schedule.scheduleRepeating( ... , new Steppable() { public void step(SimState state) { myObject.baz(state) } }, ...);
schedule.scheduleRepeating( ... , new Steppable() { public void step(SimState state) { myObject.quux(state) } }, ...);
*/
public class MethodStep implements Steppable
{
private static final long serialVersionUID = 1;
Method method;
Object object;
boolean passInSimState;
public MethodStep(Object object, String methodName)
{
this(object,methodName,false);
}
public MethodStep(Object object, String methodName, boolean passInSimState)
{
this.object = object;
this.passInSimState = passInSimState;
if (object==null)
{
throw new NullPointerException("MethodStep asked to call the method " + methodName + (passInSimState ? "\"(SimState state)" : "\"") + " on a null object");
}
try
{
if (passInSimState)
this.method = object.getClass().getMethod(methodName, new Class[]{SimState.class});
else
this.method = object.getClass().getMethod(methodName, new Class[]{});
}
catch (NoSuchMethodException ex) // make runtime exception
{
throw new RuntimeException("Could not find a public method called \"" + methodName + (passInSimState ? "\"(SimState state)" : "\"") + " in the class " + object.getClass());
}
catch (SecurityException ex)
{
throw new RuntimeException("Could not find a public method called \"" + methodName + (passInSimState ? "\"(SimState state)" : "\"") + " in the class " + object.getClass());
}
}
public void step(final SimState state)
{
try
{
if (passInSimState) method.invoke(object, new Object[] { state });
else method.invoke(object, (Object[]) null);
}
catch (IllegalAccessException ex) // make runtime exception
{
// generally should not happen -- the getMethod() method should only return public methods
throw new RuntimeException("Could not find a public method called \"" + method + (passInSimState ? "\"(SimState state)" : "\"") + " in the class " + object.getClass());
}
catch (IllegalArgumentException ex)
{
throw new RuntimeException("Could not find a public method called \"" + method + (passInSimState ? "\"(SimState state)" : "\"") + " in the class " + object.getClass());
}
catch (InvocationTargetException ex)
{
/** At the moment, Java 1.3 cannot do causes, so we don't include this for compatability reasons. Maybe we'll uncomment it later. */
/*
Throwable t = new RuntimeException("On calling \"" + methodName +"\" in the class " + object.getClass() +
", an Exception was raised in the called method.");
t.initCause(ex.getCause());
throw t;
*/
throw new RuntimeException("On calling \"" + method + (passInSimState ? "\"(SimState state)" : "\"") + " in the class " + object.getClass() +
", an Exception was raised in the called method.", ex);
}
catch (NullPointerException ex)
{
// should not be able to occur -- we've already verified that object is not null.
throw new NullPointerException("MethodStep asked to call the method " + method + (passInSimState ? "\"(SimState state)" : "\"") + " on a null object");
}
// dont' catch (ExceptionInInitializerError ex) -- let it throw through like any error
}
}