From 0caa2c7d6f1f48fa376c9b2cdd7ab4a8b28d9dc0 Mon Sep 17 00:00:00 2001 From: Devin Smith Date: Mon, 11 Sep 2023 11:50:32 -0700 Subject: [PATCH] Improve generic types for TypedFunctions (#4463) --- extensions/protobuf/build.gradle | 2 + .../deephaven/functions/BooleanFunctions.java | 134 +++++++++++--- .../io/deephaven/functions/ByteFunctions.java | 16 +- .../io/deephaven/functions/CharFunctions.java | 16 +- .../deephaven/functions/DoubleFunctions.java | 22 ++- .../deephaven/functions/FloatFunctions.java | 16 +- .../io/deephaven/functions/IntFunctions.java | 22 ++- .../io/deephaven/functions/LongFunctions.java | 22 ++- .../deephaven/functions/ObjectFunctions.java | 168 ++++++------------ .../functions/PrimitiveFunctions.java | 72 ++++++++ .../deephaven/functions/ShortFunctions.java | 16 +- .../functions/ToBooleanFunction.java | 32 +++- .../deephaven/functions/ToByteFunction.java | 4 +- .../deephaven/functions/ToCharFunction.java | 4 +- .../deephaven/functions/ToDoubleFunction.java | 4 +- .../deephaven/functions/ToFloatFunction.java | 4 +- .../io/deephaven/functions/ToIntFunction.java | 4 +- .../deephaven/functions/ToLongFunction.java | 4 +- .../deephaven/functions/ToObjectFunction.java | 71 +++++--- .../deephaven/functions/ToShortFunction.java | 4 +- .../deephaven/functions/TypedFunctions.java | 40 +++++ .../functions/ToBooleanFunctionTest.java | 129 +++++++++++--- 22 files changed, 569 insertions(+), 237 deletions(-) create mode 100644 extensions/protobuf/src/main/java/io/deephaven/functions/PrimitiveFunctions.java create mode 100644 extensions/protobuf/src/main/java/io/deephaven/functions/TypedFunctions.java diff --git a/extensions/protobuf/build.gradle b/extensions/protobuf/build.gradle index 7c4dcd6eedd..5216aea91e2 100644 --- a/extensions/protobuf/build.gradle +++ b/extensions/protobuf/build.gradle @@ -11,6 +11,8 @@ dependencies { Classpaths.inheritImmutables(project) + compileOnly depAnnotations + Classpaths.inheritJUnitPlatform(project) Classpaths.inheritAssertJ(project) diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/BooleanFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/BooleanFunctions.java index 1a9e581cb01..f64cd61a474 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/BooleanFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/BooleanFunctions.java @@ -3,21 +3,31 @@ */ package io.deephaven.functions; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; class BooleanFunctions { static ToBooleanFunction cast() { + return cast(PrimitiveBoolean.INSTANCE); + } + + static ToBooleanFunction cast(ToBooleanFunction f) { // noinspection unchecked - return (ToBooleanFunction) PrimitiveBoolean.INSTANCE; + return (ToBooleanFunction) f; } - static ToBooleanFunction of(Predicate predicate) { - return predicate instanceof ToBooleanFunction ? (ToBooleanFunction) predicate : predicate::test; + static ToBooleanFunction of(Predicate predicate) { + return predicate instanceof ToBooleanFunction + ? cast((ToBooleanFunction) predicate) + : predicate::test; } public static ToBooleanFunction ofTrue() { @@ -30,15 +40,19 @@ public static ToBooleanFunction ofFalse() { return (ToBooleanFunction) OfFalse.INSTANCE; } - static ToBooleanFunction map(Function f, Predicate g) { + static ToBooleanFunction map( + Function f, + Predicate g) { return new BooleanMap<>(f, g); } - static ToBooleanFunction not(ToBooleanFunction f) { - return f instanceof BooleanNot ? of(((BooleanNot) f).function()) : new BooleanNot<>(f); + static ToBooleanFunction not(Predicate f) { + return f instanceof BooleanNot + ? cast(((BooleanNot) f).negate()) + : new BooleanNot<>(f); } - static ToBooleanFunction or(Collection> functions) { + static ToBooleanFunction or(Collection> functions) { if (functions.isEmpty()) { return ofFalse(); } @@ -48,7 +62,7 @@ static ToBooleanFunction or(Collection> functions) { return new BooleanOr<>(functions); } - static ToBooleanFunction and(Collection> functions) { + static ToBooleanFunction and(Collection> functions) { if (functions.isEmpty()) { return ofTrue(); } @@ -65,6 +79,26 @@ private enum OfTrue implements ToBooleanFunction { public boolean test(Object value) { return true; } + + @Override + @NotNull + public ToBooleanFunction negate() { + return ofFalse(); + } + + @Override + @NotNull + public ToBooleanFunction and(@NotNull Predicate other) { + // always other + return of(other); + } + + @Override + @NotNull + public ToBooleanFunction or(@NotNull Predicate other) { + // always true + return this; + } } private enum OfFalse implements ToBooleanFunction { @@ -74,6 +108,26 @@ private enum OfFalse implements ToBooleanFunction { public boolean test(Object value) { return false; } + + @Override + @NotNull + public ToBooleanFunction negate() { + return ofTrue(); + } + + @Override + @NotNull + public ToBooleanFunction and(@NotNull Predicate other) { + // always false + return this; + } + + @Override + @NotNull + public ToBooleanFunction or(@NotNull Predicate other) { + // always other + return of(other); + } } private enum PrimitiveBoolean implements ToBooleanFunction { @@ -86,10 +140,10 @@ public boolean test(Object value) { } private static class BooleanMap implements ToBooleanFunction { - private final Function f; - private final Predicate g; + private final Function f; + private final Predicate g; - public BooleanMap(Function f, Predicate g) { + public BooleanMap(Function f, Predicate g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } @@ -98,58 +152,92 @@ public BooleanMap(Function f, Predicate g) { public boolean test(T value) { return g.test(f.apply(value)); } + + @Override + @NotNull + public ToBooleanFunction negate() { + return new BooleanMap<>(f, g.negate()); + } } private static class BooleanNot implements ToBooleanFunction { - private final Predicate function; + private final Predicate function; - public BooleanNot(ToBooleanFunction function) { + public BooleanNot(Predicate function) { this.function = Objects.requireNonNull(function); } - public Predicate function() { - return function; - } - @Override public boolean test(T value) { return !function.test(value); } + + @Override + @NotNull + public ToBooleanFunction negate() { + return of(function); + } } private static class BooleanAnd implements ToBooleanFunction { - private final Collection> functions; + private final Collection> functions; - public BooleanAnd(Collection> functions) { + public BooleanAnd(Collection> functions) { this.functions = List.copyOf(functions); } @Override public boolean test(T value) { - for (Predicate function : functions) { + for (Predicate function : functions) { if (!function.test(value)) { return false; } } return true; } + + @Override + @NotNull + public ToBooleanFunction negate() { + return new BooleanOr<>(functions.stream().map(Predicate::negate).collect(Collectors.toList())); + } + + @Override + @NotNull + public ToBooleanFunction and(@NotNull Predicate other) { + // noinspection Convert2Diamond + return new BooleanAnd(Stream.concat(functions.stream(), Stream.of(other)).collect(Collectors.toList())); + } } private static class BooleanOr implements ToBooleanFunction { - private final Collection> functions; + private final Collection> functions; - public BooleanOr(Collection> functions) { + public BooleanOr(Collection> functions) { this.functions = List.copyOf(functions); } @Override public boolean test(T value) { - for (Predicate function : functions) { + for (Predicate function : functions) { if (function.test(value)) { return true; } } return false; } + + @Override + @NotNull + public ToBooleanFunction negate() { + return new BooleanAnd<>(functions.stream().map(Predicate::negate).collect(Collectors.toList())); + } + + @Override + @NotNull + public ToBooleanFunction or(@NotNull Predicate other) { + // noinspection Convert2Diamond + return new BooleanOr(Stream.concat(functions.stream(), Stream.of(other)).collect(Collectors.toList())); + } } } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ByteFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ByteFunctions.java index b1b3cdf3e6b..d44cef49b45 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ByteFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ByteFunctions.java @@ -8,11 +8,17 @@ class ByteFunctions { static ToByteFunction cast() { + return cast(PrimitiveByte.INSTANCE); + } + + static ToByteFunction cast(ToByteFunction f) { // noinspection unchecked - return (ToByteFunction) PrimitiveByte.INSTANCE; + return (ToByteFunction) f; } - static ToByteFunction map(Function f, ToByteFunction g) { + static ToByteFunction map( + Function f, + ToByteFunction g) { return new ByteMap<>(f, g); } @@ -26,10 +32,10 @@ public byte applyAsByte(Object value) { } private static class ByteMap implements ToByteFunction { - private final Function f; - private final ToByteFunction g; + private final Function f; + private final ToByteFunction g; - public ByteMap(Function f, ToByteFunction g) { + public ByteMap(Function f, ToByteFunction g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/CharFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/CharFunctions.java index 4921bbb7f6d..428465ff8e8 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/CharFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/CharFunctions.java @@ -8,11 +8,17 @@ class CharFunctions { static ToCharFunction cast() { + return cast(PrimitiveChar.INSTANCE); + } + + static ToCharFunction cast(ToCharFunction f) { // noinspection unchecked - return (ToCharFunction) PrimitiveChar.INSTANCE; + return (ToCharFunction) f; } - static ToCharFunction map(Function f, ToCharFunction g) { + static ToCharFunction map( + Function f, + ToCharFunction g) { return new CharMap<>(f, g); } @@ -26,10 +32,10 @@ public char applyAsChar(Object value) { } private static class CharMap implements ToCharFunction { - private final Function f; - private final ToCharFunction g; + private final Function f; + private final ToCharFunction g; - public CharMap(Function f, ToCharFunction g) { + public CharMap(Function f, ToCharFunction g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/DoubleFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/DoubleFunctions.java index bbe3ff205ed..f1fab905a14 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/DoubleFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/DoubleFunctions.java @@ -9,15 +9,23 @@ class DoubleFunctions { static ToDoubleFunction cast() { + return cast(PrimitiveDouble.INSTANCE); + } + + static ToDoubleFunction cast(ToDoubleFunction f) { // noinspection unchecked - return (ToDoubleFunction) PrimitiveDouble.INSTANCE; + return (ToDoubleFunction) f; } - static ToDoubleFunction of(java.util.function.ToDoubleFunction f) { - return f instanceof ToDoubleFunction ? (ToDoubleFunction) f : f::applyAsDouble; + static ToDoubleFunction of(java.util.function.ToDoubleFunction f) { + return f instanceof ToDoubleFunction + ? cast((ToDoubleFunction) f) + : f::applyAsDouble; } - static ToDoubleFunction map(Function f, java.util.function.ToDoubleFunction g) { + static ToDoubleFunction map( + Function f, + java.util.function.ToDoubleFunction g) { return new DoubleFunctionMap<>(f, g); } @@ -31,10 +39,10 @@ public double applyAsDouble(Object value) { } private static class DoubleFunctionMap implements ToDoubleFunction { - private final Function f; - private final java.util.function.ToDoubleFunction g; + private final Function f; + private final java.util.function.ToDoubleFunction g; - public DoubleFunctionMap(Function f, java.util.function.ToDoubleFunction g) { + public DoubleFunctionMap(Function f, java.util.function.ToDoubleFunction g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/FloatFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/FloatFunctions.java index f3f6f9303a6..5e8c6d35f03 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/FloatFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/FloatFunctions.java @@ -8,11 +8,17 @@ class FloatFunctions { static ToFloatFunction cast() { + return cast(PrimitiveFloat.INSTANCE); + } + + static ToFloatFunction cast(ToFloatFunction f) { // noinspection unchecked - return (ToFloatFunction) PrimitiveFloat.INSTANCE; + return (ToFloatFunction) f; } - static ToFloatFunction map(Function f, ToFloatFunction g) { + static ToFloatFunction map( + Function f, + ToFloatFunction g) { return new FloatMap<>(f, g); } @@ -26,10 +32,10 @@ public float applyAsFloat(Object value) { } private static class FloatMap implements ToFloatFunction { - private final Function f; - private final ToFloatFunction g; + private final Function f; + private final ToFloatFunction g; - public FloatMap(Function f, ToFloatFunction g) { + public FloatMap(Function f, ToFloatFunction g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/IntFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/IntFunctions.java index e97673a937e..f707d16f654 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/IntFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/IntFunctions.java @@ -8,15 +8,23 @@ class IntFunctions { static ToIntFunction cast() { + return cast(PrimitiveInt.INSTANCE); + } + + static ToIntFunction cast(ToIntFunction f) { // noinspection unchecked - return (ToIntFunction) PrimitiveInt.INSTANCE; + return (ToIntFunction) f; } - static ToIntFunction of(java.util.function.ToIntFunction f) { - return f instanceof ToIntFunction ? (ToIntFunction) f : f::applyAsInt; + static ToIntFunction of(java.util.function.ToIntFunction f) { + return f instanceof ToIntFunction + ? cast((ToIntFunction) f) + : f::applyAsInt; } - static ToIntFunction map(Function f, java.util.function.ToIntFunction g) { + static ToIntFunction map( + Function f, + java.util.function.ToIntFunction g) { return new IntMap<>(f, g); } @@ -30,10 +38,10 @@ public int applyAsInt(Object value) { } private static class IntMap implements ToIntFunction { - private final Function f; - private final java.util.function.ToIntFunction g; + private final Function f; + private final java.util.function.ToIntFunction g; - public IntMap(Function f, java.util.function.ToIntFunction g) { + public IntMap(Function f, java.util.function.ToIntFunction g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/LongFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/LongFunctions.java index 20b135f8b88..30ba0608f65 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/LongFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/LongFunctions.java @@ -9,15 +9,23 @@ class LongFunctions { static ToLongFunction cast() { + return cast(PrimitiveLong.INSTANCE); + } + + static ToLongFunction cast(ToLongFunction f) { // noinspection unchecked - return (ToLongFunction) PrimitiveLong.INSTANCE; + return (ToLongFunction) f; } - static ToLongFunction of(java.util.function.ToLongFunction f) { - return f instanceof ToLongFunction ? (ToLongFunction) f : f::applyAsLong; + static ToLongFunction of(java.util.function.ToLongFunction f) { + return f instanceof ToLongFunction + ? cast((ToLongFunction) f) + : f::applyAsLong; } - static ToLongFunction map(Function f, java.util.function.ToLongFunction g) { + static ToLongFunction map( + Function f, + java.util.function.ToLongFunction g) { return new LongMap<>(f, g); } @@ -31,10 +39,10 @@ public long applyAsLong(Object value) { } private static class LongMap implements ToLongFunction { - private final Function f; - private final java.util.function.ToLongFunction g; + private final Function f; + private final java.util.function.ToLongFunction g; - public LongMap(Function f, java.util.function.ToLongFunction g) { + public LongMap(Function f, java.util.function.ToLongFunction g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ObjectFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ObjectFunctions.java index bab369e5552..951441a0e09 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ObjectFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ObjectFunctions.java @@ -14,32 +14,46 @@ class ObjectFunctions { static ToObjectFunction identity() { + return cast(Identity.INSTANCE); + } + + static ToObjectFunction cast(ToObjectFunction f) { // noinspection unchecked - return (ToObjectFunction) Identity.INSTANCE; + return (ToObjectFunction) f; } static ToObjectFunction cast(GenericType type) { return new Casted<>(type); } - static ToObjectFunction of(Function f, GenericType returnType) { - return new FunctionImpl<>(f, returnType); + static ToObjectFunction of( + Function f, + GenericType returnType) { + return f instanceof ToObjectFunction + ? castOrMapCast((ToObjectFunction) f, returnType) + : new FunctionImpl<>(f, returnType); } - static ToObjectFunction map(Function f, ToObjectFunction g) { - return new ObjectMap<>(f, g, g.returnType()); - } - - static ToObjectFunction map(Function f, Function g, GenericType returnType) { - return new ObjectMap<>(f, g, returnType); + static ToObjectFunction castOrMapCast( + ToObjectFunction f, + GenericType returnType) { + // noinspection unchecked + return f.returnType().equals(returnType) + ? (ToObjectFunction) f + : f.mapToObj(ObjectFunctions.cast(returnType)); } - static ToPrimitiveFunction mapPrimitive(ToObjectFunction f, ToPrimitiveFunction g) { - return MapPrimitiveVisitor.of(f, g); + static ToObjectFunction map( + Function f, + ToObjectFunction g) { + return new ObjectMap<>(f, g, g.returnType()); } - static TypedFunction map(ToObjectFunction f, TypedFunction g) { - return MapVisitor.of(f, g); + static ToObjectFunction map( + Function f, + Function g, + GenericType returnType) { + return new ObjectMap<>(f, g, returnType); } private enum Identity implements ToObjectFunction { @@ -58,63 +72,65 @@ public Object apply(Object value) { } @Override - public ToBooleanFunction mapToBoolean(Predicate g) { + public ToBooleanFunction mapToBoolean(Predicate g) { return BooleanFunctions.of(g); } + @Override - public ToCharFunction mapToChar(ToCharFunction g) { - return g; + public ToCharFunction mapToChar(ToCharFunction g) { + return CharFunctions.cast(g); } @Override - public ToByteFunction mapToByte(ToByteFunction g) { - return g; + public ToByteFunction mapToByte(ToByteFunction g) { + return ByteFunctions.cast(g); } @Override - public ToShortFunction mapToShort(ToShortFunction g) { - return g; + public ToShortFunction mapToShort(ToShortFunction g) { + return ShortFunctions.cast(g); } @Override - public ToIntFunction mapToInt(java.util.function.ToIntFunction g) { + public ToIntFunction mapToInt(java.util.function.ToIntFunction g) { return IntFunctions.of(g); } @Override - public ToLongFunction mapToLong(java.util.function.ToLongFunction g) { + public ToLongFunction mapToLong(java.util.function.ToLongFunction g) { return LongFunctions.of(g); } @Override - public ToFloatFunction mapToFloat(ToFloatFunction g) { - return g; + public ToFloatFunction mapToFloat(ToFloatFunction g) { + return FloatFunctions.cast(g); } @Override - public ToDoubleFunction mapToDouble(java.util.function.ToDoubleFunction g) { + public ToDoubleFunction mapToDouble(java.util.function.ToDoubleFunction g) { return DoubleFunctions.of(g); } @Override - public ToObjectFunction mapToObj(ToObjectFunction g) { - return g; + public ToObjectFunction mapToObj(ToObjectFunction g) { + return ObjectFunctions.cast(g); } @Override - public ToObjectFunction mapToObj(Function g, GenericType returnType) { - return ToObjectFunction.of(g, returnType); + public ToObjectFunction mapToObj(Function g, + GenericType returnType) { + return ObjectFunctions.of(g, returnType); } @Override - public ToPrimitiveFunction mapToPrimitive(ToPrimitiveFunction g) { - return g; + public ToPrimitiveFunction mapToPrimitive(ToPrimitiveFunction g) { + return PrimitiveFunctions.cast(g); } @Override - public TypedFunction map(TypedFunction g) { - return g; + public TypedFunction map(TypedFunction g) { + return TypedFunctions.cast(g); } } @@ -137,10 +153,10 @@ public R apply(T value) { } private static final class FunctionImpl implements ToObjectFunction { - private final Function f; + private final Function f; private final GenericType returnType; - FunctionImpl(Function f, GenericType returnType) { + FunctionImpl(Function f, GenericType returnType) { this.f = Objects.requireNonNull(f); this.returnType = Objects.requireNonNull(returnType); } @@ -157,11 +173,12 @@ public R apply(T value) { } private static class ObjectMap implements ToObjectFunction { - private final Function f; - private final Function g; + private final Function f; + private final Function g; private final GenericType returnType; - public ObjectMap(Function f, Function g, GenericType returnType) { + public ObjectMap(Function f, Function g, + GenericType returnType) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); this.returnType = Objects.requireNonNull(returnType); @@ -178,79 +195,4 @@ public Z apply(T value) { } } - private static class MapPrimitiveVisitor implements ToPrimitiveFunction.Visitor> { - - public static ToPrimitiveFunction of(ToObjectFunction f, ToPrimitiveFunction g) { - return g.walk(new MapPrimitiveVisitor<>(f)); - } - - private final ToObjectFunction f; - - private MapPrimitiveVisitor(ToObjectFunction f) { - this.f = Objects.requireNonNull(f); - } - - @Override - public ToBooleanFunction visit(ToBooleanFunction g) { - return f.mapToBoolean(g); - } - - @Override - public ToCharFunction visit(ToCharFunction g) { - return f.mapToChar(g); - } - - @Override - public ToByteFunction visit(ToByteFunction g) { - return f.mapToByte(g); - } - - @Override - public ToShortFunction visit(ToShortFunction g) { - return f.mapToShort(g); - } - - @Override - public ToIntFunction visit(ToIntFunction g) { - return f.mapToInt(g); - } - - @Override - public ToLongFunction visit(ToLongFunction g) { - return f.mapToLong(g); - } - - @Override - public ToFloatFunction visit(ToFloatFunction g) { - return f.mapToFloat(g); - } - - @Override - public ToDoubleFunction visit(ToDoubleFunction g) { - return f.mapToDouble(g); - } - } - - private static class MapVisitor implements TypedFunction.Visitor> { - - public static TypedFunction of(ToObjectFunction f, TypedFunction g) { - return g.walk(new MapVisitor<>(f)); - } - - private final ToObjectFunction f; - - private MapVisitor(ToObjectFunction f) { - this.f = Objects.requireNonNull(f); - } - - @Override - public ToPrimitiveFunction visit(ToPrimitiveFunction g) { - return f.mapToPrimitive(g); - } - - @Override - public ToObjectFunction visit(ToObjectFunction g) { - return f.mapToObj(g); - } - } } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/PrimitiveFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/PrimitiveFunctions.java new file mode 100644 index 00000000000..c4ba0015685 --- /dev/null +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/PrimitiveFunctions.java @@ -0,0 +1,72 @@ +package io.deephaven.functions; + +import java.util.Objects; + +class PrimitiveFunctions { + static ToPrimitiveFunction cast(ToPrimitiveFunction f) { + // noinspection unchecked + return (ToPrimitiveFunction) f; + } + + static ToPrimitiveFunction map( + ToObjectFunction f, + ToPrimitiveFunction g) { + return MapPrimitiveVisitor.of(f, g); + } + + private static class MapPrimitiveVisitor + implements ToPrimitiveFunction.Visitor> { + + public static ToPrimitiveFunction of( + ToObjectFunction f, + ToPrimitiveFunction g) { + return g.walk(new MapPrimitiveVisitor<>(f)); + } + + private final ToObjectFunction f; + + private MapPrimitiveVisitor(ToObjectFunction f) { + this.f = Objects.requireNonNull(f); + } + + @Override + public ToBooleanFunction visit(ToBooleanFunction g) { + return f.mapToBoolean(g); + } + + @Override + public ToCharFunction visit(ToCharFunction g) { + return f.mapToChar(g); + } + + @Override + public ToByteFunction visit(ToByteFunction g) { + return f.mapToByte(g); + } + + @Override + public ToShortFunction visit(ToShortFunction g) { + return f.mapToShort(g); + } + + @Override + public ToIntFunction visit(ToIntFunction g) { + return f.mapToInt(g); + } + + @Override + public ToLongFunction visit(ToLongFunction g) { + return f.mapToLong(g); + } + + @Override + public ToFloatFunction visit(ToFloatFunction g) { + return f.mapToFloat(g); + } + + @Override + public ToDoubleFunction visit(ToDoubleFunction g) { + return f.mapToDouble(g); + } + } +} diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ShortFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ShortFunctions.java index 32f37824cc1..efe8543f915 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ShortFunctions.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ShortFunctions.java @@ -9,11 +9,17 @@ class ShortFunctions { static ToShortFunction cast() { + return cast(PrimitiveShort.INSTANCE); + } + + static ToShortFunction cast(ToShortFunction f) { // noinspection unchecked - return (ToShortFunction) PrimitiveShort.INSTANCE; + return (ToShortFunction) f; } - static ToShortFunction map(Function f, ToShortFunction g) { + static ToShortFunction map( + Function f, + ToShortFunction g) { return new ShortMap<>(f, g); } @@ -27,10 +33,10 @@ public short applyAsShort(Object value) { } private static class ShortMap implements ToShortFunction { - private final Function f; - private final ToShortFunction g; + private final Function f; + private final ToShortFunction g; - public ShortMap(Function f, ToShortFunction g) { + public ShortMap(Function f, ToShortFunction g) { this.f = Objects.requireNonNull(f); this.g = Objects.requireNonNull(g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToBooleanFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToBooleanFunction.java index bf0f1353b6b..11c727a0398 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToBooleanFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToBooleanFunction.java @@ -5,8 +5,10 @@ import io.deephaven.qst.type.BooleanType; import io.deephaven.qst.type.Type; +import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.List; import java.util.function.Function; import java.util.function.Predicate; @@ -60,7 +62,9 @@ static ToBooleanFunction ofFalse() { * @param the input type * @param the intermediate type */ - static ToBooleanFunction map(Function f, Predicate g) { + static ToBooleanFunction map( + Function f, + Predicate g) { return BooleanFunctions.map(f, g); } @@ -72,7 +76,7 @@ static ToBooleanFunction map(Function f, Predicate g) { * @return the or-function * @param the input type */ - static ToBooleanFunction or(Collection> functions) { + static ToBooleanFunction or(Collection> functions) { return BooleanFunctions.or(functions); } @@ -84,18 +88,18 @@ static ToBooleanFunction or(Collection> functions) { * @return the and-function * @param the input type */ - static ToBooleanFunction and(Collection> functions) { + static ToBooleanFunction and(Collection> functions) { return BooleanFunctions.and(functions); } /** - * Creates a function that is the opposite of {@code f}. Equivalent to {@code x -> !x}. + * Creates a function that is the opposite of {@code f}. Equivalent to {@code x -> !f.test(x)}. * * @param f the function * @return the not-function * @param the input type */ - static ToBooleanFunction not(ToBooleanFunction f) { + static ToBooleanFunction not(Predicate f) { return BooleanFunctions.not(f); } @@ -111,4 +115,22 @@ default BooleanType returnType() { default R walk(Visitor visitor) { return visitor.visit(this); } + + @Override + @NotNull + default ToBooleanFunction negate() { + return not(this); + } + + @Override + @NotNull + default ToBooleanFunction and(@NotNull Predicate other) { + return ToBooleanFunction.and(List.of(this, other)); + } + + @Override + @NotNull + default ToBooleanFunction or(@NotNull Predicate other) { + return ToBooleanFunction.or(List.of(this, other)); + } } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToByteFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToByteFunction.java index 93a7a5439a4..511938a68e2 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToByteFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToByteFunction.java @@ -38,7 +38,9 @@ static ToByteFunction cast() { * @param the input type * @param the intermediate type */ - static ToByteFunction map(Function f, ToByteFunction g) { + static ToByteFunction map( + Function f, + ToByteFunction g) { return ByteFunctions.map(f, g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToCharFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToCharFunction.java index 33cf7931176..6e6cbc30bfb 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToCharFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToCharFunction.java @@ -37,7 +37,9 @@ static ToCharFunction cast() { * @param the input type * @param the intermediate type */ - static ToCharFunction map(Function f, ToCharFunction g) { + static ToCharFunction map( + Function f, + ToCharFunction g) { return CharFunctions.map(f, g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToDoubleFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToDoubleFunction.java index 4d7a6c0d725..46a20e0e2c9 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToDoubleFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToDoubleFunction.java @@ -38,7 +38,9 @@ static ToDoubleFunction cast() { * @param the input type * @param the intermediate type */ - static ToDoubleFunction map(Function f, java.util.function.ToDoubleFunction g) { + static ToDoubleFunction map( + Function f, + java.util.function.ToDoubleFunction g) { return DoubleFunctions.map(f, g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToFloatFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToFloatFunction.java index fc0d34e8ac3..ad131d34105 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToFloatFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToFloatFunction.java @@ -37,7 +37,9 @@ static ToFloatFunction cast() { * @param the input type * @param the intermediate type */ - static ToFloatFunction map(Function f, ToFloatFunction g) { + static ToFloatFunction map( + Function f, + ToFloatFunction g) { return FloatFunctions.map(f, g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToIntFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToIntFunction.java index 26da4dfad5a..4bf7f603230 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToIntFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToIntFunction.java @@ -38,7 +38,9 @@ static ToIntFunction cast() { * @param the input type * @param the intermediate type */ - static ToIntFunction map(Function f, java.util.function.ToIntFunction g) { + static ToIntFunction map( + Function f, + java.util.function.ToIntFunction g) { return IntFunctions.map(f, g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToLongFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToLongFunction.java index f21c629a4e5..674431642dc 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToLongFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToLongFunction.java @@ -37,7 +37,9 @@ static ToLongFunction cast() { * @param the input type * @param the intermediate type */ - static ToLongFunction map(Function f, java.util.function.ToLongFunction g) { + static ToLongFunction map( + Function f, + java.util.function.ToLongFunction g) { return LongFunctions.map(f, g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToObjectFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToObjectFunction.java index 9e476f903bc..80b61870ea9 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToObjectFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToObjectFunction.java @@ -28,7 +28,7 @@ public interface ToObjectFunction extends TypedFunction, Function * @param the input type * @param the return type */ - static ToObjectFunction of(Function f, GenericType returnType) { + static ToObjectFunction of(Function f, GenericType returnType) { return ObjectFunctions.of(f, returnType); } @@ -65,8 +65,11 @@ static ToObjectFunction identity(GenericType returnTyp * @return the object function * @param the input type * @param the intermediate type + * @param the return type */ - static ToObjectFunction map(Function f, ToObjectFunction g) { + static ToObjectFunction map( + Function f, + ToObjectFunction g) { return ObjectFunctions.map(f, g); } @@ -82,8 +85,12 @@ static ToObjectFunction map(Function f, ToObjectFunction the input type * @param the intermediate type + * @param the return type */ - static ToObjectFunction map(Function f, Function g, GenericType returnType) { + static ToObjectFunction map( + Function f, + Function g, + GenericType returnType) { return ObjectFunctions.map(f, g, returnType); } @@ -99,8 +106,9 @@ static ToObjectFunction map(Function f, Function g, * * @param g the outer function * @return the boolean function + * @param the returned function input type */ - default ToBooleanFunction mapToBoolean(Predicate g) { + default ToBooleanFunction mapToBoolean(Predicate g) { return ToBooleanFunction.map(this, g); } @@ -112,8 +120,9 @@ default ToBooleanFunction mapToBoolean(Predicate g) { * * @param g the outer function * @return the char function + * @param the returned function input type */ - default ToCharFunction mapToChar(ToCharFunction g) { + default ToCharFunction mapToChar(ToCharFunction g) { return ToCharFunction.map(this, g); } @@ -125,8 +134,9 @@ default ToCharFunction mapToChar(ToCharFunction g) { * * @param g the outer function * @return the byte function + * @param the returned function input type */ - default ToByteFunction mapToByte(ToByteFunction g) { + default ToByteFunction mapToByte(ToByteFunction g) { return ToByteFunction.map(this, g); } @@ -138,8 +148,9 @@ default ToByteFunction mapToByte(ToByteFunction g) { * * @param g the outer function * @return the short function + * @param the returned function input type */ - default ToShortFunction mapToShort(ToShortFunction g) { + default ToShortFunction mapToShort(ToShortFunction g) { return ToShortFunction.map(this, g); } @@ -151,8 +162,9 @@ default ToShortFunction mapToShort(ToShortFunction g) { * * @param g the outer function * @return the int function + * @param the returned function input type */ - default ToIntFunction mapToInt(java.util.function.ToIntFunction g) { + default ToIntFunction mapToInt(java.util.function.ToIntFunction g) { return ToIntFunction.map(this, g); } @@ -164,8 +176,9 @@ default ToIntFunction mapToInt(java.util.function.ToIntFunction g) { * * @param g the outer function * @return the long function + * @param the returned function input type */ - default ToLongFunction mapToLong(java.util.function.ToLongFunction g) { + default ToLongFunction mapToLong(java.util.function.ToLongFunction g) { return ToLongFunction.map(this, g); } @@ -177,8 +190,9 @@ default ToLongFunction mapToLong(java.util.function.ToLongFunction g) { * * @param g the outer function * @return the float function + * @param the returned function input type */ - default ToFloatFunction mapToFloat(ToFloatFunction g) { + default ToFloatFunction mapToFloat(ToFloatFunction g) { return ToFloatFunction.map(this, g); } @@ -190,8 +204,9 @@ default ToFloatFunction mapToFloat(ToFloatFunction g) { * * @param g the outer function * @return the double function + * @param the returned function input type */ - default ToDoubleFunction mapToDouble(java.util.function.ToDoubleFunction g) { + default ToDoubleFunction mapToDouble(java.util.function.ToDoubleFunction g) { return ToDoubleFunction.map(this, g); } @@ -203,8 +218,10 @@ default ToDoubleFunction mapToDouble(java.util.function.ToDoubleFunction g * * @param g the outer function * @return the object function + * @param the returned function input type + * @param the returned function return type */ - default ToObjectFunction mapToObj(ToObjectFunction g) { + default ToObjectFunction mapToObj(ToObjectFunction g) { return map(this, g); } @@ -216,8 +233,12 @@ default ToObjectFunction mapToObj(ToObjectFunction g) { * * @param g the outer function * @return the object function - */ - default ToObjectFunction mapToObj(Function g, GenericType returnType) { + * @param the returned function input type + * @param the returned function return type + **/ + default ToObjectFunction mapToObj( + Function g, + GenericType returnType) { return map(this, g, returnType); } @@ -237,9 +258,10 @@ default ToObjectFunction mapToObj(Function g, GenericType * @see #mapToLong(java.util.function.ToLongFunction) * @see #mapToFloat(ToFloatFunction) * @see #mapToDouble(java.util.function.ToDoubleFunction) + * @param the returned function input type */ - default ToPrimitiveFunction mapToPrimitive(ToPrimitiveFunction g) { - return ObjectFunctions.mapPrimitive(this, g); + default ToPrimitiveFunction mapToPrimitive(ToPrimitiveFunction g) { + return PrimitiveFunctions.map(this, g); } /** @@ -252,27 +274,26 @@ default ToPrimitiveFunction mapToPrimitive(ToPrimitiveFunction g) { * @return the function * @see #mapToPrimitive(ToPrimitiveFunction) * @see #mapToObj(ToObjectFunction) + * @param the returned function input type */ - default TypedFunction map(TypedFunction g) { - return ObjectFunctions.map(this, g); + default TypedFunction map(TypedFunction g) { + return TypedFunctions.map(this, g); } /** * Creates a function by casting to {@code returnType}. * *

- * In the case where {@code returnType().equals(returnType)}, the result is {@code (ObjectFunction) this}. + * In the case where {@code returnType().equals(returnType)}, the result is {@code (ObjectFunction) this}. * Otherwise, the result is equivalent to {@code x -> (R2) this.apply(x)}. * * @param returnType the return type * @return the object function - * @param the return type + * @param the returned function input type + * @param the returned function return type */ - default ToObjectFunction cast(GenericType returnType) { - // noinspection unchecked - return returnType().equals(returnType) - ? (ToObjectFunction) this - : mapToObj(ObjectFunctions.cast(returnType)); + default ToObjectFunction cast(GenericType returnType) { + return ObjectFunctions.castOrMapCast(this, returnType); } @Override diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/ToShortFunction.java b/extensions/protobuf/src/main/java/io/deephaven/functions/ToShortFunction.java index 312ed3cef45..7c4810a78ec 100644 --- a/extensions/protobuf/src/main/java/io/deephaven/functions/ToShortFunction.java +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/ToShortFunction.java @@ -38,7 +38,9 @@ static ToShortFunction cast() { * @param the input type * @param the intermediate type */ - static ToShortFunction map(Function f, ToShortFunction g) { + static ToShortFunction map( + Function f, + ToShortFunction g) { return ShortFunctions.map(f, g); } diff --git a/extensions/protobuf/src/main/java/io/deephaven/functions/TypedFunctions.java b/extensions/protobuf/src/main/java/io/deephaven/functions/TypedFunctions.java new file mode 100644 index 00000000000..46d9bbeeb02 --- /dev/null +++ b/extensions/protobuf/src/main/java/io/deephaven/functions/TypedFunctions.java @@ -0,0 +1,40 @@ +package io.deephaven.functions; + +import java.util.Objects; + +class TypedFunctions { + static TypedFunction cast(TypedFunction f) { + // noinspection unchecked + return (TypedFunction) f; + } + + static TypedFunction map( + ToObjectFunction f, + TypedFunction g) { + return MapVisitor.of(f, g); + } + + private static class MapVisitor implements TypedFunction.Visitor> { + + public static TypedFunction of(ToObjectFunction f, + TypedFunction g) { + return g.walk(new MapVisitor<>(f)); + } + + private final ToObjectFunction f; + + private MapVisitor(ToObjectFunction f) { + this.f = Objects.requireNonNull(f); + } + + @Override + public ToPrimitiveFunction visit(ToPrimitiveFunction g) { + return f.mapToPrimitive(g); + } + + @Override + public ToObjectFunction visit(ToObjectFunction g) { + return f.mapToObj(g); + } + } +} diff --git a/extensions/protobuf/src/test/java/io/deephaven/functions/ToBooleanFunctionTest.java b/extensions/protobuf/src/test/java/io/deephaven/functions/ToBooleanFunctionTest.java index f9828e8ce52..316bf10dff0 100644 --- a/extensions/protobuf/src/test/java/io/deephaven/functions/ToBooleanFunctionTest.java +++ b/extensions/protobuf/src/test/java/io/deephaven/functions/ToBooleanFunctionTest.java @@ -14,51 +14,134 @@ public class ToBooleanFunctionTest { + private static final Object OBJ = new Object(); + + // Specifically create versions that aren't the library's internal objects + + private static ToBooleanFunction myTrue() { + return x -> true; + } + + private static ToBooleanFunction myFalse() { + return x -> false; + } + @Test void ofTrue_() { - assertThat(ofTrue().test(new Object())).isTrue(); + isTrue(ofTrue(), OBJ); + isTrue(myTrue(), OBJ); } @Test void ofFalse_() { - assertThat(ofFalse().test(new Object())).isFalse(); + isFalse(ofFalse(), OBJ); + isFalse(myFalse(), OBJ); } @Test void or_() { - assertThat(or(List.of()).test(new Object())).isFalse(); - assertThat(or(List.of(ofFalse())).test(new Object())).isFalse(); - assertThat(or(List.of(ofTrue())).test(new Object())).isTrue(); - assertThat(or(List.of(ofFalse(), ofFalse())).test(new Object())).isFalse(); - assertThat(or(List.of(ofFalse(), ofTrue())).test(new Object())).isTrue(); - assertThat(or(List.of(ofTrue(), ofFalse())).test(new Object())).isTrue(); - assertThat(or(List.of(ofTrue(), ofTrue())).test(new Object())).isTrue(); + isFalse(or(List.of()), OBJ); + + isFalse(or(List.of(ofFalse())), OBJ); + isTrue(or(List.of(ofTrue())), OBJ); + isFalse(or(List.of(ofFalse(), ofFalse())), OBJ); + isTrue(or(List.of(ofFalse(), ofTrue())), OBJ); + isTrue(or(List.of(ofTrue(), ofFalse())), OBJ); + isTrue(or(List.of(ofTrue(), ofTrue())), OBJ); + + isFalse(or(List.of(myFalse())), OBJ); + isTrue(or(List.of(myTrue())), OBJ); + isFalse(or(List.of(myFalse(), myFalse())), OBJ); + isTrue(or(List.of(myFalse(), myTrue())), OBJ); + isTrue(or(List.of(myTrue(), myFalse())), OBJ); + isTrue(or(List.of(myTrue(), myTrue())), OBJ); } @Test void and_() { - assertThat(and(List.of()).test(new Object())).isTrue(); - assertThat(and(List.of(ofFalse())).test(new Object())).isFalse(); - assertThat(and(List.of(ofTrue())).test(new Object())).isTrue(); - assertThat(and(List.of(ofFalse(), ofFalse())).test(new Object())).isFalse(); - assertThat(and(List.of(ofFalse(), ofTrue())).test(new Object())).isFalse(); - assertThat(and(List.of(ofTrue(), ofFalse())).test(new Object())).isFalse(); - assertThat(and(List.of(ofTrue(), ofTrue())).test(new Object())).isTrue(); + isTrue(and(List.of()), OBJ); + + isFalse(and(List.of(ofFalse())), OBJ); + isTrue(and(List.of(ofTrue())), OBJ); + isFalse(and(List.of(ofFalse(), ofFalse())), OBJ); + isFalse(and(List.of(ofFalse(), ofTrue())), OBJ); + isFalse(and(List.of(ofTrue(), ofFalse())), OBJ); + isTrue(and(List.of(ofTrue(), ofTrue())), OBJ); + + isFalse(and(List.of(myFalse())), OBJ); + isTrue(and(List.of(myTrue())), OBJ); + isFalse(and(List.of(myFalse(), myFalse())), OBJ); + isFalse(and(List.of(myFalse(), myTrue())), OBJ); + isFalse(and(List.of(myTrue(), myFalse())), OBJ); + isTrue(and(List.of(myTrue(), myTrue())), OBJ); } @Test void not_() { - assertThat(not(ofTrue()).test(new Object())).isFalse(); - assertThat(not(ofFalse()).test(new Object())).isTrue(); + isFalse(not(ofTrue()), OBJ); + isTrue(not(ofFalse()), OBJ); + + isFalse(not(myTrue()), OBJ); + isTrue(not(myFalse()), OBJ); } @Test void map_() { final ToBooleanFunction trimIsFoo = map(String::trim, "foo"::equals); - assertThat(trimIsFoo.test("")).isFalse(); - assertThat(trimIsFoo.test(" ")).isFalse(); - assertThat(trimIsFoo.test("foo")).isTrue(); - assertThat(trimIsFoo.test(" foo ")).isTrue(); - assertThat(trimIsFoo.test(" foo bar")).isFalse(); + isFalse(trimIsFoo, ""); + isFalse(trimIsFoo, " "); + isTrue(trimIsFoo, "foo"); + isTrue(trimIsFoo, " foo "); + isFalse(trimIsFoo, " foo bar"); + } + + private static void isTrue(ToBooleanFunction f, X x) { + assertThat(f.test(x)).isTrue(); + assertThat(f.negate().test(x)).isFalse(); + + assertThat(f.or(ofTrue()).test(x)).isTrue(); + assertThat(f.and(ofTrue()).test(x)).isTrue(); + assertThat(f.or(ofFalse()).test(x)).isTrue(); + assertThat(f.and(ofFalse()).test(x)).isFalse(); + + assertThat(ToBooleanFunction.ofTrue().or(f).test(x)).isTrue(); + assertThat(ToBooleanFunction.ofTrue().and(f).test(x)).isTrue(); + assertThat(ToBooleanFunction.ofFalse().or(f).test(x)).isTrue(); + assertThat(ToBooleanFunction.ofFalse().and(f).test(x)).isFalse(); + + assertThat(f.or(myTrue()).test(x)).isTrue(); + assertThat(f.and(myTrue()).test(x)).isTrue(); + assertThat(f.or(myFalse()).test(x)).isTrue(); + assertThat(f.and(myFalse()).test(x)).isFalse(); + + assertThat(ToBooleanFunctionTest.myTrue().or(f).test(x)).isTrue(); + assertThat(ToBooleanFunctionTest.myTrue().and(f).test(x)).isTrue(); + assertThat(ToBooleanFunctionTest.myFalse().or(f).test(x)).isTrue(); + assertThat(ToBooleanFunctionTest.myFalse().and(f).test(x)).isFalse(); + } + + private static void isFalse(ToBooleanFunction f, X x) { + assertThat(f.test(x)).isFalse(); + assertThat(f.negate().test(x)).isTrue(); + + assertThat(f.or(ofTrue()).test(x)).isTrue(); + assertThat(f.and(ofTrue()).test(x)).isFalse(); + assertThat(f.or(ofFalse()).test(x)).isFalse(); + assertThat(f.and(ofFalse()).test(x)).isFalse(); + + assertThat(ToBooleanFunction.ofTrue().or(f).test(x)).isTrue(); + assertThat(ToBooleanFunction.ofTrue().and(f).test(x)).isFalse(); + assertThat(ToBooleanFunction.ofFalse().or(f).test(x)).isFalse(); + assertThat(ToBooleanFunction.ofFalse().and(f).test(x)).isFalse(); + + assertThat(f.or(myTrue()).test(x)).isTrue(); + assertThat(f.and(myTrue()).test(x)).isFalse(); + assertThat(f.or(myFalse()).test(x)).isFalse(); + assertThat(f.and(myFalse()).test(x)).isFalse(); + + assertThat(ToBooleanFunctionTest.myTrue().or(f).test(x)).isTrue(); + assertThat(ToBooleanFunctionTest.myTrue().and(f).test(x)).isFalse(); + assertThat(ToBooleanFunctionTest.myFalse().or(f).test(x)).isFalse(); + assertThat(ToBooleanFunctionTest.myFalse().and(f).test(x)).isFalse(); } }