From 419b298f5be51b67ae66cb0ce69e20721ecd5cff Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 21 Apr 2017 14:46:18 +0100 Subject: [PATCH 01/12] pom.xml: version set to 0.2.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d75aa0a..55ed31f 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ conditional - 0.1.0 + 0.2.0-SNAPSHOT From ca49a94a7d0d823ebf1a0c42580ee9dacf0f951f Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 21 Apr 2017 18:10:14 +0100 Subject: [PATCH 02/12] ConditionalTest: clean up helper methods --- .../kemitix/conditional/ConditionalTest.java | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/test/java/net/kemitix/conditional/ConditionalTest.java b/src/test/java/net/kemitix/conditional/ConditionalTest.java index 67c52a1..f249ffc 100644 --- a/src/test/java/net/kemitix/conditional/ConditionalTest.java +++ b/src/test/java/net/kemitix/conditional/ConditionalTest.java @@ -180,23 +180,43 @@ public class ConditionalTest { } private void thenBothResponsesRun() { - assertThat(thenFlag).isTrue(); - assertThat(otherwiseFlag).isTrue(); + theThenResponseRan(); + theOtherwiseResponseRan(); } private void thenTheThenResponseRuns() { - assertThat(thenFlag).isTrue(); - assertThat(otherwiseFlag).isFalse(); + theThenResponseRan(); + theOtherwiseResponseDidNotRun(); } private void thenTheOtherwiseResponseRuns() { - assertThat(thenFlag).isFalse(); - assertThat(otherwiseFlag).isTrue(); + theThenResponseDidNotRun(); + theOtherwiseResponseRan(); + } + + private void theOtherwiseResponseRan() { + assertThat(otherwiseFlag).as("otherwise response runs") + .isTrue(); + } + + private void theThenResponseRan() { + assertThat(thenFlag).as("then response runs") + .isTrue(); + } + + private void theOtherwiseResponseDidNotRun() { + assertThat(otherwiseFlag).as("otherwise response does not run") + .isFalse(); + } + + private void theThenResponseDidNotRun() { + assertThat(thenFlag).as("then response does not run") + .isFalse(); } private void thenNoResponseRuns() { - assertThat(thenFlag).isFalse(); - assertThat(otherwiseFlag).isFalse(); + theThenResponseDidNotRun(); + theOtherwiseResponseDidNotRun(); } private void when(final boolean firstClause, final boolean secondClause) { From 826dcc17ca1766c4ec91f5677234632efaccdea0 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 21 Apr 2017 18:37:14 +0100 Subject: [PATCH 03/12] ConditionalTest: more tests --- .../kemitix/conditional/ConditionalTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/java/net/kemitix/conditional/ConditionalTest.java b/src/test/java/net/kemitix/conditional/ConditionalTest.java index f249ffc..4a49fb4 100644 --- a/src/test/java/net/kemitix/conditional/ConditionalTest.java +++ b/src/test/java/net/kemitix/conditional/ConditionalTest.java @@ -166,6 +166,26 @@ public class ConditionalTest { thenNoResponseRuns(); } + @Test + public void whereTrueChainedThensBothRuns() { + //when + Condition.where(true) + .then(thenResponse) + .then(otherwiseResponse); + //then + thenBothResponsesRun(); + } + + @Test + public void whereFalseChainedThensNothingRuns() { + //when + Condition.where(false) + .then(thenResponse) + .then(otherwiseResponse); + //then + thenNoResponseRuns(); + } + private void whenOr(final boolean firstClause, final boolean secondClause) { Condition.where(firstClause) .or(secondClause) From dcf1847def64e50207d002c06d63f8a6f48644de Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 22 Apr 2017 07:34:44 +0100 Subject: [PATCH 04/12] Condition: remove use of 'if' internaly By using a look-up map for true and false the only branch in the code is removed. --- .../net/kemitix/conditional/Condition.java | 60 ++++++++----------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/src/main/java/net/kemitix/conditional/Condition.java b/src/main/java/net/kemitix/conditional/Condition.java index 7a5f313..842c98c 100644 --- a/src/main/java/net/kemitix/conditional/Condition.java +++ b/src/main/java/net/kemitix/conditional/Condition.java @@ -21,8 +21,11 @@ package net.kemitix.conditional; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * If-then-else in a functional-style. @@ -31,6 +34,14 @@ import lombok.NoArgsConstructor; */ public interface Condition { + Condition TRUE = new TrueCondition(); + + Condition FALSE = new FalseCondition(); + + Map CONDITIONS = Collections.unmodifiableMap( + Stream.of(new SimpleEntry<>(true, TRUE), new SimpleEntry<>(false, FALSE)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); + /** * Create a new {@code Condition} for the clause. * @@ -39,10 +50,7 @@ public interface Condition { * @return the Condition */ static Condition where(final boolean clause) { - if (clause) { - return TrueCondition.getInstance(); - } - return FalseCondition.getInstance(); + return CONDITIONS.get(clause); } /** @@ -52,7 +60,7 @@ public interface Condition { * * @return the Condition */ - static Condition whereNot(boolean clause) { + static Condition whereNot(final boolean clause) { return where(!clause); } @@ -72,7 +80,7 @@ public interface Condition { * * @return the Condition */ - default Condition andNot(boolean clause) { + default Condition andNot(final boolean clause) { return and(!clause); } @@ -92,7 +100,7 @@ public interface Condition { * * @return the Condition */ - default Condition orNot(boolean clause) { + default Condition orNot(final boolean clause) { return or(!clause); } @@ -119,39 +127,29 @@ public interface Condition { * * @return the Condition */ - default Condition otherwise(boolean clause) { + default Condition otherwise(final boolean clause) { return where(clause); } /** * A {@code Condition} that has evaluated to {@code true}. */ - @NoArgsConstructor(access = AccessLevel.PRIVATE) class TrueCondition implements Condition { - private static final Condition INSTANCE = new TrueCondition(); - - private static Condition getInstance() { - return INSTANCE; - } - @Override public Condition and(final boolean clause) { - if (clause) { - return this; - } - return FalseCondition.getInstance(); + return where(clause); } @Override public Condition or(final boolean secondClause) { - return this; + return TRUE; } @Override public Condition then(final Runnable response) { response.run(); - return this; + return TRUE; } @Override @@ -163,31 +161,21 @@ public interface Condition { /** * A {@code Condition} that has evaluated to {@code false}. */ - @NoArgsConstructor(access = AccessLevel.PRIVATE) class FalseCondition implements Condition { - private static final Condition INSTANCE = new FalseCondition(); - - private static Condition getInstance() { - return INSTANCE; - } - @Override public Condition and(final boolean clause) { - return this; + return FALSE; } @Override public Condition or(final boolean secondClause) { - if (secondClause) { - return TrueCondition.getInstance(); - } - return this; + return where(secondClause); } @Override public Condition then(final Runnable response) { - return this; + return FALSE; } @Override From 22c23e7e4ac829a876344f76eaeec1d67efdc7b9 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 22 Apr 2017 07:47:01 +0100 Subject: [PATCH 05/12] ConditionalTest: more tests for whereNot(), andNot() and orNot() --- .../kemitix/conditional/ConditionalTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/test/java/net/kemitix/conditional/ConditionalTest.java b/src/test/java/net/kemitix/conditional/ConditionalTest.java index 4a49fb4..2891fa0 100644 --- a/src/test/java/net/kemitix/conditional/ConditionalTest.java +++ b/src/test/java/net/kemitix/conditional/ConditionalTest.java @@ -124,6 +124,16 @@ public class ConditionalTest { thenTheThenResponseRuns(); } + @Test + public void whereNotTrueThenOtherwiseRuns() { + //when + Condition.whereNot(true) + .then(thenResponse) + .otherwise(otherwiseResponse); + //then + thenTheOtherwiseResponseRuns(); + } + @Test public void whereTrueAndNotFalseThenRuns() { //when @@ -134,6 +144,17 @@ public class ConditionalTest { thenTheThenResponseRuns(); } + @Test + public void whereTrueAndNotTrueThenOtherwiseRuns() { + //when + Condition.where(true) + .andNot(true) + .then(thenResponse) + .otherwise(otherwiseResponse); + //then + thenTheOtherwiseResponseRuns(); + } + @Test public void whereFalseOrNotFalseThenRuns() { //when @@ -144,6 +165,17 @@ public class ConditionalTest { thenTheThenResponseRuns(); } + @Test + public void whereFalseOrNotTrueThenOtherwiseRuns() { + //when + Condition.where(false) + .orNot(true) + .then(thenResponse) + .otherwise(otherwiseResponse); + //then + thenTheOtherwiseResponseRuns(); + } + @Test public void whereFalseElseTrueThenOtherwiseRuns() { //when From 598f69a65b2c08729fb68d595f483ee29cdfbef8 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 23 Apr 2017 16:53:30 +0100 Subject: [PATCH 06/12] Value: add initial implementation --- .../java/net/kemitix/conditional/Value.java | 56 +++++ .../net/kemitix/conditional/ValueTest.java | 228 ++++++++++++++++++ 2 files changed, 284 insertions(+) create mode 100644 src/main/java/net/kemitix/conditional/Value.java create mode 100644 src/test/java/net/kemitix/conditional/ValueTest.java diff --git a/src/main/java/net/kemitix/conditional/Value.java b/src/main/java/net/kemitix/conditional/Value.java new file mode 100644 index 0000000..7c7d201 --- /dev/null +++ b/src/main/java/net/kemitix/conditional/Value.java @@ -0,0 +1,56 @@ +package net.kemitix.conditional; + +import java.util.function.Supplier; + +/** + * @author Paul Campbell (pcampbell@kemitix.net). + */ +public class Value { + + private boolean clause; + + private Supplier trueSupplier; + + private Value(final boolean clause) { + this.clause = clause; + } + + static Value where(final boolean clause) { + return new Value<>(clause); + } + + static Value whereNot(final boolean clause) { + return where(!clause); + } + + Value then(final Supplier trueSupplier) { + this.trueSupplier = trueSupplier; + return this; + } + + T otherwise(final Supplier falseSupplier) { + if (clause) { + return trueSupplier.get(); + } + return falseSupplier.get(); + } + + Value and(final boolean clause) { + this.clause = this.clause && clause; + return this; + } + + Value or(final boolean clause) { + this.clause = this.clause || clause; + return this; + } + + Value andNot(final boolean clause) { + return and(!clause); + } + + Value orNot(final boolean clause) { + return or(!clause); + } + +} diff --git a/src/test/java/net/kemitix/conditional/ValueTest.java b/src/test/java/net/kemitix/conditional/ValueTest.java new file mode 100644 index 0000000..66513a8 --- /dev/null +++ b/src/test/java/net/kemitix/conditional/ValueTest.java @@ -0,0 +1,228 @@ +package net.kemitix.conditional; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Paul Campbell (pcampbell@kemitix.net). + */ +public class ValueTest { + + private static final String TRUE = "true"; + + private static final String FALSE = "false"; + + @Test + public void valueWhereTrueIsTrue() { + //when + final String result = Value.where(true).then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereFalseIsFalse() { + //when + final String result = Value.where(false).then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereTrueAndTrueIsTrue() { + //when + final String result = Value.where(true).and(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereTrueAndFalseIsFalse() { + //when + final String result = Value.where(true).and(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereFalseAndTrueIsFalse() { + //when + final String result = Value.where(false).and(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereFalseAndFalseIsFalse() { + //when + final String result = Value.where(false).and(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereTrueOrTrueIsTrue() { + //when + final String result = Value.where(true).or(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereTrueOrFalseIsTrue() { + //when + final String result = Value.where(true).or(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereFalseOrTrueIsTrue() { + //when + final String result = Value.where(false).or(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereFalseOrFalseIsFalse() { + //when + final String result = Value.where(false).or(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereNotTrueIsFalse() { + //when + final String result = Value.whereNot(true).then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereNotFalseIsTrue() { + //when + final String result = Value.whereNot(false).then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereTrueAndNotTrueIsFalse() { + //when + final String result = Value.where(true).andNot(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereTrueAndNotFalseIsTrue() { + //when + final String result = Value.where(true).andNot(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereFalseAndNotTrueIsFalse() { + //when + final String result = Value.where(false).andNot(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereFalseAndNotFalseIsFalse() { + //when + final String result = Value.where(false).andNot(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereTrueOrNotTrueIsTrue() { + //when + final String result = Value.where(true).orNot(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereTrueOrNotFalseIsTrue() { + //when + final String result = Value.where(true).orNot(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + @Test + public void valueWhereFalseOrNotTrueIsFalse() { + //when + final String result = Value.where(false).orNot(true) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsFalse(result); + } + + @Test + public void valueWhereFalseOrNotFalseIsTrue() { + //when + final String result = Value.where(false).orNot(false) + .then(this::isTrue) + .otherwise(this::isFalse); + //then + thenIsTrue(result); + } + + private String isTrue() { + return TRUE; + } + + private String isFalse() { + return FALSE; + } + + private void thenIsFalse(final String result) { + assertThat(result).isEqualTo(isFalse()); + } + + private void thenIsTrue(final String result) { + assertThat(result).isEqualTo(TRUE); + } + +} From 06c9487eea4ed076a3c1614d518f5dc650646104 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 23 Apr 2017 17:11:37 +0100 Subject: [PATCH 07/12] Value: rewrite using strong chaining logic Return values from each step restrict next chained method(s) available. --- .../java/net/kemitix/conditional/Value.java | 115 +++++++++++++----- 1 file changed, 83 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/kemitix/conditional/Value.java b/src/main/java/net/kemitix/conditional/Value.java index 7c7d201..75d5178 100644 --- a/src/main/java/net/kemitix/conditional/Value.java +++ b/src/main/java/net/kemitix/conditional/Value.java @@ -5,52 +5,103 @@ import java.util.function.Supplier; /** * @author Paul Campbell (pcampbell@kemitix.net). */ -public class Value { +public interface Value { - private boolean clause; - - private Supplier trueSupplier; - - private Value(final boolean clause) { - this.clause = clause; + static ValueClause where(final boolean clause) { + if (clause) { + return new TrueValueClause<>(); + } + return new FalseValueClause<>(); } - static Value where(final boolean clause) { - return new Value<>(clause); - } - - static Value whereNot(final boolean clause) { + static ValueClause whereNot(boolean clause) { return where(!clause); } - Value then(final Supplier trueSupplier) { - this.trueSupplier = trueSupplier; - return this; - } + interface ValueClause { - T otherwise(final Supplier falseSupplier) { - if (clause) { - return trueSupplier.get(); + ValueSupplier then(Supplier trueSupplier); + + ValueClause and(boolean clause); + + ValueClause or(boolean clause); + + default ValueClause andNot(final boolean clause) { + return and(!clause); } - return falseSupplier.get(); + + default ValueClause orNot(boolean clause) { + return or(!clause); + } + + interface ValueSupplier { + + T otherwise(Supplier falseSupplier); + + } + } - Value and(final boolean clause) { - this.clause = this.clause && clause; - return this; + class TrueValueClause implements ValueClause { + + @Override + public ValueSupplier then(final Supplier trueSupplier) { + return new TrueValueSupplier(trueSupplier); + } + + @Override + public ValueClause and(final boolean clause) { + return Value.where(clause); + } + + @Override + public ValueClause or(final boolean clause) { + return this; + } + + private class TrueValueSupplier implements ValueSupplier { + + private final Supplier valueSupplier; + + TrueValueSupplier(final Supplier valueSupplier) { + this.valueSupplier = valueSupplier; + } + + @Override + public T otherwise(final Supplier falseSupplier) { + return valueSupplier.get(); + } + + } + } - Value or(final boolean clause) { - this.clause = this.clause || clause; - return this; - } + class FalseValueClause implements ValueClause { - Value andNot(final boolean clause) { - return and(!clause); - } + @Override + public ValueSupplier then(final Supplier trueSupplier) { + return new FalseValueSupplier(); + } + + @Override + public ValueClause and(final boolean clause) { + return this; + } + + @Override + public ValueClause or(final boolean clause) { + return Value.where(clause); + } + + private class FalseValueSupplier implements ValueSupplier { + + @Override + public T otherwise(final Supplier falseSupplier) { + return falseSupplier.get(); + } + + } - Value orNot(final boolean clause) { - return or(!clause); } } From 6a5ac40f4733e9da5b3261e2a216cc267815a1d1 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 23 Apr 2017 17:14:46 +0100 Subject: [PATCH 08/12] ValueTest: remove ambiguity on then() and otherwise() parameters Both are Supplier. --- .../net/kemitix/conditional/ValueTest.java | 90 +++++++++---------- 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/src/test/java/net/kemitix/conditional/ValueTest.java b/src/test/java/net/kemitix/conditional/ValueTest.java index 66513a8..6971115 100644 --- a/src/test/java/net/kemitix/conditional/ValueTest.java +++ b/src/test/java/net/kemitix/conditional/ValueTest.java @@ -16,8 +16,8 @@ public class ValueTest { @Test public void valueWhereTrueIsTrue() { //when - final String result = Value.where(true).then(this::isTrue) - .otherwise(this::isFalse); + final String result = Value.where(true).then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -25,8 +25,8 @@ public class ValueTest { @Test public void valueWhereFalseIsFalse() { //when - final String result = Value.where(false).then(this::isTrue) - .otherwise(this::isFalse); + final String result = Value.where(false).then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -35,8 +35,8 @@ public class ValueTest { public void valueWhereTrueAndTrueIsTrue() { //when final String result = Value.where(true).and(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -45,8 +45,8 @@ public class ValueTest { public void valueWhereTrueAndFalseIsFalse() { //when final String result = Value.where(true).and(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -55,8 +55,8 @@ public class ValueTest { public void valueWhereFalseAndTrueIsFalse() { //when final String result = Value.where(false).and(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -65,8 +65,8 @@ public class ValueTest { public void valueWhereFalseAndFalseIsFalse() { //when final String result = Value.where(false).and(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -75,8 +75,8 @@ public class ValueTest { public void valueWhereTrueOrTrueIsTrue() { //when final String result = Value.where(true).or(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -85,8 +85,8 @@ public class ValueTest { public void valueWhereTrueOrFalseIsTrue() { //when final String result = Value.where(true).or(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -95,8 +95,8 @@ public class ValueTest { public void valueWhereFalseOrTrueIsTrue() { //when final String result = Value.where(false).or(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -105,8 +105,8 @@ public class ValueTest { public void valueWhereFalseOrFalseIsFalse() { //when final String result = Value.where(false).or(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -114,8 +114,8 @@ public class ValueTest { @Test public void valueWhereNotTrueIsFalse() { //when - final String result = Value.whereNot(true).then(this::isTrue) - .otherwise(this::isFalse); + final String result = Value.whereNot(true).then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -123,8 +123,8 @@ public class ValueTest { @Test public void valueWhereNotFalseIsTrue() { //when - final String result = Value.whereNot(false).then(this::isTrue) - .otherwise(this::isFalse); + final String result = Value.whereNot(false).then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -133,8 +133,8 @@ public class ValueTest { public void valueWhereTrueAndNotTrueIsFalse() { //when final String result = Value.where(true).andNot(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -143,8 +143,8 @@ public class ValueTest { public void valueWhereTrueAndNotFalseIsTrue() { //when final String result = Value.where(true).andNot(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -153,8 +153,8 @@ public class ValueTest { public void valueWhereFalseAndNotTrueIsFalse() { //when final String result = Value.where(false).andNot(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -163,8 +163,8 @@ public class ValueTest { public void valueWhereFalseAndNotFalseIsFalse() { //when final String result = Value.where(false).andNot(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -173,8 +173,8 @@ public class ValueTest { public void valueWhereTrueOrNotTrueIsTrue() { //when final String result = Value.where(true).orNot(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -183,8 +183,8 @@ public class ValueTest { public void valueWhereTrueOrNotFalseIsTrue() { //when final String result = Value.where(true).orNot(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } @@ -193,8 +193,8 @@ public class ValueTest { public void valueWhereFalseOrNotTrueIsFalse() { //when final String result = Value.where(false).orNot(true) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsFalse(result); } @@ -203,22 +203,14 @@ public class ValueTest { public void valueWhereFalseOrNotFalseIsTrue() { //when final String result = Value.where(false).orNot(false) - .then(this::isTrue) - .otherwise(this::isFalse); + .then(() -> TRUE) + .otherwise(() -> FALSE); //then thenIsTrue(result); } - private String isTrue() { - return TRUE; - } - - private String isFalse() { - return FALSE; - } - private void thenIsFalse(final String result) { - assertThat(result).isEqualTo(isFalse()); + assertThat(result).isEqualTo(FALSE); } private void thenIsTrue(final String result) { From ce42e9dcbe67d7b450f123b79667ce204df798eb Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 23 Apr 2017 17:52:15 +0100 Subject: [PATCH 09/12] Value: add javadoc --- .../java/net/kemitix/conditional/Value.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/src/main/java/net/kemitix/conditional/Value.java b/src/main/java/net/kemitix/conditional/Value.java index 75d5178..2f49daf 100644 --- a/src/main/java/net/kemitix/conditional/Value.java +++ b/src/main/java/net/kemitix/conditional/Value.java @@ -1,12 +1,45 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + package net.kemitix.conditional; import java.util.function.Supplier; /** + * A Value from an if-then-else in a functional-style. + * + * @param the type of the value + * * @author Paul Campbell (pcampbell@kemitix.net). */ public interface Value { + /** + * Create a new {@link ValueClause} for the clause. + * + * @param clause the condition to test + * @param the type of the value + * + * @return a true or false value clause + */ static ValueClause where(final boolean clause) { if (clause) { return new TrueValueClause<>(); @@ -14,34 +47,99 @@ public interface Value { return new FalseValueClause<>(); } + /** + * Create a new {@link ValueClause} for the boolean opposite of the clause. + * + * @param clause the condition to test + * @param the type of the value + * + * @return a true or false value clause + */ static ValueClause whereNot(boolean clause) { return where(!clause); } + /** + * An intermediate state in determining the final {@link Value}. + * + * @param the type of the value + */ interface ValueClause { + /** + * Create a {@link ValueSupplier} with the {@link Supplier} should the {@link ValueClause} be true. + * + * @param trueSupplier the Supplier for the true value + * + * @return the value supplier + */ ValueSupplier then(Supplier trueSupplier); + /** + * Logically AND combine the current {@link ValueClause} with clause. + * + * @param clause the condition to test + * + * @return a true or false value clause + */ ValueClause and(boolean clause); + /** + * Logically OR combine the current {@link ValueClause} with clause. + * + * @param clause the condition to test + * + * @return a true or false value clause + */ ValueClause or(boolean clause); + /** + * Logically AND combine the current {@link ValueClause} with boolean opposite of the clause. + * + * @param clause the condition to test + * + * @return a true or false value clause + */ default ValueClause andNot(final boolean clause) { return and(!clause); } + /** + * Logically OR combine the current {@link ValueClause} with boolean opposite of the clause. + * + * @param clause the condition to test + * + * @return a true or false value clause + */ default ValueClause orNot(boolean clause) { return or(!clause); } + /** + * An intermediate result of the {@link Value}. + * + * @param the type of the value + */ interface ValueSupplier { + /** + * Determine the value by whether the {@link ValueClause} was true or false. + * + * @param falseSupplier the Supplier for the false value + * + * @return the value + */ T otherwise(Supplier falseSupplier); } } + /** + * An intermediate state where the clause has evaluated to true. + * + * @param the type of the value + */ class TrueValueClause implements ValueClause { @Override @@ -59,6 +157,11 @@ public interface Value { return this; } + /** + * An intermediate result of the {@link Value} where the clause has evaluated to true. + * + * @param the type of the value + */ private class TrueValueSupplier implements ValueSupplier { private final Supplier valueSupplier; @@ -76,6 +179,11 @@ public interface Value { } + /** + * An intermediate state where the clause has evaluated to false. + * + * @param the type of the value + */ class FalseValueClause implements ValueClause { @Override @@ -93,6 +201,11 @@ public interface Value { return Value.where(clause); } + /** + * An intermediate result of the {@link Value} where the clause has evaluated to false. + * + * @param the type of the value + */ private class FalseValueSupplier implements ValueSupplier { @Override From 47d0b8f78da1c82af22e1636db4f3a09501ff6ca Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 23 Apr 2017 17:55:08 +0100 Subject: [PATCH 10/12] Value: clean up unneeded generics type parameters --- .../java/net/kemitix/conditional/Value.java | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/kemitix/conditional/Value.java b/src/main/java/net/kemitix/conditional/Value.java index 2f49daf..35618df 100644 --- a/src/main/java/net/kemitix/conditional/Value.java +++ b/src/main/java/net/kemitix/conditional/Value.java @@ -26,11 +26,9 @@ import java.util.function.Supplier; /** * A Value from an if-then-else in a functional-style. * - * @param the type of the value - * * @author Paul Campbell (pcampbell@kemitix.net). */ -public interface Value { +public interface Value { /** * Create a new {@link ValueClause} for the clause. @@ -144,12 +142,12 @@ public interface Value { @Override public ValueSupplier then(final Supplier trueSupplier) { - return new TrueValueSupplier(trueSupplier); + return new TrueValueSupplier(trueSupplier); } @Override public ValueClause and(final boolean clause) { - return Value.where(clause); + return Value.where(clause); } @Override @@ -159,10 +157,8 @@ public interface Value { /** * An intermediate result of the {@link Value} where the clause has evaluated to true. - * - * @param the type of the value */ - private class TrueValueSupplier implements ValueSupplier { + private class TrueValueSupplier implements ValueSupplier { private final Supplier valueSupplier; @@ -188,7 +184,7 @@ public interface Value { @Override public ValueSupplier then(final Supplier trueSupplier) { - return new FalseValueSupplier(); + return new FalseValueSupplier(); } @Override @@ -198,15 +194,13 @@ public interface Value { @Override public ValueClause or(final boolean clause) { - return Value.where(clause); + return Value.where(clause); } /** * An intermediate result of the {@link Value} where the clause has evaluated to false. - * - * @param the type of the value */ - private class FalseValueSupplier implements ValueSupplier { + private class FalseValueSupplier implements ValueSupplier { @Override public T otherwise(final Supplier falseSupplier) { From 5dcd67b8625833f0776616fd1049460b4fdf5d21 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 23 Apr 2017 21:37:22 +0100 Subject: [PATCH 11/12] README.adoc: add documentation for Value Also add badges for build status and code coverage. --- README.adoc | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 5cc2b63..895bb64 100644 --- a/README.adoc +++ b/README.adoc @@ -1,8 +1,15 @@ # Conditional -If-then-else in a functional-style. +image:https://travis-ci.org/kemitix/conditional.svg?branch=master["Build Status", link="https://travis-ci.org/kemitix/conditional"] -## Usage +image::https://coveralls.io/repos/github/kemitix/conditional/badge.svg?branch=master["Coverage Status", link="https://coveralls.io/github/kemitix/conditional?branch=master"] + +* link:#_condition[Condition] +* link:#_value[Value] + +## Condition + +If-then-else in a functional-style. ### if-then @@ -169,3 +176,126 @@ Condition.where(isTrue()) .and(isAlsoTrue()) .then(() -> doSomethingElse()); ---- + +## Value + +Values from an if-then-else in a functional-style. + +Functional, and verbose, alternative to the ternary operator (`?:`). + +### if-then-else + +[[source,java]] +---- +String result; +if (isTrue()) { + result = TRUE; +} else { + result = FALSE; +} +---- + +[[source,java]] +---- +String result = isTrue() ? TRUE : FALSE; +---- + +[[source,java]] +---- +final String result = Value.where(isTrue()).then(() -> TRUE) + .otherwise(() -> FALSE); +---- + +### if-not-then-else + +[[source,java]] +---- +String result; +if (!isTrue()) { + result = TRUE; +} else { + result = FALSE; +} +---- + +[[source,java]] +---- +final String result = Value.whereNot(isTrue()).then(() -> TRUE) + .otherwise(() -> FALSE); +---- + +### if-and-then-else + +[[source,java]] +---- +String result; +if (isTrue() && alternativeIsTrue()) { + result = TRUE; +} else { + result = FALSE; +} +---- + +[[source,java]] +---- +final String result = Value.where(isTrue()).and(alternativeIsTrue()) + .then(() -> TRUE) + .otherwise(() -> FALSE); +---- + +### if-and-not-then-else + +[[source,java]] +---- +String result; +if (isTrue() && !alternativeIsFalse()) { + result = TRUE; +} else { + result = FALSE; +} +---- + +[[source,java]] +---- +final String result = Value.where(isTrue()).andNot(alternativeIsFalse()) + .then(() -> TRUE) + .otherwise(() -> FALSE); +---- + +### if-or-then-else + +[[source,java]] +---- +String result; +if (isTrue() || alternativeIsTrue()) { + result = TRUE; +} else { + result = FALSE; +} +---- + +[[source,java]] +---- +final String result = Value.where(isTrue()).or(alternativeIsTrue()) + .then(() -> TRUE) + .otherwise(() -> FALSE); +---- + +### if-or-not-then-else + +[[source,java]] +---- +String result; +if (isTrue() || !isFalse()) { + result = TRUE; +} else { + result = FALSE; +} +---- + +[[source,java]] +---- +final String result = Value.where(isTrue()).orNot(isFalse()) + .then(() -> TRUE) + .otherwise(() -> FALSE); +---- From 75c63562d8f3df8893ef27566a40b98843a98ede Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 23 Apr 2017 21:44:55 +0100 Subject: [PATCH 12/12] pom.xml: version set to 0.2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 55ed31f..c2e1b13 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ conditional - 0.2.0-SNAPSHOT + 0.2.0