Value: secondary clauses now use Supplier's to enable short circuiting

This commit is contained in:
Paul Campbell 2018-03-13 17:53:16 +00:00
parent efc1705a6c
commit ac3e253bf2
5 changed files with 180 additions and 98 deletions

View file

@ -59,7 +59,7 @@ if (isTrue() && isAlsoTrue()) {
[[source,java]]
----
Condition.where(isTrue())
.and(isAlsoTrue())
.and(() -> isAlsoTrue())
.then(() -> doSomething())
.otherwise(() -> doSomethingElse());
----
@ -78,7 +78,7 @@ if (isTrue() || alternativeIsTrue()) {
[[source,java]]
----
Condition.where(isTrue())
.or(alternativeIsTrue())
.or(() -> alternativeIsTrue())
.then(() -> doSomething())
.otherwise(() -> doSomethingElse());
----
@ -115,7 +115,7 @@ if (isTrue() || !isFalse()) {
[[source,java]]
----
Condition.where(isTrue())
.andNot(isFalse())
.andNot(() -> isFalse())
.then(() -> doSomething())
.otherwise(() -> doSomethingElse());
----
@ -134,7 +134,7 @@ if (isFalse() || !isAlsoFalse()) {
[[source,java]]
----
Condition.where(isFalse())
.orNot(isAlsoFalse())
.orNot(() -> isAlsoFalse())
.then(() -> doSomething())
.otherwise(() -> doSomethingElse());
----
@ -154,7 +154,7 @@ if (isFalse()) {
----
Condition.where(isFalse())
.then(() -> doSomething())
.otherwise(isTrue())
.otherwise(() -> isTrue())
.then(() -> doSomethingElse());
----
@ -174,7 +174,7 @@ if (isTrue()) {
----
Condition.where(isTrue())
.then(() -> doSomething())
.and(isAlsoTrue())
.and(() -> isAlsoTrue())
.then(() -> doSomethingElse());
----
@ -213,8 +213,9 @@ final Optional<String> result = Value.where(isTrue(), () -> TRUE);
[[source,java]]
----
final String result = Value.<String>where(isTrue()).then(() -> TRUE)
.otherwise(() -> FALSE);
final String result = Value.<String>where(isTrue())
.then(() -> TRUE)
.otherwise(() -> FALSE);
----
### if-not-then-else
@ -231,8 +232,9 @@ if (!isTrue()) {
[[source,java]]
----
final String result = Value.<String>whereNot(isTrue()).then(() -> TRUE)
.otherwise(() -> FALSE);
final String result = Value.<String>whereNot(isTrue())
.then(() -> TRUE)
.otherwise(() -> FALSE);
----
### if-and-then-else
@ -249,9 +251,10 @@ if (isTrue() && alternativeIsTrue()) {
[[source,java]]
----
final String result = Value.<String>where(isTrue()).and(alternativeIsTrue())
.then(() -> TRUE)
.otherwise(() -> FALSE);
final String result = Value.<String>where(isTrue())
.and(() -> alternativeIsTrue())
.then(() -> TRUE)
.otherwise(() -> FALSE);
----
### if-and-not-then-else
@ -268,9 +271,10 @@ if (isTrue() && !alternativeIsFalse()) {
[[source,java]]
----
final String result = Value.<String>where(isTrue()).andNot(alternativeIsFalse())
.then(() -> TRUE)
.otherwise(() -> FALSE);
final String result = Value.<String>where(isTrue())
.andNot(() -> alternativeIsFalse())
.then(() -> TRUE)
.otherwise(() -> FALSE);
----
### if-or-then-else
@ -287,9 +291,10 @@ if (isTrue() || alternativeIsTrue()) {
[[source,java]]
----
final String result = Value.<String>where(isTrue()).or(alternativeIsTrue())
.then(() -> TRUE)
.otherwise(() -> FALSE);
final String result = Value.<String>where(isTrue())
.or(() -> alternativeIsTrue())
.then(() -> TRUE)
.otherwise(() -> FALSE);
----
### if-or-not-then-else
@ -306,7 +311,27 @@ if (isTrue() || !isFalse()) {
[[source,java]]
----
final String result = Value.<String>where(isTrue()).orNot(isFalse())
.then(() -> TRUE)
.otherwise(() -> FALSE);
final String result = Value.<String>where(isTrue())
.orNot(() -> isFalse())
.then(() -> TRUE)
.otherwise(() -> FALSE);
----
### if-then
[[source,java]]
-----
Optional<String> result;
if (isTrue()) {
result = Optional.of(TRUE);
} else {
result = Optional.empty();
}
-----
[[source,java]]
-----
final Optional<String> result = Value.<String>where(isTrue())
.then(() -> TRUE)
.optional();
-----

View file

@ -21,6 +21,7 @@
package net.kemitix.conditional;
import java.util.Optional;
import java.util.function.Supplier;
/**
@ -40,14 +41,13 @@ class FalseValueClause<T> implements Value.ValueClause<T> {
}
@Override
public Value.ValueClause<T> and(final boolean clause) {
public Value.ValueClause<T> and(final Supplier<Boolean> clause) {
return this;
}
@Override
@SuppressWarnings("PMD.ShortMethodName")
public Value.ValueClause<T> or(final boolean clause) {
return Value.where(clause);
public Value.ValueClause<T> or(final Supplier<Boolean> clause) {
return Value.where(clause.get());
}
/**
@ -62,6 +62,11 @@ class FalseValueClause<T> implements Value.ValueClause<T> {
return falseSupplier.get();
}
@Override
public Optional<T> optional() {
return Optional.empty();
}
}
}

View file

@ -23,6 +23,7 @@ package net.kemitix.conditional;
import lombok.RequiredArgsConstructor;
import java.util.Optional;
import java.util.function.Supplier;
/**
@ -42,13 +43,12 @@ class TrueValueClause<T> implements Value.ValueClause<T> {
}
@Override
public Value.ValueClause<T> and(final boolean clause) {
return Value.where(clause);
public Value.ValueClause<T> and(final Supplier<Boolean> clause) {
return Value.where(clause.get());
}
@Override
@SuppressWarnings("PMD.ShortMethodName")
public Value.ValueClause<T> or(final boolean clause) {
public Value.ValueClause<T> or(final Supplier<Boolean> clause) {
return this;
}
@ -60,7 +60,6 @@ class TrueValueClause<T> implements Value.ValueClause<T> {
@RequiredArgsConstructor
private static final class TrueValueSupplier<T> implements ValueSupplier<T> {
@SuppressWarnings("PMD.BeanMembersShouldSerialize")
private final Supplier<T> valueSupplier;
@Override
@ -68,6 +67,11 @@ class TrueValueClause<T> implements Value.ValueClause<T> {
return valueSupplier.get();
}
@Override
public Optional<T> optional() {
return Optional.ofNullable(valueSupplier.get());
}
}
}

View file

@ -41,11 +41,10 @@ public interface Value {
*
* @return the value from either the trueSupplier or the falseSupplier
*/
@SuppressWarnings("PMD.LawOfDemeter")
static <T> T where(
boolean clause,
Supplier<T> trueSupplier,
Supplier<T> falseSupplier
final boolean clause,
final Supplier<T> trueSupplier,
final Supplier<T> falseSupplier
) {
return Value.<T>where(clause).then(trueSupplier)
.otherwise(falseSupplier);
@ -61,8 +60,8 @@ public interface Value {
* @return an Optional either containing the value from the trueSupplier or empty
*/
static <T> Optional<T> where(
boolean clause,
Supplier<T> trueSupplier
final boolean clause,
final Supplier<T> trueSupplier
) {
return Optional.ofNullable(Value.where(clause, trueSupplier, () -> null));
}
@ -75,7 +74,6 @@ public interface Value {
*
* @return a true or false value clause
*/
@SuppressWarnings({"unchecked", "avoidinlineconditionals"})
static <T> ValueClause<T> where(final boolean clause) {
return (ValueClause<T>) (clause ? TrueValueClause.TRUE : FalseValueClause.FALSE);
}
@ -88,7 +86,7 @@ public interface Value {
*
* @return a true or false value clause
*/
static <T> ValueClause<T> whereNot(boolean clause) {
static <T> ValueClause<T> whereNot(final boolean clause) {
return where(!clause);
}
@ -115,7 +113,7 @@ public interface Value {
*
* @return a true or false value clause
*/
ValueClause<T> and(boolean clause);
ValueClause<T> and(Supplier<Boolean> clause);
/**
* Logically OR combine the current {@link ValueClause} with clause.
@ -124,8 +122,7 @@ public interface Value {
*
* @return a true or false value clause
*/
@SuppressWarnings("PMD.ShortMethodName")
ValueClause<T> or(boolean clause);
ValueClause<T> or(Supplier<Boolean> clause);
/**
* Logically AND combine the current {@link ValueClause} with boolean opposite of the clause.
@ -134,8 +131,8 @@ public interface Value {
*
* @return a true or false value clause
*/
default ValueClause<T> andNot(final boolean clause) {
return and(!clause);
default ValueClause<T> andNot(final Supplier<Boolean> clause) {
return and(() -> !clause.get());
}
/**
@ -145,8 +142,8 @@ public interface Value {
*
* @return a true or false value clause
*/
default ValueClause<T> orNot(boolean clause) {
return or(!clause);
default ValueClause<T> orNot(final Supplier<Boolean> clause) {
return or(() -> !clause.get());
}
/**
@ -165,6 +162,12 @@ public interface Value {
*/
T otherwise(Supplier<T> falseSupplier);
/**
* Returns the value in an Optional if the {@link ValueClause} is true, or an empty Optional if it is false.
*
* @return an Optional, possibly containing the value
*/
Optional<T> optional();
}
}

View file

@ -4,6 +4,7 @@ import lombok.val;
import org.junit.Test;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.Assertions.assertThat;
@ -52,7 +53,7 @@ public class ValueTest {
public void valueWhereClauseIsTrue() {
//when
val result = Value.<String>where(true).then(() -> TRUE)
.otherwise(() -> FALSE);
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -61,7 +62,7 @@ public class ValueTest {
public void valueWhereClauseIsFalse() {
//when
val result = Value.<String>where(false).then(() -> TRUE)
.otherwise(() -> FALSE);
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -69,9 +70,9 @@ public class ValueTest {
@Test
public void valueWhereTrueAndTrueIsTrue() {
//when
val result = Value.<String>where(true).and(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).and(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -79,9 +80,9 @@ public class ValueTest {
@Test
public void valueWhereTrueAndFalseIsFalse() {
//when
val result = Value.<String>where(true).and(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).and(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -89,9 +90,9 @@ public class ValueTest {
@Test
public void valueWhereFalseAndTrueIsFalse() {
//when
val result = Value.<String>where(false).and(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).and(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -99,9 +100,9 @@ public class ValueTest {
@Test
public void valueWhereFalseAndFalseIsFalse() {
//when
val result = Value.<String>where(false).and(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).and(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -109,9 +110,9 @@ public class ValueTest {
@Test
public void valueWhereTrueOrTrueIsTrue() {
//when
val result = Value.<String>where(true).or(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).or(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -119,9 +120,9 @@ public class ValueTest {
@Test
public void valueWhereTrueOrFalseIsTrue() {
//when
val result = Value.<String>where(true).or(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).or(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -129,9 +130,9 @@ public class ValueTest {
@Test
public void valueWhereFalseOrTrueIsTrue() {
//when
val result = Value.<String>where(false).or(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).or(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -139,9 +140,9 @@ public class ValueTest {
@Test
public void valueWhereFalseOrFalseIsFalse() {
//when
val result = Value.<String>where(false).or(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).or(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -150,7 +151,7 @@ public class ValueTest {
public void valueWhereNotTrueIsFalse() {
//when
val result = Value.<String>whereNot(true).then(() -> TRUE)
.otherwise(() -> FALSE);
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -159,7 +160,7 @@ public class ValueTest {
public void valueWhereNotFalseIsTrue() {
//when
val result = Value.<String>whereNot(false).then(() -> TRUE)
.otherwise(() -> FALSE);
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -167,9 +168,9 @@ public class ValueTest {
@Test
public void valueWhereTrueAndNotTrueIsFalse() {
//when
val result = Value.<String>where(true).andNot(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).andNot(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -177,9 +178,9 @@ public class ValueTest {
@Test
public void valueWhereTrueAndNotFalseIsTrue() {
//when
val result = Value.<String>where(true).andNot(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).andNot(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -187,9 +188,9 @@ public class ValueTest {
@Test
public void valueWhereFalseAndNotTrueIsFalse() {
//when
val result = Value.<String>where(false).andNot(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).andNot(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -197,9 +198,9 @@ public class ValueTest {
@Test
public void valueWhereFalseAndNotFalseIsFalse() {
//when
val result = Value.<String>where(false).andNot(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).andNot(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -207,9 +208,9 @@ public class ValueTest {
@Test
public void valueWhereTrueOrNotTrueIsTrue() {
//when
val result = Value.<String>where(true).orNot(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).orNot(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -217,9 +218,9 @@ public class ValueTest {
@Test
public void valueWhereTrueOrNotFalseIsTrue() {
//when
val result = Value.<String>where(true).orNot(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(true).orNot(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@ -227,9 +228,9 @@ public class ValueTest {
@Test
public void valueWhereFalseOrNotTrueIsFalse() {
//when
val result = Value.<String>where(false).orNot(true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).orNot(() -> true)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(FALSE);
}
@ -237,10 +238,54 @@ public class ValueTest {
@Test
public void valueWhereFalseOrNotFalseIsTrue() {
//when
val result = Value.<String>where(false).orNot(false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
val result = Value.<String>where(false).orNot(() -> false)
.then(() -> TRUE)
.otherwise(() -> FALSE);
//then
assertThat(result).isEqualTo(TRUE);
}
@Test
public void valueWhereTrueThenIsNotEmpty() {
//given
final Optional<Object> result = Value.where(true).then(() -> "value").optional();
//then
assertThat(result).contains("value");
}
@Test
public void valueWhereFalseThenIsEmpty() {
//given
final Optional<Object> result = Value.where(false).then(() -> "value").optional();
//when
assertThat(result).isEmpty();
}
@Test
public void shortCurcuitOr() {
//given
final AtomicInteger atomicInteger = new AtomicInteger();
//when
final Optional<String> result = Value.<String>where(true)
.or(() -> atomicInteger.compareAndSet(0, 2))
.then(() -> "Pass")
.optional();
//then
assertThat(result).contains("Pass");
assertThat(atomicInteger).hasValue(0);
}
@Test
public void shortCurcuitAnd() {
//given
final AtomicInteger atomicInteger = new AtomicInteger();
//when
final Optional<String> result = Value.<String>where(false)
.and(() -> atomicInteger.compareAndSet(0, 2))
.then(() -> "Pass")
.optional();
//then
assertThat(result).isEmpty();
assertThat(atomicInteger).hasValue(0);
}
}