All Downloads are FREE. Search and download functionalities are using the official Maven repository.

akka.japi.pf.FSMStateFunctionBuilder Maven / Gradle / Ivy

/*
 * Copyright (C) 2009-2020 Lightbend 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
 */
@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 predicate, final FI.Apply2> apply) { return erasedEvent(null, null, predicate, apply); } /** * Add a case statement that matches on the data type and if any of the event types in the list * match or any of the event instances in the list compares equal. * * @param eventMatches a list of types or instances to match against * @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 data type to match on * @return the builder with the case statement added */ public FSMStateFunctionBuilder event( final List eventMatches, final Class dataType, final FI.Apply2> apply) { builder.match( FSM.Event.class, new FI.TypedPredicate() { @Override public boolean defined(FSM.Event e) { if (dataType != null && !dataType.isInstance(e.stateData())) return false; boolean emMatch = false; Object event = e.event(); for (Object em : eventMatches) { if (em instanceof Class) { Class emc = (Class) em; emMatch = emc.isInstance(event); } else { emMatch = event.equals(em); } if (emMatch) break; } return emMatch; } }, new FI.Apply>() { public FSM.State apply(FSM.Event e) throws Exception { @SuppressWarnings("unchecked") Q q = (Q) e.stateData(); return apply.apply(e.event(), q); } }); return this; } /** * Add a case statement that matches if any of the event types in the list match or any of the * event instances in the list compares equal. * * @param eventMatches a list of types or instances 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 */ public FSMStateFunctionBuilder event( final List eventMatches, final FI.Apply2> apply) { return event(eventMatches, null, apply); } /** * Add a case statement that matches on the data type and if the event compares equal. * * @param event an event to compare equal against * @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 data type to match on * @return the builder with the case statement added */ public FSMStateFunctionBuilder eventEquals( final P event, final Class dataType, final FI.Apply2> apply) { return erasedEvent(event, dataType, null, apply); } /** * Add a case statement that matches if event compares equal. * * @param event an event to compare equal 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 */ public

FSMStateFunctionBuilder eventEquals( final P event, final FI.Apply2> apply) { return erasedEvent(event, null, null, apply); } /** * Add a case statement that matches on any type of event. * * @param apply an action to apply to the event and state data * @return the builder with the case statement added */ public FSMStateFunctionBuilder anyEvent(final FI.Apply2> apply) { return erasedEvent(null, null, null, apply); } /** * Build a {@link scala.PartialFunction} from this builder. After this call the builder will be * reset. * * @return a PartialFunction for this builder. */ public PartialFunction, FSM.State> build() { return builder.build(); } }