diff --git a/akka-actor-tests/src/test/java/akka/japi/MatchBuilderTest.java b/akka-actor-tests/src/test/java/akka/japi/MatchBuilderTest.java index adcacace73..1d8fec0e66 100644 --- a/akka-actor-tests/src/test/java/akka/japi/MatchBuilderTest.java +++ b/akka-actor-tests/src/test/java/akka/japi/MatchBuilderTest.java @@ -38,4 +38,44 @@ public class MatchBuilderTest { exception.expect(MatchError.class); assertFalse("A string should throw a MatchError", new Double(4711).equals(pf.match("4711"))); } + + + static class GenericClass { + T val; + + public GenericClass(T val) { + this.val = val; + } + } + + @Test + public void shouldHandleMatchOnGenericClass() { + Match pf = Match.create(Match.match(GenericClass.class, new FI.Apply, String>() { + @Override + public String apply(GenericClass stringGenericClass) { + return stringGenericClass.val; + } + })); + + assertTrue("String value should be extract from GenericMessage", "A".equals(pf.match(new GenericClass("A")))); + } + + + @Test + public void shouldHandleMatchWithPredicateOnGenericClass() { + Match pf = Match.create(Match.match(GenericClass.class, new FI.TypedPredicate>() { + @Override + public boolean defined(GenericClass genericClass) { + return !genericClass.val.isEmpty(); + } + }, new FI.Apply, String>() { + @Override + public String apply(GenericClass stringGenericClass) { + return stringGenericClass.val; + } + })); + + exception.expect(MatchError.class); + assertTrue("empty GenericMessage should throw match error", "".equals(pf.match(new GenericClass("")))); + } } diff --git a/akka-actor/src/main/java/akka/japi/pf/Match.java b/akka-actor/src/main/java/akka/japi/pf/Match.java index 8b3dcd24e3..d7743098b4 100644 --- a/akka-actor/src/main/java/akka/japi/pf/Match.java +++ b/akka-actor/src/main/java/akka/japi/pf/Match.java @@ -13,8 +13,8 @@ import scala.PartialFunction; * * @param the input type, that this PartialFunction will be applied to * @param the return type, that the results of the application will have - * - * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. + *

+ * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. */ public class Match extends AbstractMatch { @@ -22,13 +22,13 @@ public class Match extends AbstractMatch { * 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 + * @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 PFBuilder match(final Class

type, - final FI.Apply apply) { + public static PFBuilder match(final Class type, + final FI.Apply apply) { return new PFBuilder().match(type, apply); } @@ -36,15 +36,15 @@ public class Match extends AbstractMatch { * 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 + * @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 PFBuilder match(final Class

type, - final FI.TypedPredicate

predicate, - final FI.Apply apply) { + public static PFBuilder match(final Class type, + final FI.TypedPredicate predicate, + final FI.Apply apply) { return new PFBuilder().match(type, predicate, apply); } @@ -52,7 +52,7 @@ public class Match extends AbstractMatch { * Convenience function to create a {@link PFBuilder} with the first * case statement added. * - * @param object the object to compare equals with + * @param object the object to compare equals with * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added * @see PFBuilder#matchEquals(Object, FI.Apply) @@ -66,7 +66,7 @@ public class Match extends AbstractMatch { * Convenience function to create a {@link PFBuilder} with the first * case statement added. * - * @param apply an action to apply to the argument + * @param apply an action to apply to the argument * @return a builder with the case statement added * @see PFBuilder#matchAny(FI.Apply) */ @@ -77,8 +77,8 @@ public class Match extends AbstractMatch { /** * Create a {@link Match} from the builder. * - * @param builder a builder representing the partial function - * @return a {@link Match} that can be reused + * @param builder a builder representing the partial function + * @return a {@link Match} that can be reused */ public static final Match create(PFBuilder builder) { return new Match(builder.build()); @@ -90,16 +90,16 @@ public class Match extends AbstractMatch { /** * Convenience function to make the Java code more readable. - * + *

*


    *   Matcher<X, Y> matcher = Matcher.create(...);
-   *
+   * 

* Y someY = matcher.match(obj); *

* - * @param i the argument to apply the match to - * @return the result of the application - * @throws MatchError if there is no match + * @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); diff --git a/akka-actor/src/main/java/akka/japi/pf/PFBuilder.java b/akka-actor/src/main/java/akka/japi/pf/PFBuilder.java index 414c8c0b84..bb96c43d5f 100644 --- a/akka-actor/src/main/java/akka/japi/pf/PFBuilder.java +++ b/akka-actor/src/main/java/akka/japi/pf/PFBuilder.java @@ -9,8 +9,8 @@ package akka.japi.pf; * * @param the input type, that this PartialFunction will be applied to * @param the return type, that the results of the application will have - * - * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. + *

+ * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. */ public final class PFBuilder extends AbstractPFBuilder { @@ -23,52 +23,56 @@ public final class PFBuilder extends AbstractPFBuilder { /** * 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 + * @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

PFBuilder match(final Class

type, FI.Apply apply) { - addStatement(new CaseStatement( - new FI.Predicate() { - @Override - public boolean defined(Object o) { - return type.isInstance(o); - } - }, apply)); + @SuppressWarnings("unchecked") + public

PFBuilder match(final Class type, FI.Apply apply) { + + FI.Predicate predicate = new FI.Predicate() { + @Override + public boolean defined(Object o) { + return type.isInstance(o); + } + }; + + addStatement(new CaseStatement(predicate, (FI.Apply) 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 + * @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

PFBuilder match(final Class

type, - final FI.TypedPredicate

predicate, - final FI.Apply apply) { - addStatement(new CaseStatement( - 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); - } + @SuppressWarnings("unchecked") + public

PFBuilder match(final Class type, + final FI.TypedPredicate predicate, + final FI.Apply apply) { + FI.Predicate fiPredicate = new FI.Predicate() { + @Override + public boolean defined(Object o) { + if (!type.isInstance(o)) + return false; + else { + @SuppressWarnings("unchecked") + P p = (P) o; + return ((FI.TypedPredicate

) predicate).defined(p); } - }, apply)); + } + }; + addStatement(new CaseStatement(fiPredicate, (FI.Apply) apply)); return this; } /** * Add a new case statement to this builder. * - * @param object the object to compare equals with + * @param object the object to compare equals with * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added */ @@ -86,8 +90,9 @@ public final class PFBuilder extends AbstractPFBuilder { /** * 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 + * + * @param apply an action to apply to the argument + * @return a builder with the case statement added */ public PFBuilder matchAny(final FI.Apply apply) { addStatement(new CaseStatement( diff --git a/akka-actor/src/main/java/akka/japi/pf/ReceiveBuilder.java b/akka-actor/src/main/java/akka/japi/pf/ReceiveBuilder.java index cd03439b2e..9ec78a29f7 100644 --- a/akka-actor/src/main/java/akka/japi/pf/ReceiveBuilder.java +++ b/akka-actor/src/main/java/akka/japi/pf/ReceiveBuilder.java @@ -6,29 +6,29 @@ 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. - *

+ *

* Example: *

- * @Override
- * public Actor() {
- *   receive(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()
- *   );
+ *
+ * @Override public Actor() {
+ * receive(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()
+ * );
  * }
  * 
- * + *

* This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. */ public class ReceiveBuilder { @@ -38,32 +38,32 @@ public class 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 + * @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

UnitPFBuilder match(final Class

type, FI.UnitApply

apply) { + public static

UnitPFBuilder match(final Class type, FI.UnitApply 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 + * @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

UnitPFBuilder match(final Class

type, - FI.TypedPredicate

predicate, - FI.UnitApply

apply) { + public static

UnitPFBuilder match(final Class type, + FI.TypedPredicate predicate, + FI.UnitApply apply) { return UnitMatch.match(type, predicate, apply); } /** * Return a new {@link UnitPFBuilder} with a case statement added. * - * @param object the object to compare equals with + * @param object the object to compare equals with * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added */ @@ -74,9 +74,9 @@ public class ReceiveBuilder { /** * Return a new {@link UnitPFBuilder} with a case statement added. * - * @param object the object to compare equals with - * @param predicate a predicate that will be evaluated on the argument if the object compares equal - * @param apply an action to apply to the argument if the object compares equal + * @param object the object to compare equals with + * @param predicate a predicate that will be evaluated on the argument if the object compares equal + * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added */ public static

UnitPFBuilder matchEquals(P object, @@ -88,8 +88,8 @@ public class ReceiveBuilder { /** * Return a new {@link UnitPFBuilder} with a case statement added. * - * @param apply an action to apply to the argument - * @return a builder with the case statement added + * @param apply an action to apply to the argument + * @return a builder with the case statement added */ public static UnitPFBuilder matchAny(FI.UnitApply apply) { return UnitMatch.matchAny(apply); diff --git a/akka-actor/src/main/java/akka/japi/pf/UnitMatch.java b/akka-actor/src/main/java/akka/japi/pf/UnitMatch.java index 2a0f19b1d5..8ad187f1e1 100644 --- a/akka-actor/src/main/java/akka/japi/pf/UnitMatch.java +++ b/akka-actor/src/main/java/akka/japi/pf/UnitMatch.java @@ -15,8 +15,8 @@ import scala.runtime.BoxedUnit; * void methods to {@link scala.runtime.BoxedUnit}. * * @param the input type, that this PartialFunction will be applied to - * - * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. + *

+ * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. */ public class UnitMatch extends AbstractMatch { @@ -25,11 +25,11 @@ public class UnitMatch extends AbstractMatch { * 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 + * @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 UnitPFBuilder match(final Class

type, FI.UnitApply

apply) { + public static UnitPFBuilder match(final Class type, FI.UnitApply apply) { return new UnitPFBuilder().match(type, apply); } @@ -37,15 +37,15 @@ public class UnitMatch extends AbstractMatch { * 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 + * @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 UnitPFBuilder match(final Class

type, - final FI.TypedPredicate

predicate, - final FI.UnitApply

apply) { + public static UnitPFBuilder match(final Class type, + final FI.TypedPredicate predicate, + final FI.UnitApply apply) { return new UnitPFBuilder().match(type, predicate, apply); } @@ -53,7 +53,7 @@ public class UnitMatch extends AbstractMatch { * Convenience function to create a {@link UnitPFBuilder} with the first * case statement added. * - * @param object the object to compare equals with + * @param object the object to compare equals with * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added * @see UnitPFBuilder#matchEquals(Object, FI.UnitApply) @@ -67,9 +67,9 @@ public class UnitMatch extends AbstractMatch { * Convenience function to create a {@link UnitPFBuilder} with the first * case statement added. * - * @param object the object to compare equals with - * @param predicate a predicate that will be evaluated on the argument the object compares equal - * @param apply an action to apply to the argument if the object compares equal + * @param object the object to compare equals with + * @param predicate a predicate that will be evaluated on the argument the object compares equal + * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added * @see UnitPFBuilder#matchEquals(Object, FI.UnitApply) */ @@ -83,7 +83,7 @@ public class UnitMatch extends AbstractMatch { * Convenience function to create a {@link UnitPFBuilder} with the first * case statement added. * - * @param apply an action to apply to the argument + * @param apply an action to apply to the argument * @return a builder with the case statement added * @see UnitPFBuilder#matchAny(FI.UnitApply) */ @@ -94,7 +94,7 @@ public class UnitMatch extends AbstractMatch { /** * Create a {@link UnitMatch} from the builder. * - * @param builder a builder representing the partial function + * @param builder a builder representing the partial function * @return a {@link UnitMatch} that can be reused */ public static UnitMatch create(UnitPFBuilder builder) { @@ -107,15 +107,15 @@ public class UnitMatch extends AbstractMatch { /** * Convenience function to make the Java code more readable. - * + *

*


    *   UnitMatcher<X> matcher = UnitMatcher.create(...);
-   *
+   * 

* matcher.match(obj); *

* - * @param i the argument to apply the match to - * @throws scala.MatchError if there is no match + * @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); diff --git a/akka-actor/src/main/java/akka/japi/pf/UnitPFBuilder.java b/akka-actor/src/main/java/akka/japi/pf/UnitPFBuilder.java index 0ce2b03f32..9f8e833f02 100644 --- a/akka-actor/src/main/java/akka/japi/pf/UnitPFBuilder.java +++ b/akka-actor/src/main/java/akka/japi/pf/UnitPFBuilder.java @@ -12,8 +12,8 @@ import scala.runtime.BoxedUnit; * void methods to {@link scala.runtime.BoxedUnit}. * * @param the input type, that this PartialFunction to be applied to - * - * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. + *

+ * This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing. */ public final class UnitPFBuilder extends AbstractPFBuilder { @@ -26,53 +26,60 @@ public final class UnitPFBuilder extends AbstractPFBuilder { /** * 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 + * @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

UnitPFBuilder match(final Class

type, - final FI.UnitApply

apply) { - addStatement(new UnitCaseStatement( - new FI.Predicate() { - @Override - public boolean defined(Object o) { - return type.isInstance(o); + @SuppressWarnings("unchecked") + public

UnitPFBuilder match(final Class type, + final FI.UnitApply apply) { + + FI.Predicate predicate = new FI.Predicate() { + @Override + public boolean defined(Object o) { + return type.isInstance(o); + } + }; + + addStatement(new UnitCaseStatement(predicate, (FI.UnitApply

) apply)); + + return this; + } + + /** + * Add a new case statement to this b uilder. + * + * @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 + */ + @SuppressWarnings("unchecked") + public

UnitPFBuilder match(final Class type, + final FI.TypedPredicate predicate, + final FI.UnitApply apply) { + FI.Predicate fiPredicate = new FI.Predicate() { + @Override + public boolean defined(Object o) { + if (!type.isInstance(o)) + return false; + else { + @SuppressWarnings("unchecked") + P p = (P) o; + return ((FI.TypedPredicate

) predicate).defined(p); } - }, apply)); + } + }; + + addStatement(new UnitCaseStatement(fiPredicate, (FI.UnitApply

) 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

UnitPFBuilder match(final Class

type, - final FI.TypedPredicate

predicate, - final FI.UnitApply

apply) { - addStatement(new UnitCaseStatement( - 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. - * - * @param object the object to compare equals with + * @param object the object to compare equals with * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added */ @@ -83,17 +90,17 @@ public final class UnitPFBuilder extends AbstractPFBuilder { @Override public boolean defined(Object o) { return object.equals(o); - } - }, apply)); + } + }, apply)); return this; } /** * Add a new case statement to this builder. * - * @param object the object to compare equals with - * @param predicate a predicate that will be evaluated on the argument if the object compares equal - * @param apply an action to apply to the argument if the object compares equal + * @param object the object to compare equals with + * @param predicate a predicate that will be evaluated on the argument if the object compares equal + * @param apply an action to apply to the argument if the object compares equal * @return a builder with the case statement added */ public

UnitPFBuilder matchEquals(final P object, @@ -117,8 +124,9 @@ public final class UnitPFBuilder extends AbstractPFBuilder { /** * 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 + * + * @param apply an action to apply to the argument + * @return a builder with the case statement added */ public UnitPFBuilder matchAny(final FI.UnitApply apply) { addStatement(new UnitCaseStatement( diff --git a/akka-actor/src/main/scala/akka/japi/pf/CaseStatements.scala b/akka-actor/src/main/scala/akka/japi/pf/CaseStatements.scala index bfc0ddbe70..ed040b310f 100644 --- a/akka-actor/src/main/scala/akka/japi/pf/CaseStatements.scala +++ b/akka-actor/src/main/scala/akka/japi/pf/CaseStatements.scala @@ -4,13 +4,13 @@ package akka.japi.pf -import FI.{ UnitApply, Apply, Predicate } +import FI.{UnitApply, Apply, Predicate} private[pf] object CaseStatement { def empty[F, T](): PartialFunction[F, T] = PartialFunction.empty } -private[pf] class CaseStatement[F, P, T](predicate: Predicate, apply: Apply[P, T]) +private[pf] class CaseStatement[-F, +P, T](predicate: Predicate, apply: Apply[P, T]) extends PartialFunction[F, T] { override def isDefinedAt(o: F) = predicate.defined(o) @@ -24,4 +24,4 @@ private[pf] class UnitCaseStatement[F, P](predicate: Predicate, apply: UnitApply override def isDefinedAt(o: F) = predicate.defined(o) override def apply(o: F) = apply.apply(o.asInstanceOf[P]) -} +} \ No newline at end of file diff --git a/akka-samples/akka-docs-java-lambda/src/test/java/docs/actor/InitializationDocTest.java b/akka-samples/akka-docs-java-lambda/src/test/java/docs/actor/InitializationDocTest.java index b799e12083..68ed0602c8 100644 --- a/akka-samples/akka-docs-java-lambda/src/test/java/docs/actor/InitializationDocTest.java +++ b/akka-samples/akka-docs-java-lambda/src/test/java/docs/actor/InitializationDocTest.java @@ -1,20 +1,23 @@ +package docs.actor; /** * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.actor; -import akka.actor.*; +import akka.actor.AbstractActor; +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.japi.pf.FI; import akka.japi.pf.ReceiveBuilder; import akka.testkit.JavaTestKit; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import scala.concurrent.duration.Duration; import scala.concurrent.Await; +import scala.concurrent.duration.Duration; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; public class InitializationDocTest { @@ -27,7 +30,7 @@ public class InitializationDocTest { @AfterClass public static void afterClass() throws Exception { - Await.ready(system.terminate(), Duration.create("5 seconds")); + Await.ready(system.terminate(), Duration.create("5 seconds")); } public static class MessageInitExample extends AbstractActor { @@ -36,18 +39,49 @@ public class InitializationDocTest { public MessageInitExample() { //#messageInit receive(ReceiveBuilder. - matchEquals("init", m1 -> { - initializeMe = "Up and running"; - context().become(ReceiveBuilder. - matchEquals("U OK?", m2 -> { - sender().tell(initializeMe, self()); - }).build()); - }).build() - //#messageInit + matchEquals("init", m1 -> { + initializeMe = "Up and running"; + context().become(ReceiveBuilder. + matchEquals("U OK?", m2 -> { + sender().tell(initializeMe, self()); + }).build()); + + }).build() + //#messageInit ); } } + public class GenericMessage { + T value; + + public GenericMessage(T value) { + this.value = value; + } + } + + public static class GenericActor extends AbstractActor { + public GenericActor() { + receive(ReceiveBuilder.match(GenericMessage.class, (GenericMessage msg) -> { + GenericMessage message = msg; + sender().tell(message.value.toUpperCase(), self()); + + }).build()); + + + } + } + + static class GenericActorWithPredicate extends AbstractActor { + public GenericActorWithPredicate() { + FI.TypedPredicate> typedPredicate = s -> !s.value.isEmpty(); + + receive(ReceiveBuilder.match(GenericMessage.class, typedPredicate, (GenericMessage msg) -> { + sender().tell(msg.value.toUpperCase(), self()); + }).build()); + } + } + @Test public void testIt() { @@ -63,4 +97,30 @@ public class InitializationDocTest { expectMsgEquals("Up and running"); }}; } + + @Test + public void testGenericActor() { + new JavaTestKit(system) {{ + ActorRef genericTestActor = system.actorOf(Props.create(GenericActor.class), "genericActor"); + GenericMessage genericMessage = new GenericMessage<>("a"); + + genericTestActor.tell(genericMessage, getRef()); + expectMsgEquals("A"); + }}; + } + + @Test + public void actorShouldNotRespondForEmptyMessage() { + new JavaTestKit(system) {{ + ActorRef genericTestActor = system.actorOf(Props.create(GenericActorWithPredicate.class), "genericActorWithPredicate"); + GenericMessage emptyGenericMessage = new GenericMessage<>(""); + GenericMessage nonEmptyGenericMessage = new GenericMessage<>("a"); + + genericTestActor.tell(emptyGenericMessage, getRef()); + expectNoMsg(); + + genericTestActor.tell(nonEmptyGenericMessage, getRef()); + expectMsgEquals("A"); + }}; + } }