Hi,
I think your state machine is wonderful. However, much too complex for me at this point (much too much features ;-)).
But I was writing my own state machine and I keep looking to yours for guidance ;-D.
My State machine usage has the following properties:
- Input is a stream of characters that fall into specific classes
- Currently I am using the characters as input to a Conditional (your .when()) and devoid the use of events altogether
- My Conditional is simply called "CharTest" and is instantiated with a class (enum type value) to match against.
When I look at your state machine (Squirrel) I would have two options for using it:
- Turn the characters into classes (enum values) BEFORE I feed them into the machine, which renders them as Events.
- Do not use events at all and only use when, create Conditions instantiated with matched classes and use isSatisfied() to test for their equivalence. Obtain the input from the Context which would be a custom object. Obtain any flags I have from the context as well.
Currently I have a cascade of 'tests' (descendents of my Conditional) that I can combine using e.g. new AndTest(new CharTest(CharType.MODE), new NegTest(new FlagTest(ALT))) which is my little way of not having to write any additional code. It reminds me of the Hamcrest unit test matchers for JUnit. (((.In Hamcrest you can write this as assertThat(CharType.from(input), both(equalTo(CharType.MODE)).and(not(ALT.value())) or something of the kind..))).
In the form of Squirrel's Conditions this would be nearly identical to what I have now.
class CharCondition extends Condition {
CharType matchedClass;
public CharCondition(CharType matchedClass) {
this.matchedClass = matchedClass;
}
public boolean isSatisfied(Context c) {
return c != null && CharType.from(c.getInput()) == matchedClass;
}
}
Then I could even have a EnumMap that links the CharTypes to the instantiated matcher classes ;-).
Time to write some code! :D.