public class Call extends AbstractFaAction
is an FaAction
that forwards the callback to its invoke()
method to a named method by using
reflection.
Creating a Dfa
with many different callbacks
(FaAction
s)
can be tedious, because each action must be in its own
class. Although anonymous classes help to reduce the code clutter,
the actions often must communicate through a common state. Doing so
in a way that the Dfa
can be used in parallel threads
requires each action to retrieve the common state from DfaRun.clientData
and cast it to the type it is known to be
— tedious again.
The Call
action helps to get rid of the tedious
steps described above. Instead of one class per action, just write
one class, say Worker
, and implement each action as a
method. The name of the actions does not matter, they just have to
be public
and must have the same signature as FaAction.invoke(java.lang.StringBuilder, int, monq.jfa.DfaRun)
. To use the resulting Worker
in a Dfa
, two things need to be done:
Call
objects with the action methods' names when
creating the Nfa
.Worker
in the
DfaRun.clientData
field of the DfaRun
object that operates the Dfa
compiled from the
Nfa
.When called, the invoke()
method of a Call
object will retrieve the
Worker
from the clientData
field of its
third parameter. Then it uses reflection to find the action to call
according to the name specified in the constructor of the
Call
object.
Example:
public class Worker { public void invokeOne(StringBuilder sb, int start, DfaRun r) { ... } public void invokeTwo(StringBuilder sb, int start, DfaRun r) { ... } } // somewhere else create the Dfa and the DfaRun Dfa dfa = new Nfa("myRe1", new Call("invokeOne")) .or("myRe2", new Call("invokeTwo")) ... DfaRun run = new DfaRun(dfa); run.clientData = new Worker(); ...
Note: I would be interested to hear opinions or measurements whether this approach, using reflection, is slower than using one class per action.
Constructor and Description |
---|
Call(java.lang.String methodName)
creates a
Call that will forward the call to a
method with the given methodName . |
Modifier and Type | Method and Description |
---|---|
boolean |
equals(java.lang.Object _o)
returns
true if and only if _o is a
Call object and invokes the same method name. |
java.lang.String |
getMethodName()
returns the method name specified in the constructor.
|
int |
hashCode() |
void |
invoke(java.lang.StringBuilder out,
int start,
DfaRun run)
calls the method specified in the constructor by finding it in
run.clientData via reflection. |
mergeWith, setPriority
public Call(java.lang.String methodName)
creates a Call
that will forward the call to a
method with the given methodName
.
public void invoke(java.lang.StringBuilder out, int start, DfaRun run) throws CallbackException
calls the method specified in the constructor by finding it in
run.clientData
via reflection.
CallbackException
- if the method called throws it. In
that case the exception is rethrown.java.lang.IllegalArgumentException
- if the named method cannot be
found in run.clientData
, if the invocation results
in an IllegalAccessException
or if the method called
throws a checked exception other than a
CallbackException
.public java.lang.String getMethodName()
returns the method name specified in the constructor.
public boolean equals(java.lang.Object _o)
returns true
if and only if _o
is a
Call
object and invokes the same method name.
equals
in class java.lang.Object
public int hashCode()
hashCode
in class java.lang.Object