Skip to content

Commit

Permalink
runtime-compute: Change the way compose works with ToBoolean
Browse files Browse the repository at this point in the history
  • Loading branch information
Emil Forslund committed Jun 1, 2018
1 parent 72df8a3 commit cdc3b46
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 5 deletions.
Expand Up @@ -125,10 +125,42 @@ default int compare(T first, T second) {
return Boolean.compare(f, s); return Boolean.compare(f, s);
} }


/**
* {@inheritDoc}
* <p>
* {@code ToBoolean} is a bit special when it comes to the
* {@code compose()}-method. If the {@code before} method returns
* {@code null}, the composed expression will return {@code false}. This is
* to remain compatible with how Speedment handles predicates in streams.
* To get a {@code ToBooleanNullable} that acts as you might expect, instead
* use {@link #compose}
*
* @param before the function to apply before this function is applied
* @param <V> the input type of the {@code before} function
* @return the composed expression
*/
@Override @Override
default <V> ToBooleanNullable<V> compose(Function<? super V, ? extends T> before) { default <V> ToBoolean<V> compose(Function<? super V, ? extends T> before) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Function<V, T> casted = (Function<V, T>) before; final Function<V, T> casted = (Function<V, T>) before;
return ComposedUtil.composeToBoolean(casted, this); return ComposedUtil.composeToBoolean(casted, this);
} }

/**
* Returns a composed expression that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param before the function to apply before this function is applied
* @param <V> the input type of the {@code before} function
* @return the composed expression
*
* @since 3.1.2
*/
default <V> ToBooleanNullable<V> composeNullable(Function<? super V, ? extends T> before) {
@SuppressWarnings("unchecked")
final Function<V, T> casted = (Function<V, T>) before;
return ComposedUtil.composeToBooleanAsNullable(casted, this);
}
} }
Expand Up @@ -455,10 +455,24 @@ public Double apply(T object) {
* @param <A> the type returned by {@code first} * @param <A> the type returned by {@code first}
* @return the composed expression * @return the composed expression
*/ */
public static <T, A> ToBooleanNullable<T> composeToBoolean(Function<T, A> before, ToBoolean<A> after) { public static <T, A> ToBoolean<T> composeToBoolean(Function<T, A> before, ToBoolean<A> after) {
return new ComposeToBoolean<>(before, after); return new ComposeToBoolean<>(before, after);
} }


/**
* Returns a new expression that first applies the {@code first} function
* and then passes the result to the {@code second} expression.
*
* @param before the first function to apply
* @param after the expression to apply to the result
* @param <T> the type of the initial input
* @param <A> the type returned by {@code first}
* @return the composed expression
*/
public static <T, A> ToBooleanNullable<T> composeToBooleanAsNullable(Function<T, A> before, ToBoolean<A> after) {
return new ComposeToBooleanNullable<>(before, after);
}

/** /**
* Returns a new expression that first applies the {@code first} function * Returns a new expression that first applies the {@code first} function
* and then passes the result to the {@code second} expression. * and then passes the result to the {@code second} expression.
Expand All @@ -470,18 +484,22 @@ public static <T, A> ToBooleanNullable<T> composeToBoolean(Function<T, A> before
* @return the composed expression * @return the composed expression
*/ */
public static <T, A> ToBooleanNullable<T> composeToBooleanNullable(Function<T, A> before, ToBooleanNullable<A> after) { public static <T, A> ToBooleanNullable<T> composeToBooleanNullable(Function<T, A> before, ToBooleanNullable<A> after) {
return new ComposeToBoolean<>(before, after); return new ComposeToBooleanNullable<>(before, after);
} }


/** /**
* Internal implementation of the {@link ComposedExpression}. * Internal implementation of the {@link ComposedExpression}. Booleans are
* handled a bit differently when it comes to {@code null}-values. If the
* {@code before}-function returns {@code null}, then the expression will
* always evaluate to {@code false}. This is to stay compatible with how
* Speedment handles predicates in streams.
* *
* @param <T> the outer input type * @param <T> the outer input type
* @param <A> the inner input type * @param <A> the inner input type
* @param <AFTER> the expression type of the {@code after} operation * @param <AFTER> the expression type of the {@code after} operation
*/ */
private final static class ComposeToBoolean<T, A, AFTER extends ToBooleanFunction<A> & Expression<A>> private final static class ComposeToBoolean<T, A, AFTER extends ToBooleanFunction<A> & Expression<A>>
implements ComposedExpression<T, A>, ToBooleanNullable<T> { implements ComposedExpression<T, A>, ToBoolean<T> {


private final Function<T, A> before; private final Function<T, A> before;
private final AFTER after; private final AFTER after;
Expand All @@ -501,6 +519,41 @@ public AFTER secondStep() {
return after; return after;
} }


@Override
public boolean applyAsBoolean(T object) throws NullPointerException {
final A intermediate = before.apply(object);
return intermediate != null && after.applyAsBoolean(intermediate);
}
}

/**
* Internal implementation of the {@link ComposedExpression}.
*
* @param <T> the outer input type
* @param <A> the inner input type
* @param <AFTER> the expression type of the {@code after} operation
*/
private final static class ComposeToBooleanNullable<T, A, AFTER extends ToBooleanFunction<A> & Expression<A>>
implements ComposedExpression<T, A>, ToBooleanNullable<T> {

private final Function<T, A> before;
private final AFTER after;

ComposeToBooleanNullable(Function<T, A> before, AFTER after) {
this.before = requireNonNull(before);
this.after = requireNonNull(after);
}

@Override
public Function<T, A> firstStep() {
return before;
}

@Override
public AFTER secondStep() {
return after;
}

@Override @Override
public boolean applyAsBoolean(T object) throws NullPointerException { public boolean applyAsBoolean(T object) throws NullPointerException {
final A intermediate = before.apply(object); final A intermediate = before.apply(object);
Expand Down

0 comments on commit cdc3b46

Please sign in to comment.