akka.japi.pf.FSMStateFunctionBuilder Maven / Gradle / Ivy
/**
* Copyright (C) 2009-2014 Typesafe Inc.
*/
package akka.japi.pf;
import akka.actor.FSM;
import scala.PartialFunction;
import java.util.List;
/**
* Builder used to create a partial function for {@link akka.actor.FSM#whenUnhandled}.
*
* @param the state type
* @param the data type
*
* This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing.
*/
@SuppressWarnings("rawtypes")
public class FSMStateFunctionBuilder {
private PFBuilder, FSM.State> builder =
new PFBuilder, FSM.State>();
/**
* An erased processing of the event matcher. The compile time checks are enforced
* by the public typed versions.
*
* It works like this.
*
* If eventOrType or dataOrType is a Class, then we do a isInstance check,
* otherwise we do an equals check. The null value compares true for anything.
* If the predicate is null, it is skipped otherwise the predicate has to match
* as well.
*
* @param eventOrType an event or a type to match against
* @param dataOrType a data instance or a type to match against
* @param predicate a predicate to match against
* @param apply an action to apply to the event and state data if there is a match
* @return the builder with the case statement added
*/
private FSMStateFunctionBuilder erasedEvent(final Object eventOrType,
final Object dataOrType,
final FI.TypedPredicate2 predicate,
final FI.Apply2 apply) {
builder.match(FSM.Event.class,
new FI.TypedPredicate() {
@Override
public boolean defined(FSM.Event e) {
boolean res = true;
if (eventOrType != null) {
if (eventOrType instanceof Class) {
Class eventType = (Class) eventOrType;
res = eventType.isInstance(e.event());
}
else {
res = eventOrType.equals(e.event());
}
}
if (res && dataOrType != null) {
if (dataOrType instanceof Class) {
Class dataType = (Class) dataOrType;
res = dataType.isInstance(e.stateData());
}
else {
res = dataOrType.equals(e.stateData());
}
}
if (res && predicate != null) {
@SuppressWarnings("unchecked")
boolean ures = predicate.defined(e.event(), e.stateData());
res = ures;
}
return res;
}
},
new FI.Apply>() {
public FSM.State apply(FSM.Event e) throws Exception {
@SuppressWarnings("unchecked")
FSM.State res = (FSM.State) apply.apply(e.event(), e.stateData());
return res;
}
}
);
return this;
}
/**
* Add a case statement that matches on an event and data type and a predicate.
*
* @param eventType the event type to match on
* @param dataType the data type to match on
* @param predicate a predicate to evaluate on the matched types
* @param apply an action to apply to the event and state data if there is a match
* @param the event type to match on
* @param the data type to match on
* @return the builder with the case statement added
*/
public final FSMStateFunctionBuilder event(final Class
eventType,
final Class dataType,
final FI.TypedPredicate2 predicate,
final FI.Apply2
> apply) {
erasedEvent(eventType, dataType, predicate, apply);
return this;
}
/**
* Add a case statement that matches on an event and data type.
*
* @param eventType the event type to match on
* @param dataType the data type to match on
* @param apply an action to apply to the event and state data if there is a match
* @param
the event type to match on
* @param the data type to match on
* @return the builder with the case statement added
*/
public FSMStateFunctionBuilder event(final Class
eventType,
final Class dataType,
final FI.Apply2> apply) {
return erasedEvent(eventType, dataType, null, apply);
}
/**
* Add a case statement that matches if the event type and predicate matches.
*
* @param eventType the event type to match on
* @param predicate a predicate that will be evaluated on the data and the event
* @param apply an action to apply to the event and state data if there is a match
* @return the builder with the case statement added
*/
public
FSMStateFunctionBuilder event(final Class
eventType,
final FI.TypedPredicate2
predicate,
final FI.Apply2
> apply) {
return erasedEvent(eventType, null, predicate, apply);
}
/**
* Add a case statement that matches if the event type and predicate matches.
*
* @param eventType the event type to match on
* @param apply an action to apply to the event and state data if there is a match
* @return the builder with the case statement added
*/
public
FSMStateFunctionBuilder event(final Class
eventType,
final FI.Apply2
> apply) {
return erasedEvent(eventType, null, null, apply);
}
/**
* Add a case statement that matches if the predicate matches.
*
* @param predicate a predicate that will be evaluated on the data and the event
* @param apply an action to apply to the event and state data if there is a match
* @return the builder with the case statement added
*/
public FSMStateFunctionBuilder event(final FI.TypedPredicate2