diff --git a/license-report.md b/license-report.md index da6e689c6df..ececa9ef41c 100644 --- a/license-report.md +++ b/license-report.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine:spine-client:2.0.0-SNAPSHOT.170` +# Dependencies of `io.spine:spine-client:2.0.0-SNAPSHOT.171` ## Runtime 1. **Group** : com.google.android. **Name** : annotations. **Version** : 4.1.1.4. @@ -798,12 +798,12 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Wed Nov 01 15:46:08 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Fri Nov 03 00:38:26 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-core:2.0.0-SNAPSHOT.170` +# Dependencies of `io.spine:spine-core:2.0.0-SNAPSHOT.171` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -1561,12 +1561,12 @@ This report was generated on **Wed Nov 01 15:46:08 WET 2023** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Wed Nov 01 15:46:08 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Fri Nov 03 00:38:27 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-server:2.0.0-SNAPSHOT.170` +# Dependencies of `io.spine:spine-server:2.0.0-SNAPSHOT.171` ## Runtime 1. **Group** : com.google.android. **Name** : annotations. **Version** : 4.1.1.4. @@ -2372,12 +2372,12 @@ This report was generated on **Wed Nov 01 15:46:08 WET 2023** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Wed Nov 01 15:46:09 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Fri Nov 03 00:38:27 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-testutil-client:2.0.0-SNAPSHOT.170` +# Dependencies of `io.spine.tools:spine-testutil-client:2.0.0-SNAPSHOT.171` ## Runtime 1. **Group** : com.google.android. **Name** : annotations. **Version** : 4.1.1.4. @@ -3303,12 +3303,12 @@ This report was generated on **Wed Nov 01 15:46:09 WET 2023** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Wed Nov 01 15:46:09 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Fri Nov 03 00:38:28 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-testutil-core:2.0.0-SNAPSHOT.170` +# Dependencies of `io.spine.tools:spine-testutil-core:2.0.0-SNAPSHOT.171` ## Runtime 1. **Group** : com.google.android. **Name** : annotations. **Version** : 4.1.1.4. @@ -4234,12 +4234,12 @@ This report was generated on **Wed Nov 01 15:46:09 WET 2023** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Wed Nov 01 15:46:10 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Fri Nov 03 00:38:28 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-testutil-server:2.0.0-SNAPSHOT.170` +# Dependencies of `io.spine.tools:spine-testutil-server:2.0.0-SNAPSHOT.171` ## Runtime 1. **Group** : com.google.android. **Name** : annotations. **Version** : 4.1.1.4. @@ -5213,4 +5213,4 @@ This report was generated on **Wed Nov 01 15:46:10 WET 2023** using [Gradle-Lice The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Wed Nov 01 15:46:10 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file +This report was generated on **Fri Nov 03 00:38:29 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file diff --git a/pom.xml b/pom.xml index db7a8121183..3bc58567fdb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject. --> io.spine spine-core-java -2.0.0-SNAPSHOT.170 +2.0.0-SNAPSHOT.171 2015 diff --git a/server/src/main/java/io/spine/server/tuple/Either.java b/server/src/main/java/io/spine/server/tuple/Either.java index 0a006ab0003..985226d750b 100644 --- a/server/src/main/java/io/spine/server/tuple/Either.java +++ b/server/src/main/java/io/spine/server/tuple/Either.java @@ -52,7 +52,7 @@ public abstract class Either implements Iterable, Serializable { protected Either(Message value, int index) { /* We need instances of GeneratedMessageV3 as they are Serializable. The only known case of message class which does not descend from - GeneratedMessageV3 is DynamicMessage, and Spine does not support it. */ + GeneratedMessageV3 is DynamicMessage, and Spine SDK does not support it. */ this.value = (GeneratedMessageV3) checkNotNull(value); checkArgument(index >= 0, "Index must be greater or equal zero"); this.index = index; diff --git a/server/src/main/java/io/spine/server/tuple/Element.java b/server/src/main/java/io/spine/server/tuple/Element.java index 905b5272158..a4f61e20ae2 100644 --- a/server/src/main/java/io/spine/server/tuple/Element.java +++ b/server/src/main/java/io/spine/server/tuple/Element.java @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import com.google.protobuf.GeneratedMessageV3; import com.google.protobuf.Message; import io.spine.base.EventMessage; +import io.spine.server.model.Nothing; import java.io.IOException; import java.io.ObjectInputStream; @@ -67,7 +68,11 @@ final class Element implements Serializable { this.type = Type.OPTIONAL; } else if (value instanceof GeneratedMessageV3) { var messageV3 = (GeneratedMessageV3) value; - checkNotDefault(messageV3); + // Treat `Nothing` as a special case, allowing its default instance + // so that `Just` is possible. + if (!(value instanceof Nothing)) { + checkNotDefault(messageV3); + } this.type = Type.MESSAGE; } else { throw newIllegalArgumentException( @@ -82,7 +87,7 @@ final class Element implements Serializable { * Obtains the value of the element by its index and casts it to the type {@code }. */ @SuppressWarnings("TypeParameterUnusedInFormals") // See Javadoc. - static T value(Tuple tuple, IndexOf index) { + static T value(Tuple tuple, IndexOf index) { @SuppressWarnings("unchecked") // The caller is responsible for the correct type. var value = (T) tuple.get(index.value()); return value; diff --git a/server/src/main/java/io/spine/server/tuple/Pair.java b/server/src/main/java/io/spine/server/tuple/Pair.java index 3ab1d42240e..05de92c9004 100644 --- a/server/src/main/java/io/spine/server/tuple/Pair.java +++ b/server/src/main/java/io/spine/server/tuple/Pair.java @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static io.spine.server.tuple.Element.value; -import static io.spine.server.tuple.Values.isOptionalPresent; import static java.util.Optional.ofNullable; /** diff --git a/server/src/main/java/io/spine/server/tuple/Quartet.java b/server/src/main/java/io/spine/server/tuple/Quartet.java index 9992ce254f8..bcb297e455e 100644 --- a/server/src/main/java/io/spine/server/tuple/Quartet.java +++ b/server/src/main/java/io/spine/server/tuple/Quartet.java @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,6 @@ import java.util.Optional; import static io.spine.server.tuple.Element.value; -import static io.spine.server.tuple.Values.isOptionalPresent; import static java.util.Optional.ofNullable; /** @@ -170,13 +169,13 @@ private static M checkNotNullOrEmpty(M value) { return checkNotEmpty(Quartet.class, value); } - @SuppressWarnings("OverloadedVarargsMethod") // to avoid repeated usage of this class name. - private static void checkAllNotNullOrEmpty(Message... values) { + @SafeVarargs + private static void checkAllNotNullOrEmpty(M... values) { checkAllNotNullOrEmpty(Quartet.class, values); } - @SuppressWarnings("OverloadedVarargsMethod") // to avoid repeated usage of this class name. - private static void checkAllNotEmpty(Message... values) { + @SafeVarargs + private static void checkAllNotEmpty(M... values) { checkAllNotEmpty(Quartet.class, values); } } diff --git a/server/src/main/java/io/spine/server/tuple/Quintet.java b/server/src/main/java/io/spine/server/tuple/Quintet.java index e953477b782..abbfa428ce0 100644 --- a/server/src/main/java/io/spine/server/tuple/Quintet.java +++ b/server/src/main/java/io/spine/server/tuple/Quintet.java @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,6 @@ import java.util.Optional; import static io.spine.server.tuple.Element.value; -import static io.spine.server.tuple.Values.isOptionalPresent; import static java.util.Optional.ofNullable; /** @@ -62,8 +61,8 @@ * the type of the fifth element */ public final class Quintet - extends Tuple - implements AValue, BValue, CValue, DValue, EValue { + extends Tuple + implements AValue, BValue, CValue, DValue, EValue { private static final long serialVersionUID = 0L; @@ -203,13 +202,13 @@ private static M checkNotNullOrEmpty(M value) { return checkNotEmpty(Quintet.class, value); } - @SuppressWarnings("OverloadedVarargsMethod") // to avoid repeated usage of this class name. - private static void checkAllNotNullOrEmpty(Message... values) { + @SafeVarargs + private static void checkAllNotNullOrEmpty(M... values) { checkAllNotNullOrEmpty(Quintet.class, values); } - @SuppressWarnings("OverloadedVarargsMethod") // to avoid repeated usage of this class name. - private static void checkAllNotEmpty(Message... values) { + @SafeVarargs + private static void checkAllNotEmpty(M... values) { checkAllNotEmpty(Quintet.class, values); } } diff --git a/server/src/main/java/io/spine/server/tuple/Triplet.java b/server/src/main/java/io/spine/server/tuple/Triplet.java index 4b53e0f716d..804b865a60e 100644 --- a/server/src/main/java/io/spine/server/tuple/Triplet.java +++ b/server/src/main/java/io/spine/server/tuple/Triplet.java @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,6 @@ import java.util.Optional; import static io.spine.server.tuple.Element.value; -import static io.spine.server.tuple.Values.isOptionalPresent; import static java.util.Optional.ofNullable; /** @@ -144,13 +143,13 @@ private static M checkNotNullOrEmpty(M value) { return checkNotEmpty(Triplet.class, value); } - @SuppressWarnings("OverloadedVarargsMethod") // to avoid repeated usage of this class name. - private static void checkAllNotNullOrEmpty(Message... values) { + @SafeVarargs + private static void checkAllNotNullOrEmpty(M... values) { checkAllNotNullOrEmpty(Triplet.class, values); } - @SuppressWarnings("OverloadedVarargsMethod") // to avoid repeated usage of this class name. - private static void checkAllNotEmpty(Message... values) { + @SafeVarargs + private static void checkAllNotEmpty(M... values) { checkAllNotEmpty(Triplet.class, values); } } diff --git a/server/src/main/java/io/spine/server/tuple/Tuple.java b/server/src/main/java/io/spine/server/tuple/Tuple.java index bdd19e74ff1..531df0609b5 100644 --- a/server/src/main/java/io/spine/server/tuple/Tuple.java +++ b/server/src/main/java/io/spine/server/tuple/Tuple.java @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -107,15 +107,17 @@ M checkNotNullOrEmpty(Class checkingClass, M value) { return result; } - static - void checkAllNotNullOrEmpty(Class checkingClass, Message... values) { + @SafeVarargs + static + void checkAllNotNullOrEmpty(Class checkingClass, M... values) { for (var value : values) { checkNotNullOrEmpty(checkingClass, value); } } - static - void checkAllNotEmpty(Class checkingClass, Message... values) { + @SafeVarargs + static + void checkAllNotEmpty(Class checkingClass, M... values) { for (var value : values) { checkNotEmpty(checkingClass, value); } @@ -157,6 +159,20 @@ public final boolean equals(Object obj) { return Objects.equals(this.values, other.values); } + /** + * If the passed {@code value} is an {@code Optional}, tells if its value is present. + * + *

Otherwise, returns {@code true}. + */ + static boolean isOptionalPresent(Object value) { + checkNotNull(value); + if(!(value instanceof Optional)) { + return true; + } + var asOptional = (Optional) value; + return asOptional.isPresent(); + } + /** * Traverses through elements obtaining a message value from them. */ diff --git a/server/src/main/kotlin/io/spine/server/event/Just.kt b/server/src/main/kotlin/io/spine/server/event/Just.kt index e8ec28f731d..5a256804b2b 100644 --- a/server/src/main/kotlin/io/spine/server/event/Just.kt +++ b/server/src/main/kotlin/io/spine/server/event/Just.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,12 +27,14 @@ package io.spine.server.event import io.spine.base.EventMessage +import io.spine.server.model.Nothing import io.spine.server.tuple.Tuple /** * A tuple of one event. * - * Used when returning an iterable from a handler method for better readability over `List`. + * Used when returning an `Iterable` from a handler method for better readability over + * `Iterable` or `List`. * * @param E the type of the event. */ @@ -40,8 +42,16 @@ public class Just(event: E) : Tuple(event) { public companion object { + @Suppress("ConstPropertyName") // Following Java conventions. private const val serialVersionUID: Long = 0L + /** + * The instance of `Just`. + */ + public val nothing: Just by lazy { + Just(Nothing.getDefaultInstance()) + } + /** * A factory method for Java. * @@ -51,5 +61,13 @@ public class Just(event: E) : Tuple(event) { */ @JvmStatic public fun just(event: E): Just = Just(event) + + /** + * Obtains the instance of `Just` for Java code. + * + * Prefer the [nothing] property of the companion object in Kotlin. + */ + @JvmStatic + public fun nothing(): Just = nothing } } diff --git a/server/src/main/kotlin/io/spine/server/event/Policy.kt b/server/src/main/kotlin/io/spine/server/event/Policy.kt index 23c28b29318..91fdd395b36 100644 --- a/server/src/main/kotlin/io/spine/server/event/Policy.kt +++ b/server/src/main/kotlin/io/spine/server/event/Policy.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ package io.spine.server.event import com.google.common.collect.ImmutableSet +import com.google.protobuf.Message import io.spine.base.EventMessage import io.spine.core.ContractFor import io.spine.logging.WithLogging @@ -34,35 +35,99 @@ import io.spine.server.BoundedContext import io.spine.server.type.EventClass /** - * A policy converts one event into zero to many other events. + * A policy converts one event into zero to many other events. * * As a rule of thumb, a policy should read: - * Whenever , then . - * - * For example: - * Whenever a field option is discovered, a validation rule must be added. + * ```markdown + * Whenever , then . + * ``` + * For example, + * ```markdown + * Whenever a field option is discovered, a validation rule must be added. + * ``` + * To implement the policy, override the [whenever] method to return events produced in response + * to the incoming event. * - * To implement the policy, declare a method which reacts to an event with an event: + * For the policy rule in the example above, the code would look like this: * ```kotlin - * class MyPolicy : Policy() { + * class ValidationRulePolicy : Policy() { * * @React - * override fun whenever(event: ProjectCreated): Just { + * override fun whenever(event: FieldOptionDiscovered): Just { * // Produce the event. * } * } * ``` - * @param E the type of the event handled by this policy + * ### Returning zero events + * The contract of the [whenever] method requires returning an `Iterable` of event messages. + * To return no events, declare the return type as `Just`, where `Nothing` is + * the type from the `io.spine.server.model` package. Return the value of `Just.nothing` property + * from your Kotlin method, or `Just.nothing()` from Java. + * + * If you need to avoid the naming collision with [kotlin.Nothing], consider using + * type aliases [NothingHappened][io.spine.server.model.NothingHappened] or + * [NoReaction][io.spine.server.model.NoReaction]. + * + * ### Returning one event + * To return one event, declare `Just` as the return type of the [whenever] method. + * Use the [Just] constructor from Kotlin or [Just.just]`()` static method from Java. + * + * ### Returning more than one event + * To make your return type more readable, consider using the following classes from + * the `io.spine.server.tuple` package: + * [Pair][io.spine.server.tuple.Pair], + * [Triplet][io.spine.server.tuple.Triplet], [Quartet][io.spine.server.tuple.Quartet], + * [Quintet][io.spine.server.tuple.Quintet], with the corresponding number of elements declared + * in the return type of the [whenever] method. For example, `Pair`. + * + * For returning more than five events, please use `Iterable`, as usually. + * + * @param E the type of the event handled by this policy. + * + * @see Just + * @see [io.spine.server.tuple.Pair] + * @see [io.spine.server.tuple.Triplet] + * @see [io.spine.server.tuple.Quartet] + * @see [io.spine.server.tuple.Quintet] + * @see [io.spine.server.model.Nothing] + * @see [io.spine.server.model.NothingHappened] + * @see [io.spine.server.model.NoReaction] */ public abstract class Policy : AbstractEventReactor(), WithLogging { protected lateinit var context: BoundedContext + init { + // This call would check that there is only one event receptor + // defined in the derived class. + // Doing it earlier, here, in the constructor without waiting until + // the dispatching schema is built (thus gathering the message classes), + // allows failing faster and avoiding delayed debugging. + messageClasses() + } + /** * Handles an event and produces some number of events in response. + * + * ### API NOTE + * + * This method returns `Iterable` instead of `Iterable`, + * to allow implementing classes declare the return types using classes descending from + * [Either][io.spine.server.tuple.Either]. For example, `EitherOf2`. + * + * `Either` implements `Iterable`. Classes extending `Either` have two or + * more generic parameters bounded by `Message`, not `EventMessage`. + * Therefore, these classes will not be accepted as return types of + * the overridden methods because `Iterable` will not be + * a super type for them. + * + * Policy authors should declare return types of the overridden methods as described + * in the [class documentation][Policy]. + * + * @see Policy */ @ContractFor(handler = React::class) - protected abstract fun whenever(event: E): Iterable + protected abstract fun whenever(event: E): Iterable final override fun registerWith(context: BoundedContext) { super.registerWith(context) diff --git a/server/src/main/java/io/spine/server/tuple/Values.java b/server/src/main/kotlin/io/spine/server/model/EventExts.kt similarity index 61% rename from server/src/main/java/io/spine/server/tuple/Values.java rename to server/src/main/kotlin/io/spine/server/model/EventExts.kt index 22150d43ea3..c81668eea02 100644 --- a/server/src/main/java/io/spine/server/tuple/Values.java +++ b/server/src/main/kotlin/io/spine/server/model/EventExts.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022, TeamDev. All rights reserved. + * Copyright 2023, TeamDev. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,34 +24,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.server.tuple; - -import java.util.Optional; - -import static com.google.common.base.Preconditions.checkNotNull; +package io.spine.server.model /** - * A utility for working with {@link Tuple} values. + * The alias for cases of naming collisions between + * [io.spine.server.model.Nothing] and [kotlin.Nothing]. */ -final class Values { +public typealias NothingHappened = Nothing - /** - * Prevents this utility class from instantiation. - */ - private Values() { - } +/** + * The alias for cases of naming collisions between + * [io.spine.server.model.Nothing] and [kotlin.Nothing]. + */ +public typealias NoReaction = Nothing - /** - * If the passed {@code value} is an {@code Optional}, tells if its value is present. - * - *

Otherwise, returns {@code true}. - */ - static boolean isOptionalPresent(Object value) { - checkNotNull(value); - if(!(value instanceof Optional)) { - return true; - } - var asOptional = (Optional) value; - return asOptional.isPresent(); - } -} diff --git a/server/src/test/java/io/spine/server/tuple/TupleTest.java b/server/src/test/java/io/spine/server/tuple/TupleTest.java index 38603894128..6bf90786fcd 100644 --- a/server/src/test/java/io/spine/server/tuple/TupleTest.java +++ b/server/src/test/java/io/spine/server/tuple/TupleTest.java @@ -39,9 +39,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.Iterator; - -import static io.spine.server.tuple.Values.isOptionalPresent; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/server/src/test/kotlin/io/spine/server/event/PolicySpec.kt b/server/src/test/kotlin/io/spine/server/event/PolicySpec.kt new file mode 100644 index 00000000000..2a639095c31 --- /dev/null +++ b/server/src/test/kotlin/io/spine/server/event/PolicySpec.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2023, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.server.event + +import io.kotest.matchers.shouldBe +import io.spine.core.External +import io.spine.server.model.Nothing +import io.spine.server.tuple.EitherOf2 +import io.spine.test.shared.event.SomethingHappened +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +@DisplayName("`Policy` should") +internal class PolicySpec { + + @Test + fun `do not allow adding more react methods`() { + assertThrows { + GreedyPolicy() + } + } + + @Test + fun `allow using 'Just' in return value`() { + val policy = object : Policy() { + @React + public override fun whenever(event: SomethingHappened): Just { + return Just.nothing + } + } + policy.whenever(somethingHappened) shouldBe Just.nothing + } + + @Test + fun `allow using 'Either' in return value`() { + object : Policy() { + @React + public override fun whenever(event: SomethingHappened): EitherOf2 { + return EitherOf2.withA(nothing) + } + }.let { + it.whenever(somethingHappened) shouldBe EitherOf2.withA(nothing) + } + } + + companion object { + val somethingHappened = SomethingHappened.getDefaultInstance() + val nothing = Nothing.getDefaultInstance() + } +} + +/** + * The policy which attempts to define a `@React` receptor to handle more than one + * event type, as required by the `Policy` contract. + */ +private class GreedyPolicy : Policy() { + + @React + override fun whenever(@External event: Nothing): Just = + Just.nothing + + @React + fun on(@Suppress("UNUSED_PARAMETER") e: SomethingHappened): Just = + Just.nothing +} diff --git a/version.gradle.kts b/version.gradle.kts index 3d1fb0002eb..ed1c8a3aa17 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -29,4 +29,4 @@ * * For versions of Spine-based dependencies, please see [io.spine.internal.dependency.Spine]. */ -val versionToPublish: String by extra("2.0.0-SNAPSHOT.170") +val versionToPublish: String by extra("2.0.0-SNAPSHOT.171")