Make the AbstractBehavior builder mutable (#26309)
* Make the AbstractBehavior builder mutable #26260 * Use mutable builder style in first sample, mention that fluent is an option * A bit of rework of the Java builders: * onAnyMessage added * use the japi SAMs throughout in the APIs * avoid wrapping the japi functions in Scala functions for the most common cases * more Java test coverage * Not just any exception * Works on 2.11 as well as 2.12
This commit is contained in:
parent
ddada9a8e1
commit
8fabb73f2b
22 changed files with 391 additions and 268 deletions
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
package akka.actor.typed.javadsl;
|
package akka.actor.typed.javadsl;
|
||||||
|
|
||||||
|
import akka.actor.testkit.typed.javadsl.TestKitJunitResource;
|
||||||
|
import akka.actor.testkit.typed.javadsl.TestProbe;
|
||||||
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.scalatest.junit.JUnitSuite;
|
import org.scalatest.junit.JUnitSuite;
|
||||||
|
|
||||||
|
|
@ -15,9 +18,13 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
import static akka.actor.typed.javadsl.Behaviors.same;
|
import static akka.actor.typed.javadsl.Behaviors.same;
|
||||||
import static akka.actor.typed.javadsl.Behaviors.stopped;
|
import static akka.actor.typed.javadsl.Behaviors.stopped;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/** Test creating [[Behavior]]s using [[BehaviorBuilder]] */
|
/** Test creating [[Behavior]]s using [[BehaviorBuilder]] */
|
||||||
public class BehaviorBuilderTest extends JUnitSuite {
|
public class BehaviorBuilderTest extends JUnitSuite {
|
||||||
|
|
||||||
|
@ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource();
|
||||||
|
|
||||||
interface Message {}
|
interface Message {}
|
||||||
|
|
||||||
static final class One implements Message {
|
static final class One implements Message {
|
||||||
|
|
@ -28,7 +35,6 @@ public class BehaviorBuilderTest extends JUnitSuite {
|
||||||
|
|
||||||
static final class MyList<T> extends ArrayList<T> implements Message {};
|
static final class MyList<T> extends ArrayList<T> implements Message {};
|
||||||
|
|
||||||
@Test
|
|
||||||
public void shouldCompile() {
|
public void shouldCompile() {
|
||||||
Behavior<Message> b =
|
Behavior<Message> b =
|
||||||
Behaviors.receive(Message.class)
|
Behaviors.receive(Message.class)
|
||||||
|
|
@ -54,6 +60,86 @@ public class BehaviorBuilderTest extends JUnitSuite {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void caseSelectedInOrderAdded() {
|
||||||
|
final TestProbe<Object> probe = testKit.createTestProbe();
|
||||||
|
Behavior<Object> behavior =
|
||||||
|
BehaviorBuilder.create()
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
(context, msg) -> {
|
||||||
|
probe.ref().tell("handler 1: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
(context, msg) -> {
|
||||||
|
probe.ref().tell("handler 2: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ActorRef<Object> ref = testKit.spawn(behavior);
|
||||||
|
ref.tell("message");
|
||||||
|
probe.expectMessage("handler 1: message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleMessageBasedOnEquality() {
|
||||||
|
final TestProbe<Object> probe = testKit.createTestProbe();
|
||||||
|
Behavior<Object> behavior =
|
||||||
|
BehaviorBuilder.create()
|
||||||
|
.onMessageEquals(
|
||||||
|
"message",
|
||||||
|
(context) -> {
|
||||||
|
probe.ref().tell("got it");
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ActorRef<Object> ref = testKit.spawn(behavior);
|
||||||
|
ref.tell("message");
|
||||||
|
probe.expectMessage("got it");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void applyPredicate() {
|
||||||
|
final TestProbe<Object> probe = testKit.createTestProbe();
|
||||||
|
Behavior<Object> behavior =
|
||||||
|
BehaviorBuilder.create()
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
(msg) -> "other".equals(msg),
|
||||||
|
(context, msg) -> {
|
||||||
|
probe.ref().tell("handler 1: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
(context, msg) -> {
|
||||||
|
probe.ref().tell("handler 2: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ActorRef<Object> ref = testKit.spawn(behavior);
|
||||||
|
ref.tell("message");
|
||||||
|
probe.expectMessage("handler 2: message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void catchAny() {
|
||||||
|
final TestProbe<Object> probe = testKit.createTestProbe();
|
||||||
|
Behavior<Object> behavior =
|
||||||
|
BehaviorBuilder.create()
|
||||||
|
.onAnyMessage(
|
||||||
|
(context, msg) -> {
|
||||||
|
probe.ref().tell(msg);
|
||||||
|
return same();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ActorRef<Object> ref = testKit.spawn(behavior);
|
||||||
|
ref.tell("message");
|
||||||
|
probe.expectMessage("message");
|
||||||
|
}
|
||||||
|
|
||||||
interface CounterMessage {};
|
interface CounterMessage {};
|
||||||
|
|
||||||
static final class Increase implements CounterMessage {};
|
static final class Increase implements CounterMessage {};
|
||||||
|
|
@ -92,6 +178,12 @@ public class BehaviorBuilderTest extends JUnitSuite {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImmutableCounter() {
|
public void testImmutableCounter() {
|
||||||
Behavior<CounterMessage> immutable = immutableCounter(0);
|
ActorRef<CounterMessage> ref = testKit.spawn(immutableCounter(0));
|
||||||
|
TestProbe<Got> probe = testKit.createTestProbe();
|
||||||
|
ref.tell(new Get(probe.getRef()));
|
||||||
|
assertEquals(0, probe.expectMessageClass(Got.class).n);
|
||||||
|
ref.tell(new Increase());
|
||||||
|
ref.tell(new Get(probe.getRef()));
|
||||||
|
assertEquals(1, probe.expectMessageClass(Got.class).n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,23 @@
|
||||||
|
|
||||||
package akka.actor.typed.javadsl;
|
package akka.actor.typed.javadsl;
|
||||||
|
|
||||||
|
import akka.actor.testkit.typed.javadsl.TestKitJunitResource;
|
||||||
|
import akka.actor.testkit.typed.javadsl.TestProbe;
|
||||||
|
import akka.actor.typed.ActorRef;
|
||||||
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.scalatest.junit.JUnitSuite;
|
import org.scalatest.junit.JUnitSuite;
|
||||||
|
|
||||||
import akka.actor.typed.Behavior;
|
import akka.actor.typed.Behavior;
|
||||||
|
|
||||||
|
import static akka.actor.typed.javadsl.Behaviors.same;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/** Test creating [[MutableActor]]s using [[ReceiveBuilder]] */
|
/** Test creating [[MutableActor]]s using [[ReceiveBuilder]] */
|
||||||
public class ReceiveBuilderTest extends JUnitSuite {
|
public class ReceiveBuilderTest extends JUnitSuite {
|
||||||
|
|
||||||
|
@ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMutableCounter() {
|
public void testMutableCounter() {
|
||||||
Behavior<BehaviorBuilderTest.CounterMessage> mutable =
|
Behavior<BehaviorBuilderTest.CounterMessage> mutable =
|
||||||
|
|
@ -36,7 +43,7 @@ public class ReceiveBuilderTest extends JUnitSuite {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<BehaviorBuilderTest.CounterMessage> createReceive() {
|
public Receive<BehaviorBuilderTest.CounterMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(BehaviorBuilderTest.Increase.class, this::receiveIncrease)
|
.onMessage(BehaviorBuilderTest.Increase.class, this::receiveIncrease)
|
||||||
.onMessage(BehaviorBuilderTest.Get.class, this::receiveGet)
|
.onMessage(BehaviorBuilderTest.Get.class, this::receiveGet)
|
||||||
.build();
|
.build();
|
||||||
|
|
@ -56,7 +63,7 @@ public class ReceiveBuilderTest extends JUnitSuite {
|
||||||
@Override
|
@Override
|
||||||
public Receive<BehaviorBuilderTest.CounterMessage> createReceive() {
|
public Receive<BehaviorBuilderTest.CounterMessage> createReceive() {
|
||||||
assertEquals(42, value);
|
assertEquals(42, value);
|
||||||
return receiveBuilder().build();
|
return newReceiveBuilder().build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,4 +72,67 @@ public class ReceiveBuilderTest extends JUnitSuite {
|
||||||
MyAbstractBehavior mutable = new MyAbstractBehavior(42);
|
MyAbstractBehavior mutable = new MyAbstractBehavior(42);
|
||||||
assertEquals(Behaviors.unhandled(), mutable.receive(null, new BehaviorBuilderTest.Increase()));
|
assertEquals(Behaviors.unhandled(), mutable.receive(null, new BehaviorBuilderTest.Increase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void caseSelectedInOrderAdded() {
|
||||||
|
final TestProbe<Object> probe = testKit.createTestProbe();
|
||||||
|
Behavior<Object> behavior =
|
||||||
|
ReceiveBuilder.<Object>create()
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
msg -> {
|
||||||
|
probe.ref().tell("handler 1: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
msg -> {
|
||||||
|
probe.ref().tell("handler 2: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ActorRef<Object> ref = testKit.spawn(behavior);
|
||||||
|
ref.tell("message");
|
||||||
|
probe.expectMessage("handler 1: message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void applyPredicate() {
|
||||||
|
final TestProbe<Object> probe = testKit.createTestProbe();
|
||||||
|
Behavior<Object> behavior =
|
||||||
|
ReceiveBuilder.create()
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
msg -> "other".equals(msg),
|
||||||
|
msg -> {
|
||||||
|
probe.ref().tell("handler 1: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.onMessage(
|
||||||
|
String.class,
|
||||||
|
msg -> {
|
||||||
|
probe.ref().tell("handler 2: " + msg);
|
||||||
|
return Behaviors.same();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ActorRef<Object> ref = testKit.spawn(behavior);
|
||||||
|
ref.tell("message");
|
||||||
|
probe.expectMessage("handler 2: message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void catchAny() {
|
||||||
|
final TestProbe<Object> probe = testKit.createTestProbe();
|
||||||
|
Behavior<Object> behavior =
|
||||||
|
ReceiveBuilder.create()
|
||||||
|
.onAnyMessage(
|
||||||
|
msg -> {
|
||||||
|
probe.ref().tell(msg);
|
||||||
|
return same();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ActorRef<Object> ref = testKit.spawn(behavior);
|
||||||
|
ref.tell("message");
|
||||||
|
probe.expectMessage("message");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ public class InteractionPatternsTest extends JUnitSuite {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<Command> createReceive() {
|
public Receive<Command> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(
|
.onMessage(
|
||||||
Translate.class,
|
Translate.class,
|
||||||
cmd -> {
|
cmd -> {
|
||||||
|
|
@ -603,7 +603,7 @@ public class InteractionPatternsTest extends JUnitSuite {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<Object> createReceive() {
|
public Receive<Object> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(
|
.onMessage(
|
||||||
Wallet.class,
|
Wallet.class,
|
||||||
(wallet) -> {
|
(wallet) -> {
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,11 @@
|
||||||
package jdocs.akka.typed;
|
package jdocs.akka.typed;
|
||||||
|
|
||||||
// #imports
|
// #imports
|
||||||
import akka.NotUsed;
|
|
||||||
import akka.actor.typed.ActorRef;
|
import akka.actor.typed.ActorRef;
|
||||||
import akka.actor.typed.ActorSystem;
|
import akka.actor.typed.ActorSystem;
|
||||||
import akka.actor.typed.Behavior;
|
import akka.actor.typed.Behavior;
|
||||||
import akka.actor.typed.Terminated;
|
import akka.actor.typed.Terminated;
|
||||||
import akka.actor.typed.javadsl.AbstractBehavior;
|
import akka.actor.typed.javadsl.*;
|
||||||
import akka.actor.typed.javadsl.ActorContext;
|
|
||||||
import akka.actor.typed.javadsl.Behaviors;
|
|
||||||
import akka.actor.typed.javadsl.Receive;
|
|
||||||
// #imports
|
// #imports
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
@ -112,8 +108,9 @@ public class OOIntroTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<RoomCommand> createReceive() {
|
public Receive<RoomCommand> createReceive() {
|
||||||
return receiveBuilder()
|
ReceiveBuilder<RoomCommand> builder = newReceiveBuilder();
|
||||||
.onMessage(
|
|
||||||
|
builder.onMessage(
|
||||||
GetSession.class,
|
GetSession.class,
|
||||||
getSession -> {
|
getSession -> {
|
||||||
ActorRef<SessionEvent> client = getSession.replyTo;
|
ActorRef<SessionEvent> client = getSession.replyTo;
|
||||||
|
|
@ -125,16 +122,18 @@ public class OOIntroTest {
|
||||||
client.tell(new SessionGranted(ses.narrow()));
|
client.tell(new SessionGranted(ses.narrow()));
|
||||||
sessions.add(ses);
|
sessions.add(ses);
|
||||||
return this;
|
return this;
|
||||||
})
|
});
|
||||||
.onMessage(
|
|
||||||
|
builder.onMessage(
|
||||||
PublishSessionMessage.class,
|
PublishSessionMessage.class,
|
||||||
pub -> {
|
pub -> {
|
||||||
NotifyClient notification =
|
NotifyClient notification =
|
||||||
new NotifyClient((new MessagePosted(pub.screenName, pub.message)));
|
new NotifyClient((new MessagePosted(pub.screenName, pub.message)));
|
||||||
sessions.forEach(s -> s.tell(notification));
|
sessions.forEach(s -> s.tell(notification));
|
||||||
return this;
|
return this;
|
||||||
})
|
});
|
||||||
.build();
|
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,13 @@ abstract class AbstractBehavior[T] extends ExtensibleBehavior[T] {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement this to define how messages and signals are processed. Use the
|
* Implement this to define how messages and signals are processed. Use the
|
||||||
* [[AbstractBehavior.receiveBuilder]] to define the message dispatch.
|
* [[AbstractBehavior.newReceiveBuilder]] to define the message dispatch.
|
||||||
*/
|
*/
|
||||||
def createReceive: Receive[T]
|
def createReceive: Receive[T]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a [[ReceiveBuilder]] to define the message dispatch of the `Behavior`.
|
* Create a new [[ReceiveBuilder]] to define the message dispatch of the `Behavior`.
|
||||||
* Typically used from [[AbstractBehavior.createReceive]].
|
* Typically used from [[AbstractBehavior.createReceive]].
|
||||||
*/
|
*/
|
||||||
def receiveBuilder: ReceiveBuilder[T] = ReceiveBuilder.create
|
def newReceiveBuilder: ReceiveBuilder[T] = ReceiveBuilder.create
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,29 +5,34 @@
|
||||||
package akka.actor.typed.javadsl
|
package akka.actor.typed.javadsl
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
|
import akka.japi.function.{ Function ⇒ JFunction }
|
||||||
import akka.japi.function.{ Function, Function2, Predicate }
|
import akka.japi.function.{ Function2 ⇒ JFunction2 }
|
||||||
|
import akka.japi.function.{ Predicate ⇒ JPredicate }
|
||||||
import akka.annotation.InternalApi
|
import akka.annotation.InternalApi
|
||||||
import akka.actor.typed
|
import akka.actor.typed.Behavior
|
||||||
import akka.actor.typed.{ Behavior, ExtensibleBehavior, Signal }
|
import akka.actor.typed.ExtensibleBehavior
|
||||||
|
import akka.actor.typed.Signal
|
||||||
|
import akka.actor.typed.TypedActorContext
|
||||||
import akka.actor.typed.Behavior.unhandled
|
import akka.actor.typed.Behavior.unhandled
|
||||||
|
|
||||||
import BehaviorBuilder._
|
import BehaviorBuilder._
|
||||||
|
import akka.util.OptionVal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for creating a [[Behavior]] by 'chaining' message and signal handlers.
|
* Immutable builder used for creating a [[Behavior]] by 'chaining' message and signal handlers.
|
||||||
*
|
*
|
||||||
* When handling a message or signal, this [[Behavior]] will consider all handlers in the order they were added,
|
* When handling a message or signal, this [[Behavior]] will consider all handlers in the order they were added,
|
||||||
* looking for the first handler for which both the type and the (optional) predicate match.
|
* looking for the first handler for which both the type and the (optional) predicate match.
|
||||||
*
|
*
|
||||||
* @tparam T the common superclass of all supported messages.
|
* @tparam T the common superclass of all supported messages.
|
||||||
*/
|
*/
|
||||||
class BehaviorBuilder[T] private (
|
final class BehaviorBuilder[T] private (
|
||||||
private val messageHandlers: List[Case[T, T]],
|
messageHandlers: List[Case[T, T]],
|
||||||
private val signalHandlers: List[Case[T, Signal]]
|
signalHandlers: List[Case[T, Signal]]
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a Behavior from the current state of the builder
|
||||||
|
*/
|
||||||
def build(): Behavior[T] = new BuiltBehavior(messageHandlers.reverse, signalHandlers.reverse)
|
def build(): Behavior[T] = new BuiltBehavior(messageHandlers.reverse, signalHandlers.reverse)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -36,10 +41,10 @@ class BehaviorBuilder[T] private (
|
||||||
* @param type type of message to match
|
* @param type type of message to match
|
||||||
* @param handler action to apply if the type matches
|
* @param handler action to apply if the type matches
|
||||||
* @tparam M type of message to match
|
* @tparam M type of message to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return a new behavior builder with the specified handling appended
|
||||||
*/
|
*/
|
||||||
def onMessage[M <: T](`type`: Class[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
def onMessage[M <: T](`type`: Class[M], handler: JFunction2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
||||||
withMessage(`type`, None, (i1: ActorContext[T], msg: T) ⇒ handler.apply(i1, msg.asInstanceOf[M]))
|
withMessage(OptionVal.Some(`type`), OptionVal.None, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new predicated case to the message handling.
|
* Add a new predicated case to the message handling.
|
||||||
|
|
@ -48,14 +53,13 @@ class BehaviorBuilder[T] private (
|
||||||
* @param test a predicate that will be evaluated on the argument if the type matches
|
* @param test a predicate that will be evaluated on the argument if the type matches
|
||||||
* @param handler action to apply if the type matches and the predicate returns true
|
* @param handler action to apply if the type matches and the predicate returns true
|
||||||
* @tparam M type of message to match
|
* @tparam M type of message to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return a new behavior builder with the specified handling appended
|
||||||
*/
|
*/
|
||||||
def onMessage[M <: T](`type`: Class[M], test: Predicate[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
def onMessage[M <: T](`type`: Class[M], test: JPredicate[M], handler: JFunction2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
||||||
withMessage(
|
withMessage(
|
||||||
`type`,
|
OptionVal.Some(`type`),
|
||||||
Some((t: T) ⇒ test.test(t.asInstanceOf[M])),
|
OptionVal.Some((t: T) ⇒ test.test(t.asInstanceOf[M])),
|
||||||
(i1: ActorContext[T], msg: T) ⇒ handler.apply(i1, msg.asInstanceOf[M])
|
handler)
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the message handling without compile time type check.
|
* Add a new case to the message handling without compile time type check.
|
||||||
|
|
@ -65,20 +69,36 @@ class BehaviorBuilder[T] private (
|
||||||
*
|
*
|
||||||
* @param type type of message to match
|
* @param type type of message to match
|
||||||
* @param handler action to apply when the type matches
|
* @param handler action to apply when the type matches
|
||||||
* @return a new behavior with the specified handling appended
|
* @return a new behavior builder with the specified handling appended
|
||||||
*/
|
*/
|
||||||
def onMessageUnchecked[M <: T](`type`: Class[_ <: T], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
def onMessageUnchecked[M <: T](`type`: Class[_ <: T], handler: JFunction2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
||||||
withMessage(`type`, None, (i1: ActorContext[T], msg: T) ⇒ handler.apply(i1, msg.asInstanceOf[M]))
|
withMessage[M](
|
||||||
|
OptionVal.Some(`type`.asInstanceOf[Class[M]]), OptionVal.None, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the message handling matching equal messages.
|
* Add a new case to the message handling matching equal messages.
|
||||||
*
|
*
|
||||||
* @param msg the message to compare to
|
* @param msg the message to compare to
|
||||||
* @param handler action to apply when the message matches
|
* @param handler action to apply when the message matches
|
||||||
* @return a new behavior with the specified handling appended
|
* @return a new behavior builder with the specified handling appended
|
||||||
*/
|
*/
|
||||||
def onMessageEquals(msg: T, handler: Function[ActorContext[T], Behavior[T]]): BehaviorBuilder[T] =
|
def onMessageEquals(msg: T, handler: JFunction[ActorContext[T], Behavior[T]]): BehaviorBuilder[T] =
|
||||||
withMessage(msg.getClass, Some(_.equals(msg)), (ctx: ActorContext[T], _: T) ⇒ handler.apply(ctx))
|
withMessage[T](
|
||||||
|
OptionVal.Some(msg.getClass.asInstanceOf[Class[T]]),
|
||||||
|
OptionVal.Some(_.equals(msg)),
|
||||||
|
new JFunction2[ActorContext[T], T, Behavior[T]] {
|
||||||
|
override def apply(ctx: ActorContext[T], msg: T): Behavior[T] = handler.apply(ctx)
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new case to the message handling matching any message. Subsequent `onMessage` clauses will
|
||||||
|
* never see any messages.
|
||||||
|
*
|
||||||
|
* @param handler action to apply for any message
|
||||||
|
* @return a new behavior builder with the specified handling appended
|
||||||
|
*/
|
||||||
|
def onAnyMessage(handler: JFunction2[ActorContext[T], T, Behavior[T]]): BehaviorBuilder[T] =
|
||||||
|
withMessage(OptionVal.None, OptionVal.None, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the signal handling.
|
* Add a new case to the signal handling.
|
||||||
|
|
@ -86,10 +106,13 @@ class BehaviorBuilder[T] private (
|
||||||
* @param type type of signal to match
|
* @param type type of signal to match
|
||||||
* @param handler action to apply if the type matches
|
* @param handler action to apply if the type matches
|
||||||
* @tparam M type of signal to match
|
* @tparam M type of signal to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return a new behavior builder with the specified handling appended
|
||||||
*/
|
*/
|
||||||
def onSignal[M <: Signal](`type`: Class[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
def onSignal[M <: Signal](`type`: Class[M], handler: JFunction2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
||||||
withSignal(`type`, None, (ctx: ActorContext[T], signal: Signal) ⇒ handler.apply(ctx, signal.asInstanceOf[M]))
|
withSignal(
|
||||||
|
`type`,
|
||||||
|
OptionVal.None,
|
||||||
|
handler.asInstanceOf[JFunction2[ActorContext[T], Signal, Behavior[T]]])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new predicated case to the signal handling.
|
* Add a new predicated case to the signal handling.
|
||||||
|
|
@ -98,168 +121,87 @@ class BehaviorBuilder[T] private (
|
||||||
* @param test a predicate that will be evaluated on the argument if the type matches
|
* @param test a predicate that will be evaluated on the argument if the type matches
|
||||||
* @param handler action to apply if the type matches and the predicate returns true
|
* @param handler action to apply if the type matches and the predicate returns true
|
||||||
* @tparam M type of signal to match
|
* @tparam M type of signal to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return a new behavior builder with the specified handling appended
|
||||||
*/
|
*/
|
||||||
def onSignal[M <: Signal](`type`: Class[M], test: Predicate[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
def onSignal[M <: Signal](`type`: Class[M], test: JPredicate[M], handler: JFunction2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
||||||
withSignal(
|
withSignal(
|
||||||
`type`,
|
`type`,
|
||||||
Some((t: Signal) ⇒ test.test(t.asInstanceOf[M])),
|
OptionVal.Some((t: Signal) ⇒ test.test(t.asInstanceOf[M])),
|
||||||
(ctx: ActorContext[T], signal: Signal) ⇒ handler.apply(ctx, signal.asInstanceOf[M])
|
handler.asInstanceOf[JFunction2[ActorContext[T], Signal, Behavior[T]]]
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new case to the signal handling without compile time type check.
|
|
||||||
*
|
|
||||||
* Should normally not be used, but when matching on class with generic type
|
|
||||||
* argument it can be useful, e.g. <code>GenMsg.class</code> and <code>(ActorContext<Message> ctx, GenMsg<String> list) -> {...}</code>
|
|
||||||
*
|
|
||||||
* @param type type of signal to match
|
|
||||||
* @param handler action to apply when the type matches
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def onSignalUnchecked[M <: Signal](`type`: Class[_ <: Signal], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
withSignal(`type`, None, (ctx: ActorContext[T], signal: Signal) ⇒ handler.apply(ctx, signal.asInstanceOf[M]))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the signal handling matching equal signals.
|
* Add a new case to the signal handling matching equal signals.
|
||||||
*
|
*
|
||||||
* @param signal the signal to compare to
|
* @param signal the signal to compare to
|
||||||
* @param handler action to apply when the message matches
|
* @param handler action to apply when the message matches
|
||||||
* @return a new behavior with the specified handling appended
|
* @return a new behavior builder with the specified handling appended
|
||||||
*/
|
*/
|
||||||
def onSignalEquals(signal: Signal, handler: Function[ActorContext[T], Behavior[T]]): BehaviorBuilder[T] =
|
def onSignalEquals(signal: Signal, handler: Function[ActorContext[T], Behavior[T]]): BehaviorBuilder[T] =
|
||||||
withSignal(signal.getClass, Some(_.equals(signal)), (ctx: ActorContext[T], _: Signal) ⇒ handler.apply(ctx))
|
withSignal(
|
||||||
|
signal.getClass,
|
||||||
|
OptionVal.Some(_.equals(signal)),
|
||||||
|
new JFunction2[ActorContext[T], Signal, Behavior[T]] {
|
||||||
|
override def apply(ctx: ActorContext[T], signal: Signal): Behavior[T] = {
|
||||||
|
handler.apply(ctx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
private def withMessage(`type`: Class[_ <: T], test: Option[T ⇒ Boolean], handler: (ActorContext[T], T) ⇒ Behavior[T]): BehaviorBuilder[T] =
|
private def withMessage[M <: T](clazz: OptionVal[Class[M]], test: OptionVal[M ⇒ Boolean], handler: JFunction2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] = {
|
||||||
new BehaviorBuilder[T](Case[T, T](`type`, test, handler) +: messageHandlers, signalHandlers)
|
val newCase = Case(
|
||||||
|
clazz,
|
||||||
|
test,
|
||||||
|
handler
|
||||||
|
)
|
||||||
|
new BehaviorBuilder[T](newCase.asInstanceOf[Case[T, T]] +: messageHandlers, signalHandlers)
|
||||||
|
}
|
||||||
|
|
||||||
private def withSignal[M <: Signal](`type`: Class[M], test: Option[Signal ⇒ Boolean], handler: (ActorContext[T], Signal) ⇒ Behavior[T]): BehaviorBuilder[T] =
|
private def withSignal[M <: Signal](`type`: Class[M], test: OptionVal[Signal ⇒ Boolean], handler: JFunction2[ActorContext[T], Signal, Behavior[T]]): BehaviorBuilder[T] = {
|
||||||
new BehaviorBuilder[T](messageHandlers, Case[T, Signal](`type`, test, handler) +: signalHandlers)
|
new BehaviorBuilder[T](
|
||||||
|
messageHandlers,
|
||||||
|
Case(OptionVal.Some(`type`), test, handler).asInstanceOf[Case[T, Signal]] +: signalHandlers
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object BehaviorBuilder {
|
object BehaviorBuilder {
|
||||||
def create[T]: BehaviorBuilder[T] = new BehaviorBuilder[T](Nil, Nil)
|
|
||||||
|
|
||||||
|
private val _empty = new BehaviorBuilder[Nothing](Nil, Nil)
|
||||||
|
|
||||||
|
// used for both matching signals and messages so we throw away types after they are enforced by the builder API above
|
||||||
/** INTERNAL API */
|
/** INTERNAL API */
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[javadsl] final case class Case[BT, MT](`type`: Class[_ <: MT], test: Option[MT ⇒ Boolean], handler: (ActorContext[BT], MT) ⇒ Behavior[BT])
|
private[javadsl] final case class Case[BT, MT](`type`: OptionVal[Class[_ <: MT]], test: OptionVal[MT ⇒ Boolean], handler: JFunction2[ActorContext[BT], MT, Behavior[BT]])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a new behavior chain starting with this case.
|
* @return new empty immutable behavior builder.
|
||||||
*
|
|
||||||
* @param type type of message to match
|
|
||||||
* @param handler action to apply if the type matches
|
|
||||||
* @tparam T type of behavior to create
|
|
||||||
* @tparam M type of message to match
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
*/
|
||||||
def message[T, M <: T](`type`: Class[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
def create[T]: BehaviorBuilder[T] = _empty.asInstanceOf[BehaviorBuilder[T]]
|
||||||
BehaviorBuilder.create[T].onMessage(`type`, handler)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new behavior chain starting with this predicated case.
|
|
||||||
*
|
|
||||||
* @param type type of message to match
|
|
||||||
* @param test a predicate that will be evaluated on the argument if the type matches
|
|
||||||
* @param handler action to apply if the type matches and the predicate returns true
|
|
||||||
* @tparam T type of behavior to create
|
|
||||||
* @tparam M type of message to match
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def message[T, M <: T](`type`: Class[M], test: Predicate[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
BehaviorBuilder.create[T].onMessage(`type`, test, handler)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new behavior chain starting with a handler without compile time type check.
|
|
||||||
*
|
|
||||||
* Should normally not be used, but when matching on class with generic type
|
|
||||||
* argument it can be useful, e.g. <code>List.class</code> and <code>(List<String> list) -> {...}</code>
|
|
||||||
*
|
|
||||||
* @param type type of message to match
|
|
||||||
* @param handler action to apply when the type matches
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def messageUnchecked[T, M <: T](`type`: Class[_ <: T], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
BehaviorBuilder.create[T].onMessageUnchecked(`type`, handler)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new behavior chain starting with a handler for equal messages.
|
|
||||||
*
|
|
||||||
* @param msg the message to compare to
|
|
||||||
* @param handler action to apply when the message matches
|
|
||||||
* @tparam T type of behavior to create
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def messageEquals[T](msg: T, handler: Function[ActorContext[T], Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
BehaviorBuilder.create[T].onMessageEquals(msg, handler)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new behavior chain starting with this signal case.
|
|
||||||
*
|
|
||||||
* @param type type of signal to match
|
|
||||||
* @param handler action to apply if the type matches
|
|
||||||
* @tparam T type of behavior to create
|
|
||||||
* @tparam M type of signal to match
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def signal[T, M <: Signal](`type`: Class[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
BehaviorBuilder.create[T].onSignal(`type`, handler)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new behavior chain starting with this predicated signal case.
|
|
||||||
*
|
|
||||||
* @param type type of signals to match
|
|
||||||
* @param test a predicate that will be evaluated on the argument if the type matches
|
|
||||||
* @param handler action to apply if the type matches and the predicate returns true
|
|
||||||
* @tparam T type of behavior to create
|
|
||||||
* @tparam M type of signal to match
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def signal[T, M <: Signal](`type`: Class[M], test: Predicate[M], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
BehaviorBuilder.create[T].onSignal(`type`, test, handler)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new behavior chain starting with this unchecked signal case.
|
|
||||||
*
|
|
||||||
* Should normally not be used, but when matching on class with generic type
|
|
||||||
* argument it can be useful, e.g. <code>GenMsg.class</code> and <code>(ActorContext<Message> ctx, GenMsg<String> list) -> {...}</code>
|
|
||||||
*
|
|
||||||
* @param type type of signal to match
|
|
||||||
* @param handler action to apply when the type matches
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def signalUnchecked[T, M <: Signal](`type`: Class[_ <: Signal], handler: Function2[ActorContext[T], M, Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
BehaviorBuilder.create[T].onSignalUnchecked(`type`, handler)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new behavior chain starting with a handler for this specific signal.
|
|
||||||
*
|
|
||||||
* @param signal the signal to compare to
|
|
||||||
* @param handler action to apply when the message matches
|
|
||||||
* @tparam T type of behavior to create
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def signalEquals[T](signal: Signal, handler: Function[ActorContext[T], Behavior[T]]): BehaviorBuilder[T] =
|
|
||||||
BehaviorBuilder.create[T].onSignalEquals(signal, handler)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BuiltBehavior[T](
|
/**
|
||||||
private val messageHandlers: List[Case[T, T]],
|
* The concrete behavior
|
||||||
private val signalHandlers: List[Case[T, Signal]]
|
*
|
||||||
|
* INTERNAL API
|
||||||
|
*/
|
||||||
|
@InternalApi
|
||||||
|
private final class BuiltBehavior[T](
|
||||||
|
messageHandlers: List[Case[T, T]],
|
||||||
|
signalHandlers: List[Case[T, Signal]]
|
||||||
) extends ExtensibleBehavior[T] {
|
) extends ExtensibleBehavior[T] {
|
||||||
|
|
||||||
override def receive(ctx: typed.TypedActorContext[T], msg: T): Behavior[T] = receive[T](ctx.asJava, msg, messageHandlers)
|
override def receive(ctx: TypedActorContext[T], msg: T): Behavior[T] = receive(ctx.asJava, msg, messageHandlers)
|
||||||
|
|
||||||
override def receiveSignal(ctx: typed.TypedActorContext[T], msg: Signal): Behavior[T] = receive[Signal](ctx.asJava, msg, signalHandlers)
|
override def receiveSignal(ctx: TypedActorContext[T], msg: Signal): Behavior[T] = receive(ctx.asJava, msg, signalHandlers)
|
||||||
|
|
||||||
@tailrec
|
@tailrec
|
||||||
private def receive[M](ctx: ActorContext[T], msg: M, handlers: List[Case[T, M]]): Behavior[T] =
|
private def receive[M](ctx: ActorContext[T], msg: M, handlers: List[Case[T, M]]): Behavior[T] =
|
||||||
handlers match {
|
handlers match {
|
||||||
case Case(cls, predicate, handler) :: tail ⇒
|
case Case(cls, predicate, handler) :: tail ⇒
|
||||||
if (cls.isAssignableFrom(msg.getClass) && (predicate.isEmpty || predicate.get.apply(msg))) handler(ctx, msg)
|
if ((cls.isEmpty || cls.get.isAssignableFrom(msg.getClass)) && (predicate.isEmpty || predicate.get.apply(msg)))
|
||||||
else receive[M](ctx, msg, tail)
|
handler(ctx, msg)
|
||||||
case _ ⇒
|
else receive(ctx, msg, tail)
|
||||||
|
case Nil ⇒
|
||||||
unhandled[T]
|
unhandled[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,26 +5,29 @@
|
||||||
package akka.actor.typed.javadsl
|
package akka.actor.typed.javadsl
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
import akka.japi.function.{ Creator, Function, Predicate }
|
import akka.japi.function.Creator
|
||||||
|
import akka.japi.function.{ Function ⇒ JFunction }
|
||||||
|
import akka.japi.function.{ Predicate ⇒ JPredicate }
|
||||||
import akka.actor.typed.{ Behavior, Signal }
|
import akka.actor.typed.{ Behavior, Signal }
|
||||||
import akka.annotation.InternalApi
|
import akka.annotation.InternalApi
|
||||||
|
import akka.util.OptionVal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used when implementing [[AbstractBehavior]].
|
* Mutable builder used when implementing [[AbstractBehavior]].
|
||||||
*
|
*
|
||||||
* When handling a message or signal, this [[Behavior]] will consider all handlers in the order they were added,
|
* When handling a message or signal, this [[Behavior]] will consider all handlers in the order they were added,
|
||||||
* looking for the first handler for which both the type and the (optional) predicate match.
|
* looking for the first handler for which both the type and the (optional) predicate match.
|
||||||
*
|
*
|
||||||
* @tparam T the common superclass of all supported messages.
|
* @tparam T the common superclass of all supported messages.
|
||||||
*/
|
*/
|
||||||
class ReceiveBuilder[T] private (
|
final class ReceiveBuilder[T] private (
|
||||||
private val messageHandlers: List[ReceiveBuilder.Case[T, T]],
|
private var messageHandlers: List[ReceiveBuilder.Case[T, T]],
|
||||||
private val signalHandlers: List[ReceiveBuilder.Case[T, Signal]]
|
private var signalHandlers: List[ReceiveBuilder.Case[T, Signal]]
|
||||||
) {
|
) {
|
||||||
|
|
||||||
import ReceiveBuilder.Case
|
import ReceiveBuilder.Case
|
||||||
|
|
||||||
def build(): Receive[T] = new BuiltReceive(messageHandlers.reverse, signalHandlers.reverse)
|
def build(): Receive[T] = new BuiltReceive[T](messageHandlers.reverse, signalHandlers.reverse)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the message handling.
|
* Add a new case to the message handling.
|
||||||
|
|
@ -32,10 +35,10 @@ class ReceiveBuilder[T] private (
|
||||||
* @param type type of message to match
|
* @param type type of message to match
|
||||||
* @param handler action to apply if the type matches
|
* @param handler action to apply if the type matches
|
||||||
* @tparam M type of message to match
|
* @tparam M type of message to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return this behavior builder
|
||||||
*/
|
*/
|
||||||
def onMessage[M <: T](`type`: Class[M], handler: Function[M, Behavior[T]]): ReceiveBuilder[T] =
|
def onMessage[M <: T](`type`: Class[M], handler: JFunction[M, Behavior[T]]): ReceiveBuilder[T] =
|
||||||
withMessage(`type`, None, msg ⇒ handler.apply(msg.asInstanceOf[M]))
|
withMessage(OptionVal.Some(`type`), OptionVal.None, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new predicated case to the message handling.
|
* Add a new predicated case to the message handling.
|
||||||
|
|
@ -44,14 +47,10 @@ class ReceiveBuilder[T] private (
|
||||||
* @param test a predicate that will be evaluated on the argument if the type matches
|
* @param test a predicate that will be evaluated on the argument if the type matches
|
||||||
* @param handler action to apply if the type matches and the predicate returns true
|
* @param handler action to apply if the type matches and the predicate returns true
|
||||||
* @tparam M type of message to match
|
* @tparam M type of message to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return this behavior builder
|
||||||
*/
|
*/
|
||||||
def onMessage[M <: T](`type`: Class[M], test: Predicate[M], handler: Function[M, Behavior[T]]): ReceiveBuilder[T] =
|
def onMessage[M <: T](`type`: Class[M], test: JPredicate[M], handler: JFunction[M, Behavior[T]]): ReceiveBuilder[T] =
|
||||||
withMessage(
|
withMessage(OptionVal.Some(`type`), OptionVal.Some(test), handler)
|
||||||
`type`,
|
|
||||||
Some((t: T) ⇒ test.test(t.asInstanceOf[M])),
|
|
||||||
msg ⇒ handler.apply(msg.asInstanceOf[M])
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the message handling without compile time type check.
|
* Add a new case to the message handling without compile time type check.
|
||||||
|
|
@ -61,20 +60,35 @@ class ReceiveBuilder[T] private (
|
||||||
*
|
*
|
||||||
* @param type type of message to match
|
* @param type type of message to match
|
||||||
* @param handler action to apply when the type matches
|
* @param handler action to apply when the type matches
|
||||||
* @return a new behavior with the specified handling appended
|
* @return this behavior builder
|
||||||
*/
|
*/
|
||||||
def onMessageUnchecked[M <: T](`type`: Class[_ <: T], handler: Function[M, Behavior[T]]): ReceiveBuilder[T] =
|
def onMessageUnchecked[M <: T](`type`: Class[_ <: T], handler: JFunction[M, Behavior[T]]): ReceiveBuilder[T] =
|
||||||
withMessage(`type`, None, msg ⇒ handler.apply(msg.asInstanceOf[M]))
|
withMessage[M](OptionVal.Some(`type`.asInstanceOf[Class[M]]), OptionVal.None, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the message handling matching equal messages.
|
* Add a new case to the message handling matching equal messages.
|
||||||
*
|
*
|
||||||
* @param msg the message to compare to
|
* @param msg the message to compare to
|
||||||
* @param handler action to apply when the message matches
|
* @param handler action to apply when the message matches
|
||||||
* @return a new behavior with the specified handling appended
|
* @return this behavior builder
|
||||||
*/
|
*/
|
||||||
def onMessageEquals(msg: T, handler: Creator[Behavior[T]]): ReceiveBuilder[T] =
|
def onMessageEquals(msg: T, handler: Creator[Behavior[T]]): ReceiveBuilder[T] =
|
||||||
withMessage(msg.getClass, Some(_.equals(msg)), _ ⇒ handler.create())
|
withMessage(OptionVal.Some(msg.getClass), OptionVal.Some(new JPredicate[T] {
|
||||||
|
override def test(param: T): Boolean = param == (msg)
|
||||||
|
}), new JFunction[T, Behavior[T]] {
|
||||||
|
// invoke creator without the message
|
||||||
|
override def apply(param: T): Behavior[T] = handler.create()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new case to the message handling matching any message. Subsequent `onMessage` clauses will
|
||||||
|
* never see any messages.
|
||||||
|
*
|
||||||
|
* @param handler action to apply for any message
|
||||||
|
* @return this behavior builder
|
||||||
|
*/
|
||||||
|
def onAnyMessage(handler: JFunction[T, Behavior[T]]): ReceiveBuilder[T] =
|
||||||
|
withMessage(OptionVal.None, OptionVal.None, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the signal handling.
|
* Add a new case to the signal handling.
|
||||||
|
|
@ -82,10 +96,10 @@ class ReceiveBuilder[T] private (
|
||||||
* @param type type of signal to match
|
* @param type type of signal to match
|
||||||
* @param handler action to apply if the type matches
|
* @param handler action to apply if the type matches
|
||||||
* @tparam M type of signal to match
|
* @tparam M type of signal to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return this behavior builder
|
||||||
*/
|
*/
|
||||||
def onSignal[M <: Signal](`type`: Class[M], handler: Function[M, Behavior[T]]): ReceiveBuilder[T] =
|
def onSignal[M <: Signal](`type`: Class[M], handler: JFunction[M, Behavior[T]]): ReceiveBuilder[T] =
|
||||||
withSignal(`type`, None, signal ⇒ handler.apply(signal.asInstanceOf[M]))
|
withSignal(`type`, OptionVal.None, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new predicated case to the signal handling.
|
* Add a new predicated case to the signal handling.
|
||||||
|
|
@ -94,60 +108,55 @@ class ReceiveBuilder[T] private (
|
||||||
* @param test a predicate that will be evaluated on the argument if the type matches
|
* @param test a predicate that will be evaluated on the argument if the type matches
|
||||||
* @param handler action to apply if the type matches and the predicate returns true
|
* @param handler action to apply if the type matches and the predicate returns true
|
||||||
* @tparam M type of signal to match
|
* @tparam M type of signal to match
|
||||||
* @return a new behavior with the specified handling appended
|
* @return this behavior builder
|
||||||
*/
|
*/
|
||||||
def onSignal[M <: Signal](`type`: Class[M], test: Predicate[M], handler: Function[M, Behavior[T]]): ReceiveBuilder[T] =
|
def onSignal[M <: Signal](`type`: Class[M], test: JPredicate[M], handler: JFunction[M, Behavior[T]]): ReceiveBuilder[T] =
|
||||||
withSignal(
|
withSignal(`type`, OptionVal.Some(test), handler)
|
||||||
`type`,
|
|
||||||
Some((t: Signal) ⇒ test.test(t.asInstanceOf[M])),
|
|
||||||
signal ⇒ handler.apply(signal.asInstanceOf[M])
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new case to the signal handling without compile time type check.
|
|
||||||
*
|
|
||||||
* Should normally not be used, but when matching on class with generic type
|
|
||||||
* argument it can be useful, e.g. <code>GenMsg.class</code> and <code>(ActorContext<Message> ctx, GenMsg<String> list) -> {...}</code>
|
|
||||||
*
|
|
||||||
* @param type type of signal to match
|
|
||||||
* @param handler action to apply when the type matches
|
|
||||||
* @return a new behavior with the specified handling appended
|
|
||||||
*/
|
|
||||||
def onSignalUnchecked[M <: Signal](`type`: Class[_ <: Signal], handler: Function[M, Behavior[T]]): ReceiveBuilder[T] =
|
|
||||||
withSignal(`type`, None, signal ⇒ handler.apply(signal.asInstanceOf[M]))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new case to the signal handling matching equal signals.
|
* Add a new case to the signal handling matching equal signals.
|
||||||
*
|
*
|
||||||
* @param signal the signal to compare to
|
* @param signal the signal to compare to
|
||||||
* @param handler action to apply when the message matches
|
* @param handler action to apply when the message matches
|
||||||
* @return a new behavior with the specified handling appended
|
* @return this behavior builder
|
||||||
*/
|
*/
|
||||||
def onSignalEquals(signal: Signal, handler: Creator[Behavior[T]]): ReceiveBuilder[T] =
|
def onSignalEquals(signal: Signal, handler: Creator[Behavior[T]]): ReceiveBuilder[T] =
|
||||||
withSignal(signal.getClass, Some(_.equals(signal)), _ ⇒ handler.create())
|
withSignal(signal.getClass, OptionVal.Some(new JPredicate[Signal] {
|
||||||
|
override def test(param: Signal): Boolean = param == signal
|
||||||
|
}), new JFunction[Signal, Behavior[T]] {
|
||||||
|
override def apply(param: Signal): Behavior[T] = handler.create()
|
||||||
|
})
|
||||||
|
|
||||||
private def withMessage(`type`: Class[_ <: T], test: Option[T ⇒ Boolean], handler: T ⇒ Behavior[T]): ReceiveBuilder[T] =
|
private def withMessage[M <: T](`type`: OptionVal[Class[M]], test: OptionVal[JPredicate[M]], handler: JFunction[M, Behavior[T]]): ReceiveBuilder[T] = {
|
||||||
new ReceiveBuilder[T](Case[T, T](`type`, test, handler) +: messageHandlers, signalHandlers)
|
messageHandlers = Case[T, M](`type`, test, handler).asInstanceOf[Case[T, T]] +: messageHandlers
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
private def withSignal[M <: Signal](`type`: Class[M], test: Option[Signal ⇒ Boolean], handler: Signal ⇒ Behavior[T]): ReceiveBuilder[T] =
|
private def withSignal[M <: Signal](`type`: Class[M], test: OptionVal[JPredicate[M]], handler: JFunction[M, Behavior[T]]): ReceiveBuilder[T] = {
|
||||||
new ReceiveBuilder[T](messageHandlers, Case[T, Signal](`type`, test, handler) +: signalHandlers)
|
signalHandlers = Case[T, M](OptionVal.Some(`type`), test, handler).asInstanceOf[Case[T, Signal]] +: signalHandlers
|
||||||
|
this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ReceiveBuilder {
|
object ReceiveBuilder {
|
||||||
|
/** Create a new mutable receive builder */
|
||||||
def create[T]: ReceiveBuilder[T] = new ReceiveBuilder[T](Nil, Nil)
|
def create[T]: ReceiveBuilder[T] = new ReceiveBuilder[T](Nil, Nil)
|
||||||
|
|
||||||
/** INTERNAL API */
|
/** INTERNAL API */
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[javadsl] final case class Case[BT, MT](`type`: Class[_ <: MT], test: Option[MT ⇒ Boolean], handler: MT ⇒ Behavior[BT])
|
private[javadsl] final case class Case[BT, MT](`type`: OptionVal[Class[_ <: MT]], test: OptionVal[JPredicate[MT]], handler: JFunction[MT, Behavior[BT]])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receive type for [[AbstractBehavior]]
|
* Receive type for [[AbstractBehavior]]
|
||||||
|
*
|
||||||
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
|
@InternalApi
|
||||||
private final class BuiltReceive[T](
|
private final class BuiltReceive[T](
|
||||||
private val messageHandlers: List[ReceiveBuilder.Case[T, T]],
|
messageHandlers: List[ReceiveBuilder.Case[T, T]],
|
||||||
private val signalHandlers: List[ReceiveBuilder.Case[T, Signal]]
|
signalHandlers: List[ReceiveBuilder.Case[T, Signal]]
|
||||||
) extends Receive[T] {
|
) extends Receive[T] {
|
||||||
import ReceiveBuilder.Case
|
import ReceiveBuilder.Case
|
||||||
|
|
||||||
|
|
@ -159,7 +168,7 @@ private final class BuiltReceive[T](
|
||||||
private def receive[M](msg: M, handlers: List[Case[T, M]]): Behavior[T] =
|
private def receive[M](msg: M, handlers: List[Case[T, M]]): Behavior[T] =
|
||||||
handlers match {
|
handlers match {
|
||||||
case Case(cls, predicate, handler) :: tail ⇒
|
case Case(cls, predicate, handler) :: tail ⇒
|
||||||
if (cls.isAssignableFrom(msg.getClass) && (predicate.isEmpty || predicate.get.apply(msg))) handler(msg)
|
if ((cls.isEmpty || cls.get.isAssignableFrom(msg.getClass)) && (predicate.isEmpty || predicate.get.test(msg))) handler(msg)
|
||||||
else receive[M](msg, tail)
|
else receive[M](msg, tail)
|
||||||
case _ ⇒
|
case _ ⇒
|
||||||
Behaviors.unhandled
|
Behaviors.unhandled
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package akka.japi.function
|
||||||
/**
|
/**
|
||||||
* A Function interface. Used to create first-class-functions is Java.
|
* A Function interface. Used to create first-class-functions is Java.
|
||||||
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
||||||
|
* Supports throwing `Exception` in the apply, which the `java.util.function.Function` counterpart does not.
|
||||||
*/
|
*/
|
||||||
@SerialVersionUID(1L)
|
@SerialVersionUID(1L)
|
||||||
trait Function[-T, +R] extends java.io.Serializable {
|
trait Function[-T, +R] extends java.io.Serializable {
|
||||||
|
|
@ -17,6 +18,7 @@ trait Function[-T, +R] extends java.io.Serializable {
|
||||||
/**
|
/**
|
||||||
* A Function interface. Used to create 2-arg first-class-functions is Java.
|
* A Function interface. Used to create 2-arg first-class-functions is Java.
|
||||||
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
||||||
|
* Supports throwing `Exception` in the apply, which the `java.util.function.BiFunction` counterpart does not.
|
||||||
*/
|
*/
|
||||||
@SerialVersionUID(1L)
|
@SerialVersionUID(1L)
|
||||||
trait Function2[-T1, -T2, +R] extends java.io.Serializable {
|
trait Function2[-T1, -T2, +R] extends java.io.Serializable {
|
||||||
|
|
@ -27,6 +29,7 @@ trait Function2[-T1, -T2, +R] extends java.io.Serializable {
|
||||||
/**
|
/**
|
||||||
* A Procedure is like a Function, but it doesn't produce a return value.
|
* A Procedure is like a Function, but it doesn't produce a return value.
|
||||||
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
||||||
|
* Supports throwing `Exception` in the apply, which the `java.util.function.Consumer` counterpart does not.
|
||||||
*/
|
*/
|
||||||
@SerialVersionUID(1L)
|
@SerialVersionUID(1L)
|
||||||
trait Procedure[-T] extends java.io.Serializable {
|
trait Procedure[-T] extends java.io.Serializable {
|
||||||
|
|
@ -37,9 +40,11 @@ trait Procedure[-T] extends java.io.Serializable {
|
||||||
/**
|
/**
|
||||||
* An executable piece of code that takes no parameters and doesn't return any value.
|
* An executable piece of code that takes no parameters and doesn't return any value.
|
||||||
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
||||||
|
* Supports throwing `Exception` in the apply, which the `java.util.function.Effect` counterpart does not.
|
||||||
*/
|
*/
|
||||||
@SerialVersionUID(1L)
|
@SerialVersionUID(1L)
|
||||||
trait Effect extends java.io.Serializable {
|
trait Effect extends java.io.Serializable {
|
||||||
|
|
||||||
@throws(classOf[Exception])
|
@throws(classOf[Exception])
|
||||||
def apply(): Unit
|
def apply(): Unit
|
||||||
}
|
}
|
||||||
|
|
@ -47,6 +52,7 @@ trait Effect extends java.io.Serializable {
|
||||||
/**
|
/**
|
||||||
* Java API: Defines a criteria and determines whether the parameter meets this criteria.
|
* Java API: Defines a criteria and determines whether the parameter meets this criteria.
|
||||||
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
* `Serializable` is needed to be able to grab line number for Java 8 lambdas.
|
||||||
|
* Supports throwing `Exception` in the apply, which the `java.util.function.Predicate` counterpart does not.
|
||||||
*/
|
*/
|
||||||
@SerialVersionUID(1L)
|
@SerialVersionUID(1L)
|
||||||
trait Predicate[-T] extends java.io.Serializable {
|
trait Predicate[-T] extends java.io.Serializable {
|
||||||
|
|
@ -55,6 +61,7 @@ trait Predicate[-T] extends java.io.Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constructor/factory, takes no parameters but creates a new value of type T every call.
|
* A constructor/factory, takes no parameters but creates a new value of type T every call.
|
||||||
|
* Supports throwing `Exception` in the apply, which the `java.util.function.Creator` counterpart does not.
|
||||||
*/
|
*/
|
||||||
@SerialVersionUID(1L)
|
@SerialVersionUID(1L)
|
||||||
trait Creator[+T] extends Serializable {
|
trait Creator[+T] extends Serializable {
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ public class ReplicatorTest extends JUnitSuite {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<ClientCommand> createReceive() {
|
public Receive<ClientCommand> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(Increment.class, this::onIncrement)
|
.onMessage(Increment.class, this::onIncrement)
|
||||||
.onMessage(InternalUpdateResponse.class, msg -> Behaviors.same())
|
.onMessage(InternalUpdateResponse.class, msg -> Behaviors.same())
|
||||||
.onMessage(GetValue.class, this::onGetValue)
|
.onMessage(GetValue.class, this::onGetValue)
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public class ReceptionistExampleTest extends JUnitSuite {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<Object> createReceive() {
|
public Receive<Object> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(
|
.onMessage(
|
||||||
Receptionist.Listing.class,
|
Receptionist.Listing.class,
|
||||||
listing -> listing.isForKey(serviceKey),
|
listing -> listing.isForKey(serviceKey),
|
||||||
|
|
@ -131,7 +131,7 @@ public class ReceptionistExampleTest extends JUnitSuite {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<Object> createReceive() {
|
public Receive<Object> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(
|
.onMessage(
|
||||||
Receptionist.Listing.class,
|
Receptionist.Listing.class,
|
||||||
listing -> listing.isForKey(serviceKey),
|
listing -> listing.isForKey(serviceKey),
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ The console output may look like this:
|
||||||
|
|
||||||
The next example is more realistic and demonstrates some important patterns:
|
The next example is more realistic and demonstrates some important patterns:
|
||||||
|
|
||||||
* Using a sealed trait and case class/objects to represent multiple messages an actor can receive
|
* Using @scala[a sealed trait and case class/objects]@java[an interface and classes implementing that interface] to represent multiple messages an actor can receive
|
||||||
* Handle sessions by using child actors
|
* Handle sessions by using child actors
|
||||||
* Handling state by changing behavior
|
* Handling state by changing behavior
|
||||||
* Using multiple typed actors to represent different parts of a protocol in a type safe way
|
* Using multiple typed actors to represent different parts of a protocol in a type safe way
|
||||||
|
|
@ -357,6 +357,10 @@ As the state is mutable, we never return a different behavior from the message l
|
||||||
the `AbstractBehavior` instance itself (`this`) as a behavior to use for processing the next message coming in.
|
the `AbstractBehavior` instance itself (`this`) as a behavior to use for processing the next message coming in.
|
||||||
We could also return `Behavior.same` to achieve the same.
|
We could also return `Behavior.same` to achieve the same.
|
||||||
|
|
||||||
|
@java[In this sample we make separate statements for creating the behavior builder, but it also returns the builder
|
||||||
|
itself from each step so a more fluent behavior definition style is also possible. What you should prefer depends on
|
||||||
|
how big the set of messages the actor accepts is.]
|
||||||
|
|
||||||
It is also possible to return a new different `AbstractBehavior`, for example to represent a different state in a
|
It is also possible to return a new different `AbstractBehavior`, for example to represent a different state in a
|
||||||
finite state machine (FSM), or use one of the functional behavior factories to combine the object oriented
|
finite state machine (FSM), or use one of the functional behavior factories to combine the object oriented
|
||||||
with the functional style for different parts of the lifecycle of the same Actor behavior.
|
with the functional style for different parts of the lifecycle of the same Actor behavior.
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class PrintMyActorRefActor extends AbstractBehavior<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<String> createReceive() {
|
public Receive<String> createReceive() {
|
||||||
return receiveBuilder().onMessageEquals("printit", this::printIt).build();
|
return newReceiveBuilder().onMessageEquals("printit", this::printIt).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Behavior<String> printIt() {
|
private Behavior<String> printIt() {
|
||||||
|
|
@ -60,7 +60,7 @@ class StartStopActor1 extends AbstractBehavior<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<String> createReceive() {
|
public Receive<String> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessageEquals("stop", Behaviors::stopped)
|
.onMessageEquals("stop", Behaviors::stopped)
|
||||||
.onSignal(PostStop.class, signal -> postStop())
|
.onSignal(PostStop.class, signal -> postStop())
|
||||||
.build();
|
.build();
|
||||||
|
|
@ -84,7 +84,7 @@ class StartStopActor2 extends AbstractBehavior<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<String> createReceive() {
|
public Receive<String> createReceive() {
|
||||||
return receiveBuilder().onSignal(PostStop.class, signal -> postStop()).build();
|
return newReceiveBuilder().onSignal(PostStop.class, signal -> postStop()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Behavior<String> postStop() {
|
private Behavior<String> postStop() {
|
||||||
|
|
@ -113,7 +113,7 @@ class SupervisingActor extends AbstractBehavior<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<String> createReceive() {
|
public Receive<String> createReceive() {
|
||||||
return receiveBuilder().onMessageEquals("failChild", this::failChild).build();
|
return newReceiveBuilder().onMessageEquals("failChild", this::failChild).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Behavior<String> failChild() {
|
private Behavior<String> failChild() {
|
||||||
|
|
@ -134,7 +134,7 @@ class SupervisedActor extends AbstractBehavior<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<String> createReceive() {
|
public Receive<String> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessageEquals("fail", this::fail)
|
.onMessageEquals("fail", this::fail)
|
||||||
.onSignal(PreRestart.class, signal -> preRestart())
|
.onSignal(PreRestart.class, signal -> preRestart())
|
||||||
.onSignal(PostStop.class, signal -> postStop())
|
.onSignal(PostStop.class, signal -> postStop())
|
||||||
|
|
@ -174,7 +174,7 @@ class Main extends AbstractBehavior<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<String> createReceive() {
|
public Receive<String> createReceive() {
|
||||||
return receiveBuilder().onMessageEquals("start", this::start).build();
|
return newReceiveBuilder().onMessageEquals("start", this::start).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Behavior<String> start() {
|
private Behavior<String> start() {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public class IotSupervisor extends AbstractBehavior<Void> {
|
||||||
// No need to handle any messages
|
// No need to handle any messages
|
||||||
@Override
|
@Override
|
||||||
public Receive<Void> createReceive() {
|
public Receive<Void> createReceive() {
|
||||||
return receiveBuilder().onSignal(PostStop.class, signal -> postStop()).build();
|
return newReceiveBuilder().onSignal(PostStop.class, signal -> postStop()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IotSupervisor postStop() {
|
private IotSupervisor postStop() {
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public class Device extends AbstractBehavior<DeviceMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<DeviceMessage> createReceive() {
|
public Receive<DeviceMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(RecordTemperature.class, this::recordTemperature)
|
.onMessage(RecordTemperature.class, this::recordTemperature)
|
||||||
.onMessage(ReadTemperature.class, this::readTemperature)
|
.onMessage(ReadTemperature.class, this::readTemperature)
|
||||||
.onSignal(PostStop.class, signal -> postStop())
|
.onSignal(PostStop.class, signal -> postStop())
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public class Device extends AbstractBehavior<DeviceMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<DeviceMessage> createReceive() {
|
public Receive<DeviceMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(ReadTemperature.class, this::readTemperature)
|
.onMessage(ReadTemperature.class, this::readTemperature)
|
||||||
.onSignal(PostStop.class, signal -> postStop())
|
.onSignal(PostStop.class, signal -> postStop())
|
||||||
.build();
|
.build();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public class Device extends AbstractBehavior<DeviceMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<DeviceMessage> createReceive() {
|
public Receive<DeviceMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(RecordTemperature.class, this::recordTemperature)
|
.onMessage(RecordTemperature.class, this::recordTemperature)
|
||||||
.onMessage(ReadTemperature.class, this::readTemperature)
|
.onMessage(ReadTemperature.class, this::readTemperature)
|
||||||
.onMessage(Passivate.class, m -> Behaviors.stopped())
|
.onMessage(Passivate.class, m -> Behaviors.stopped())
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ public class DeviceGroup extends AbstractBehavior<DeviceGroupMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<DeviceGroupMessage> createReceive() {
|
public Receive<DeviceGroupMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
||||||
// #device-group-register
|
// #device-group-register
|
||||||
// #device-group-remove
|
// #device-group-remove
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ public class DeviceManager extends AbstractBehavior<DeviceManagerMessage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Receive<DeviceManagerMessage> createReceive() {
|
public Receive<DeviceManagerMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
||||||
.onMessage(RequestDeviceList.class, this::onRequestDeviceList)
|
.onMessage(RequestDeviceList.class, this::onRequestDeviceList)
|
||||||
.onMessage(DeviceGroupTerminated.class, this::onTerminated)
|
.onMessage(DeviceGroupTerminated.class, this::onTerminated)
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public class Device extends AbstractBehavior<DeviceMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<DeviceMessage> createReceive() {
|
public Receive<DeviceMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(RecordTemperature.class, this::recordTemperature)
|
.onMessage(RecordTemperature.class, this::recordTemperature)
|
||||||
.onMessage(ReadTemperature.class, this::readTemperature)
|
.onMessage(ReadTemperature.class, this::readTemperature)
|
||||||
.onMessage(Passivate.class, m -> Behaviors.stopped())
|
.onMessage(Passivate.class, m -> Behaviors.stopped())
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ public class DeviceGroup extends AbstractBehavior<DeviceGroupMessage> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Receive<DeviceGroupMessage> createReceive() {
|
public Receive<DeviceGroupMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
// #query-added
|
// #query-added
|
||||||
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
||||||
.onMessage(RequestDeviceList.class, r -> r.groupId.equals(groupId), this::onDeviceList)
|
.onMessage(RequestDeviceList.class, r -> r.groupId.equals(groupId), this::onDeviceList)
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ public class DeviceGroupQuery extends AbstractBehavior<DeviceGroupQueryMessage>
|
||||||
// #query-state
|
// #query-state
|
||||||
@Override
|
@Override
|
||||||
public Receive<DeviceGroupQueryMessage> createReceive() {
|
public Receive<DeviceGroupQueryMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(WrappedRespondTemperature.class, this::onRespondTemperature)
|
.onMessage(WrappedRespondTemperature.class, this::onRespondTemperature)
|
||||||
.onMessage(DeviceTerminated.class, this::onDeviceTerminated)
|
.onMessage(DeviceTerminated.class, this::onDeviceTerminated)
|
||||||
.onMessage(CollectionTimeout.class, this::onCollectionTimeout)
|
.onMessage(CollectionTimeout.class, this::onCollectionTimeout)
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ public class DeviceManager extends AbstractBehavior<DeviceManagerMessage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Receive<DeviceManagerMessage> createReceive() {
|
public Receive<DeviceManagerMessage> createReceive() {
|
||||||
return receiveBuilder()
|
return newReceiveBuilder()
|
||||||
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
.onMessage(RequestTrackDevice.class, this::onTrackDevice)
|
||||||
.onMessage(RequestDeviceList.class, this::onRequestDeviceList)
|
.onMessage(RequestDeviceList.class, this::onRequestDeviceList)
|
||||||
.onMessage(RequestAllTemperatures.class, this::onRequestAllTemperatures)
|
.onMessage(RequestAllTemperatures.class, this::onRequestAllTemperatures)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue