+act #3770 Added Java 8 friendly APIs for Actor and FSM
This commit is contained in:
parent
301b735516
commit
e5bcf8bfc9
28 changed files with 2204 additions and 15 deletions
36
akka-actor/src/main/java/akka/japi/pf/AbstractMatch.java
Normal file
36
akka-actor/src/main/java/akka/japi/pf/AbstractMatch.java
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
import scala.PartialFunction;
|
||||
|
||||
/**
|
||||
* Version of {@link scala.PartialFunction} that can be built during
|
||||
* runtime from Java.
|
||||
*
|
||||
* @param <I> the input type, that this PartialFunction will be applied to
|
||||
* @param <R> the return type, that the results of the application will have
|
||||
*/
|
||||
class AbstractMatch<I, R> {
|
||||
|
||||
protected final PartialFunction<I, R> statements;
|
||||
|
||||
AbstractMatch(PartialFunction<I, R> statements) {
|
||||
PartialFunction<I, R> empty = CaseStatement.empty();
|
||||
if (statements == null)
|
||||
this.statements = empty;
|
||||
else
|
||||
this.statements = statements.orElse(empty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn this {@link Match} into a {@link scala.PartialFunction}.
|
||||
*
|
||||
* @return a partial function representation ot his {@link Match}
|
||||
*/
|
||||
public PartialFunction<I, R> asPF() {
|
||||
return statements;
|
||||
}
|
||||
}
|
||||
42
akka-actor/src/main/java/akka/japi/pf/AbstractPFBuilder.java
Normal file
42
akka-actor/src/main/java/akka/japi/pf/AbstractPFBuilder.java
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
import scala.PartialFunction;
|
||||
|
||||
/**
|
||||
* A builder for {@link scala.PartialFunction}.
|
||||
*
|
||||
* @param <F> the input type, that this PartialFunction will be applied to
|
||||
* @param <T> the return type, that the results of the application will have
|
||||
*/
|
||||
abstract class AbstractPFBuilder<F, T> {
|
||||
|
||||
protected PartialFunction<F, T> statements = null;
|
||||
|
||||
protected void addStatement(PartialFunction<F, T> statement) {
|
||||
if (statements == null)
|
||||
statements = statement;
|
||||
else
|
||||
statements = statements.orElse(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link scala.PartialFunction} from this builder.
|
||||
* After this call the builder will be reset.
|
||||
*
|
||||
* @return a PartialFunction for this builder.
|
||||
*/
|
||||
public PartialFunction<F, T> build() {
|
||||
PartialFunction<F, T> empty = CaseStatement.empty();
|
||||
PartialFunction<F, T> statements = this.statements;
|
||||
|
||||
this.statements = null;
|
||||
if (statements == null)
|
||||
return empty;
|
||||
else
|
||||
return statements.orElse(empty);
|
||||
}
|
||||
}
|
||||
136
akka-actor/src/main/java/akka/japi/pf/FI.java
Normal file
136
akka-actor/src/main/java/akka/japi/pf/FI.java
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
/**
|
||||
* Class that encapsulates all the Functional Interfaces
|
||||
* used for creating partial functions.
|
||||
*/
|
||||
public final class FI {
|
||||
private FI() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for an application.
|
||||
*
|
||||
* @param <I> the input type, that this Apply will be applied to
|
||||
* @param <R> the return type, that the results of the application will have
|
||||
*/
|
||||
public static interface Apply<I, R> {
|
||||
/**
|
||||
* The application to perform.
|
||||
*
|
||||
* @param i an instance that the application is performed on
|
||||
* @return the result of the application
|
||||
*/
|
||||
public abstract R apply(I i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for an application.
|
||||
*
|
||||
* @param <I1> the first input type, that this Apply will be applied to
|
||||
* @param <I2> the second input type, that this Apply will be applied to
|
||||
* @param <R> the return type, that the results of the application will have
|
||||
*/
|
||||
public static interface Apply2<I1, I2, R> {
|
||||
/**
|
||||
* The application to perform.
|
||||
*
|
||||
* @param i1 an instance that the application is performed on
|
||||
* @param i2 an instance that the application is performed on
|
||||
* @return the result of the application
|
||||
*/
|
||||
public abstract R apply(I1 i1, I2 i2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for a predicate.
|
||||
*
|
||||
* @param <T> the type that the predicate will operate on.
|
||||
*/
|
||||
public static interface TypedPredicate<T> {
|
||||
/**
|
||||
* The predicate to evaluate.
|
||||
*
|
||||
* @param t an instance that the predicate is evaluated on.
|
||||
* @return the result of the predicate
|
||||
*/
|
||||
public abstract boolean defined(T t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for an application.
|
||||
*
|
||||
* @param <I> the input type, that this Apply will be applied to
|
||||
*/
|
||||
public static interface UnitApply<I> {
|
||||
/**
|
||||
* The application to perform.
|
||||
*
|
||||
* @param i an instance that the application is performed on
|
||||
*/
|
||||
public abstract void apply(I i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for an application.
|
||||
*
|
||||
* @param <I1> the first input type, that this Apply will be applied to
|
||||
* @param <I2> the second input type, that this Apply will be applied to
|
||||
*/
|
||||
public static interface UnitApply2<I1, I2> {
|
||||
/**
|
||||
* The application to perform.
|
||||
*
|
||||
* @param i1 an instance that the application is performed on
|
||||
* @param i2 an instance that the application is performed on
|
||||
*/
|
||||
public abstract void apply(I1 i1, I2 i2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for an application.
|
||||
*
|
||||
* @param <I1> the first input type, that this Apply will be applied to
|
||||
* @param <I2> the second input type, that this Apply will be applied to
|
||||
* @param <I3> the third input type, that this Apply will be applied to
|
||||
*/
|
||||
public static interface UnitApply3<I1, I2, I3> {
|
||||
/**
|
||||
* The application to perform.
|
||||
*
|
||||
* @param i1 an instance that the application is performed on
|
||||
* @param i2 an instance that the application is performed on
|
||||
* @param i3 an instance that the application is performed on
|
||||
*/
|
||||
public abstract void apply(I1 i1, I2 i2, I3 i3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for an application.
|
||||
*/
|
||||
public static interface UnitApplyVoid {
|
||||
/**
|
||||
* The application to perform.
|
||||
*/
|
||||
public abstract void apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Package scoped functional interface for a predicate. Used internally to match against arbitrary types.
|
||||
*/
|
||||
static interface Predicate {
|
||||
/**
|
||||
* The predicate to evaluate.
|
||||
*
|
||||
* @param o an instance that the predicate is evaluated on.
|
||||
* @return the result of the predicate
|
||||
*/
|
||||
public abstract boolean defined(Object o);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
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 <S> the state type
|
||||
* @param <D> the data type
|
||||
*/
|
||||
public class FSMStateFunctionBuilder<S, D> {
|
||||
|
||||
private PFBuilder<FSM.Event<D>, FSM.State<S, D>> builder =
|
||||
new PFBuilder<FSM.Event<D>, FSM.State<S, D>>();
|
||||
|
||||
/**
|
||||
* 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 <P> the event type to match on
|
||||
* @param <Q> the data type to match on
|
||||
* @return the builder with the case statement added
|
||||
*/
|
||||
public <P, Q> FSMStateFunctionBuilder<S, D> event(final Class<P> eventType,
|
||||
final Class<Q> dataType,
|
||||
final FI.Apply2<P, Q, FSM.State<S, D>> apply) {
|
||||
builder.match(FSM.Event.class,
|
||||
new FI.TypedPredicate<FSM.Event>() {
|
||||
@Override
|
||||
public boolean defined(FSM.Event e) {
|
||||
return eventType.isInstance(e.event()) && dataType.isInstance(e.stateData());
|
||||
}
|
||||
},
|
||||
new FI.Apply<FSM.Event, FSM.State<S, D>>() {
|
||||
public FSM.State<S, D> apply(FSM.Event e) {
|
||||
@SuppressWarnings("unchecked")
|
||||
P p = (P) e.event();
|
||||
@SuppressWarnings("unchecked")
|
||||
Q q = (Q) e.stateData();
|
||||
return apply.apply(p, q);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <Q> the data type to match on
|
||||
* @return the builder with the case statement added
|
||||
*/
|
||||
public <Q> FSMStateFunctionBuilder<S, D> event(final List<Object> eventMatches,
|
||||
final Class<Q> dataType,
|
||||
final FI.Apply<Q, FSM.State<S, D>> apply) {
|
||||
builder.match(FSM.Event.class,
|
||||
new FI.TypedPredicate<FSM.Event>() {
|
||||
@Override
|
||||
public boolean defined(FSM.Event e) {
|
||||
if (!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<FSM.Event, FSM.State<S, D>>() {
|
||||
public FSM.State<S, D> apply(FSM.Event e) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Q q = (Q) e.stateData();
|
||||
return apply.apply(q);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<S, D> anyEvent(final FI.Apply2<Object, D, FSM.State<S, D>> apply) {
|
||||
builder.match(FSM.Event.class,
|
||||
new FI.Apply<FSM.Event, FSM.State<S, D>>() {
|
||||
public FSM.State<S, D> apply(FSM.Event e) {
|
||||
@SuppressWarnings("unchecked")
|
||||
D d = (D) e.stateData();
|
||||
return apply.apply(e.event(), d);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.Event<D>, FSM.State<S, D>> build() {
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
121
akka-actor/src/main/java/akka/japi/pf/FSMStopBuilder.java
Normal file
121
akka-actor/src/main/java/akka/japi/pf/FSMStopBuilder.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
import akka.actor.FSM;
|
||||
import scala.PartialFunction;
|
||||
import scala.runtime.BoxedUnit;
|
||||
|
||||
/**
|
||||
* Builder used to create a partial function for {@link akka.actor.FSM#onTermination}.
|
||||
*
|
||||
* @param <S> the state type
|
||||
* @param <D> the data type
|
||||
*/
|
||||
public class FSMStopBuilder<S, D> {
|
||||
|
||||
private UnitPFBuilder<FSM.StopEvent<S, D>> builder =
|
||||
new UnitPFBuilder<FSM.StopEvent<S, D>>();
|
||||
|
||||
/**
|
||||
* Add a case statement that matches on an {@link FSM.Reason}.
|
||||
*
|
||||
* @param reason the reason for the termination
|
||||
* @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 FSMStopBuilder<S, D> stop(final FSM.Reason reason,
|
||||
final FI.UnitApply2<S, D> apply) {
|
||||
builder.match(FSM.StopEvent.class,
|
||||
new FI.TypedPredicate<FSM.StopEvent>() {
|
||||
@Override
|
||||
public boolean defined(FSM.StopEvent e) {
|
||||
return reason.equals(e.reason());
|
||||
}
|
||||
},
|
||||
new FI.UnitApply<FSM.StopEvent>() {
|
||||
public void apply(FSM.StopEvent e) {
|
||||
@SuppressWarnings("unchecked")
|
||||
S s = (S) e.currentState();
|
||||
@SuppressWarnings("unchecked")
|
||||
D d = (D) e.stateData();
|
||||
apply.apply(s, d);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a case statement that matches on a reason type.
|
||||
*
|
||||
* @param reasonType the reason type to match on
|
||||
* @param apply an action to apply to the reason, event and state data if there is a match
|
||||
* @param <P> the reason type to match on
|
||||
* @return the builder with the case statement added
|
||||
*/
|
||||
public <P extends FSM.Reason> FSMStopBuilder<S, D> stop(final Class<P> reasonType,
|
||||
final FI.UnitApply3<P, S, D> apply) {
|
||||
return this.stop(reasonType,
|
||||
new FI.TypedPredicate<P>() {
|
||||
@Override
|
||||
public boolean defined(P p) {
|
||||
return true;
|
||||
}
|
||||
}, apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a case statement that matches on a reason type and a predicate.
|
||||
*
|
||||
* @param reasonType the reason type to match on
|
||||
* @param apply an action to apply to the reason, event and state data if there is a match
|
||||
* @param predicate a predicate that will be evaluated on the reason if the type matches
|
||||
* @param <P> the reason type to match on
|
||||
* @return the builder with the case statement added
|
||||
*/
|
||||
public <P extends FSM.Reason> FSMStopBuilder<S, D> stop(final Class<P> reasonType,
|
||||
final FI.TypedPredicate<P> predicate,
|
||||
final FI.UnitApply3<P, S, D> apply) {
|
||||
builder.match(FSM.StopEvent.class,
|
||||
new FI.TypedPredicate<FSM.StopEvent>() {
|
||||
@Override
|
||||
public boolean defined(FSM.StopEvent e) {
|
||||
if (reasonType.isInstance(e.reason())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
P p = (P) e.reason();
|
||||
return predicate.defined(p);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
new FI.UnitApply<FSM.StopEvent>() {
|
||||
public void apply(FSM.StopEvent e) {
|
||||
@SuppressWarnings("unchecked")
|
||||
P p = (P) e.reason();
|
||||
@SuppressWarnings("unchecked")
|
||||
S s = (S) e.currentState();
|
||||
@SuppressWarnings("unchecked")
|
||||
D d = (D) e.stateData();
|
||||
apply.apply(p, s, d);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.StopEvent<S, D>, BoxedUnit> build() {
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
import scala.PartialFunction;
|
||||
import scala.runtime.BoxedUnit;
|
||||
import scala.Tuple2;
|
||||
|
||||
/**
|
||||
* Builder used to create a partial function for {@link akka.actor.FSM#onTransition}.
|
||||
*
|
||||
* @param <S> the state type
|
||||
*/
|
||||
public class FSMTransitionHandlerBuilder<S> {
|
||||
|
||||
private UnitPFBuilder<Tuple2<S, S>> builder =
|
||||
new UnitPFBuilder<Tuple2<S, S>>();
|
||||
|
||||
/**
|
||||
* Add a case statement that matches on a from state and a to state.
|
||||
*
|
||||
* @param fromState the from state to match on
|
||||
* @param toState the to state to match on
|
||||
* @param apply an action to apply when the states match
|
||||
* @return the builder with the case statement added
|
||||
*/
|
||||
public FSMTransitionHandlerBuilder<S> state(final S fromState,
|
||||
final S toState,
|
||||
final FI.UnitApplyVoid apply) {
|
||||
builder.match(Tuple2.class,
|
||||
new FI.TypedPredicate<Tuple2>() {
|
||||
@Override
|
||||
public boolean defined(Tuple2 t) {
|
||||
return fromState.equals(t._1()) && toState.equals(t._2());
|
||||
}
|
||||
},
|
||||
new FI.UnitApply<Tuple2>() {
|
||||
@Override
|
||||
public void apply(Tuple2 t) {
|
||||
apply.apply();
|
||||
}
|
||||
}
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link scala.PartialFunction} from this builder.
|
||||
* After this call the builder will be reset.
|
||||
*
|
||||
* @return a PartialFunction for this builder.
|
||||
*/
|
||||
public PartialFunction<Tuple2<S, S>, BoxedUnit> build() {
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
79
akka-actor/src/main/java/akka/japi/pf/Match.java
Normal file
79
akka-actor/src/main/java/akka/japi/pf/Match.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
import scala.MatchError;
|
||||
import scala.PartialFunction;
|
||||
|
||||
/**
|
||||
* Version of {@link scala.PartialFunction} that can be built during
|
||||
* runtime from Java.
|
||||
*
|
||||
* @param <I> the input type, that this PartialFunction will be applied to
|
||||
* @param <R> the return type, that the results of the application will have
|
||||
*/
|
||||
public class Match<I, R> extends AbstractMatch<I, R> {
|
||||
|
||||
/**
|
||||
* Convenience function to create a {@link PFBuilder} with the first
|
||||
* case statement added.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param apply an action to apply to the argument if the type matches
|
||||
* @return a builder with the case statement added
|
||||
* @see PFBuilder#match(Class, FI.Apply)
|
||||
*/
|
||||
public static final <F, T, P> PFBuilder<F, T> match(final Class<P> type,
|
||||
final FI.Apply<P, T> apply) {
|
||||
return new PFBuilder<F, T>().match(type, apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to create a {@link PFBuilder} with the first
|
||||
* case statement added.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param predicate a predicate that will be evaluated on the argument if the type matches
|
||||
* @param apply an action to apply to the argument if the type matches
|
||||
* @return a builder with the case statement added
|
||||
* @see PFBuilder#match(Class, FI.TypedPredicate, FI.Apply)
|
||||
*/
|
||||
public static <F, T, P> PFBuilder<F, T> match(final Class<P> type,
|
||||
final FI.TypedPredicate<P> predicate,
|
||||
final FI.Apply<P, T> apply) {
|
||||
return new PFBuilder<F, T>().match(type, predicate, apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Match} from the builder.
|
||||
*
|
||||
* @param builder a builder representing the partial function
|
||||
* @return a {@link Match} that can be reused
|
||||
*/
|
||||
public static final <F, T> Match<F, T> create(PFBuilder<F, T> builder) {
|
||||
return new Match<F, T>(builder.build());
|
||||
}
|
||||
|
||||
Match(PartialFunction<I, R> statements) {
|
||||
super(statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to make the Java code more readable.
|
||||
*
|
||||
* <pre><code>
|
||||
* Matcher<X, Y> matcher = Matcher.create(...);
|
||||
*
|
||||
* Y someY = matcher.match(obj);
|
||||
* </code></pre>
|
||||
*
|
||||
* @param i the argument to apply the match to
|
||||
* @return the result of the application
|
||||
* @throws MatchError if there is no match
|
||||
*/
|
||||
public R match(I i) throws MatchError {
|
||||
return statements.apply(i);
|
||||
}
|
||||
}
|
||||
81
akka-actor/src/main/java/akka/japi/pf/PFBuilder.java
Normal file
81
akka-actor/src/main/java/akka/japi/pf/PFBuilder.java
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
/**
|
||||
* A builder for {@link scala.PartialFunction}.
|
||||
*
|
||||
* @param <I> the input type, that this PartialFunction will be applied to
|
||||
* @param <R> the return type, that the results of the application will have
|
||||
*/
|
||||
public final class PFBuilder<I, R> extends AbstractPFBuilder<I, R> {
|
||||
|
||||
/**
|
||||
* Create a PFBuilder.
|
||||
*/
|
||||
public PFBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new case statement to this builder.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param apply an action to apply to the argument if the type matches
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public <P> PFBuilder<I, R> match(final Class<P> type, FI.Apply<P, R> apply) {
|
||||
addStatement(new CaseStatement<I, P, R>(
|
||||
new FI.Predicate() {
|
||||
@Override
|
||||
public boolean defined(Object o) {
|
||||
return type.isInstance(o);
|
||||
}
|
||||
}, apply));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new case statement to this builder.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param predicate a predicate that will be evaluated on the argument if the type matches
|
||||
* @param apply an action to apply to the argument if the type matches and the predicate returns true
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public <P> PFBuilder<I, R> match(final Class<P> type,
|
||||
final FI.TypedPredicate<P> predicate,
|
||||
final FI.Apply<P, R> apply) {
|
||||
addStatement(new CaseStatement<I, P, R>(
|
||||
new FI.Predicate() {
|
||||
@Override
|
||||
public boolean defined(Object o) {
|
||||
if (!type.isInstance(o))
|
||||
return false;
|
||||
else {
|
||||
@SuppressWarnings("unchecked")
|
||||
P p = (P) o;
|
||||
return predicate.defined(p);
|
||||
}
|
||||
}
|
||||
}, apply));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new case statement to this builder, that matches any argument.
|
||||
* @param apply an action to apply to the argument
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public PFBuilder<I, R> matchAny(final FI.Apply<Object, R> apply) {
|
||||
addStatement(new CaseStatement<I, Object, R>(
|
||||
new FI.Predicate() {
|
||||
@Override
|
||||
public boolean defined(Object o) {
|
||||
return true;
|
||||
}
|
||||
}, apply));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
58
akka-actor/src/main/java/akka/japi/pf/ReceiveBuilder.java
Normal file
58
akka-actor/src/main/java/akka/japi/pf/ReceiveBuilder.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
/**
|
||||
* Used for building a partial function for {@link akka.actor.Actor#receive() Actor.receive()}.
|
||||
*
|
||||
* There is both a match on type only, and a match on type and predicate.
|
||||
*
|
||||
* Inside an actor you can use it like this with Java 8 to define your receive method:
|
||||
* <pre>
|
||||
* @Override
|
||||
* public PartialFunction<Object, BoxedUnit> receive() {
|
||||
* return ReceiveBuilder.
|
||||
* match(Double.class, d -> {
|
||||
* sender().tell(d.isNaN() ? 0 : d, self());
|
||||
* }).
|
||||
* match(Integer.class, i -> {
|
||||
* sender().tell(i * 10, self());
|
||||
* }).
|
||||
* match(String.class, s -> s.startsWith("foo"), s -> {
|
||||
* sender().tell(s.toUpperCase(), self());
|
||||
* }).build();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class ReceiveBuilder {
|
||||
private ReceiveBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link UnitPFBuilder} with a case statement added.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param apply an action to apply to the argument if the type matches
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public static <P> UnitPFBuilder<Object> match(final Class<P> type, FI.UnitApply<P> apply) {
|
||||
return UnitMatch.match(type, apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link UnitPFBuilder} with a case statement added.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param predicate a predicate that will be evaluated on the argument if the type matches
|
||||
* @param apply an action to apply to the argument if the type matches and the predicate returns true
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public static <P> UnitPFBuilder<Object> match(final Class<P> type,
|
||||
FI.TypedPredicate<P> predicate,
|
||||
FI.UnitApply<P> apply) {
|
||||
return UnitMatch.match(type, predicate, apply);
|
||||
}
|
||||
}
|
||||
79
akka-actor/src/main/java/akka/japi/pf/UnitMatch.java
Normal file
79
akka-actor/src/main/java/akka/japi/pf/UnitMatch.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
import scala.MatchError;
|
||||
import scala.PartialFunction;
|
||||
import scala.runtime.BoxedUnit;
|
||||
|
||||
/**
|
||||
* Version of {@link scala.PartialFunction} that can be built during
|
||||
* runtime from Java.
|
||||
* This is a specialized version of {@link UnitMatch} to map java
|
||||
* void methods to {@link scala.runtime.BoxedUnit}.
|
||||
*
|
||||
* @param <I> the input type, that this PartialFunction will be applied to
|
||||
*/
|
||||
public class UnitMatch<I> extends AbstractMatch<I, BoxedUnit> {
|
||||
|
||||
/**
|
||||
* Convenience function to create a {@link UnitPFBuilder} with the first
|
||||
* case statement added.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param apply an action to apply to the argument if the type matches
|
||||
* @return a builder with the case statement added
|
||||
* @see UnitPFBuilder#match(Class, FI.UnitApply)
|
||||
*/
|
||||
public static final <F, P> UnitPFBuilder<F> match(final Class<P> type, FI.UnitApply<P> apply) {
|
||||
return new UnitPFBuilder<F>().match(type, apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to create a {@link UnitPFBuilder} with the first
|
||||
* case statement added.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param predicate a predicate that will be evaluated on the argument if the type matches
|
||||
* @param apply an action to apply to the argument if the type and predicate matches
|
||||
* @return a builder with the case statement added
|
||||
* @see UnitPFBuilder#match(Class, FI.TypedPredicate, FI.UnitApply)
|
||||
*/
|
||||
public static <F, P> UnitPFBuilder<F> match(final Class<P> type,
|
||||
final FI.TypedPredicate<P> predicate,
|
||||
final FI.UnitApply<P> apply) {
|
||||
return new UnitPFBuilder<F>().match(type, predicate, apply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link UnitMatch} from the builder.
|
||||
*
|
||||
* @param builder a builder representing the partial function
|
||||
* @return a {@link UnitMatch} that can be reused
|
||||
*/
|
||||
public static <F> UnitMatch<F> create(UnitPFBuilder<F> builder) {
|
||||
return new UnitMatch<F>(builder.build());
|
||||
}
|
||||
|
||||
private UnitMatch(PartialFunction<I, BoxedUnit> statements) {
|
||||
super(statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to make the Java code more readable.
|
||||
*
|
||||
* <pre><code>
|
||||
* UnitMatcher<X> matcher = UnitMatcher.create(...);
|
||||
*
|
||||
* matcher.match(obj);
|
||||
* </code></pre>
|
||||
*
|
||||
* @param i the argument to apply the match to
|
||||
* @throws scala.MatchError if there is no match
|
||||
*/
|
||||
public void match(I i) throws MatchError {
|
||||
statements.apply(i);
|
||||
}
|
||||
}
|
||||
85
akka-actor/src/main/java/akka/japi/pf/UnitPFBuilder.java
Normal file
85
akka-actor/src/main/java/akka/japi/pf/UnitPFBuilder.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.japi.pf;
|
||||
|
||||
import scala.runtime.BoxedUnit;
|
||||
|
||||
/**
|
||||
* A builder for {@link scala.PartialFunction}.
|
||||
* This is a specialized version of {@link PFBuilder} to map java
|
||||
* void methods to {@link scala.runtime.BoxedUnit}.
|
||||
*
|
||||
* @param <I> the input type, that this PartialFunction to be applied to
|
||||
*/
|
||||
public final class UnitPFBuilder<I> extends AbstractPFBuilder<I, BoxedUnit> {
|
||||
|
||||
/**
|
||||
* Create a UnitPFBuilder.
|
||||
*/
|
||||
public UnitPFBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new case statement to this builder.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param apply an action to apply to the argument if the type matches
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public <P> UnitPFBuilder<I> match(final Class<P> type,
|
||||
final FI.UnitApply<P> apply) {
|
||||
addStatement(new UnitCaseStatement<I, P>(
|
||||
new FI.Predicate() {
|
||||
@Override
|
||||
public boolean defined(Object o) {
|
||||
return type.isInstance(o);
|
||||
}
|
||||
}, apply));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new case statement to this builder.
|
||||
*
|
||||
* @param type a type to match the argument against
|
||||
* @param predicate a predicate that will be evaluated on the argument if the type matches
|
||||
* @param apply an action to apply to the argument if the type matches and the predicate returns true
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public <P> UnitPFBuilder<I> match(final Class<P> type,
|
||||
final FI.TypedPredicate<P> predicate,
|
||||
final FI.UnitApply<P> apply) {
|
||||
addStatement(new UnitCaseStatement<I, P>(
|
||||
new FI.Predicate() {
|
||||
@Override
|
||||
public boolean defined(Object o) {
|
||||
if (!type.isInstance(o))
|
||||
return false;
|
||||
else {
|
||||
@SuppressWarnings("unchecked")
|
||||
P p = (P) o;
|
||||
return predicate.defined(p);
|
||||
}
|
||||
}
|
||||
}, apply));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new case statement to this builder, that matches any argument.
|
||||
* @param apply an action to apply to the argument
|
||||
* @return a builder with the case statement added
|
||||
*/
|
||||
public UnitPFBuilder<I> matchAny(final FI.UnitApply<Object> apply) {
|
||||
addStatement(new UnitCaseStatement<I, Object>(
|
||||
new FI.Predicate() {
|
||||
@Override
|
||||
public boolean defined(Object o) {
|
||||
return true;
|
||||
}
|
||||
}, apply));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue