Skip to content

Commit

Permalink
Add ResolveHandler filter (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLion authored May 3, 2021
1 parent 5ff659e commit b5694b6
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 3 deletions.
34 changes: 32 additions & 2 deletions src/main/java/com/github/joselion/maybe/ResolveHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

import org.eclipse.jdt.annotation.Nullable;

Expand Down Expand Up @@ -123,8 +124,9 @@ public <X extends E> ResolveHandler<T, E> catchError(final Class<X> errorType, f
* If neither the value nor the error is present, it returns an empty handler.
*
* @param <U> the type the value will be mapped to
* @param mapper a function to map the current value to another (if present)
* @return a new handler with the mapped value, the previous error, or nothing
* @param mapper a function to map the value to another (if present)
* @return a new handler with either the mapped value, the previous error, or
* nothing
*/
public <U> ResolveHandler<U, E> map(final Function<T, U> mapper) {
if (success.isPresent()) {
Expand All @@ -138,6 +140,34 @@ public <U> ResolveHandler<U, E> map(final Function<T, U> mapper) {
return withNothing();
}

/**
* If a value is present, and the value matches the given {@code predicate},
* returns a new handler with the value, otherwise returns an empty handler.
* If the error is present, the {@code predicate} is never applied and, the
* next handler will still contain the error.
* <p>
* If neither the value nor the error is present, it returns an empty handler.
*
* @param predicate a predicate to apply to the value (if present)
* @return a new handler with either the value if it matched the predicate,
* the previous error, or nothing
*/
public ResolveHandler<T, E> filter(final Predicate<T> predicate) {
if (success.isPresent()) {
final T value = success.get();

return predicate.test(value)
? withSuccess(value)
: withNothing();
}

if (error.isPresent()) {
return withError(error.get());
}

return withNothing();
}

/**
* Returns the value resolved/handled if present. A default value otherwise.
*
Expand Down
67 changes: 66 additions & 1 deletion src/test/java/com/github/joselion/maybe/ResolveHandlerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

import com.github.joselion.maybe.helpers.UnitTest;
Expand Down Expand Up @@ -240,7 +241,7 @@
@Nested class map {
@Nested class when_the_value_is_present {
@Test void returns_a_new_handler_applying_the_mapper_function() {
final ResolveHandler<Integer, Exception> handler = ResolveHandler.withSuccess("Hello world!")
final ResolveHandler<Integer, ?> handler = ResolveHandler.withSuccess("Hello world!")
.map(String::length);

assertThat(handler)
Expand Down Expand Up @@ -284,6 +285,70 @@
}
}

@Nested class filter {
@Nested class when_the_value_is_present {
@Nested class and_the_predicate_matches {
@Test void returns_a_new_handler_with_the_value() {
final ResolveHandler<String, ?> handler = ResolveHandler.withSuccess("Hello world!")
.filter(it -> it.contains("world"));

assertThat(handler)
.extracting(SUCCESS, optional(String.class))
.contains("Hello world!");

assertThat(handler)
.extracting(ERROR, optional(Exception.class))
.isEmpty();
}
}

@Nested class and_the_predicate_does_NOT_match {
@Test void returns_an_empty_handler() {
final ResolveHandler<String, ?> handler = ResolveHandler.withSuccess("Hello world!")
.filter(it -> it.contains("planet"));

assertThat(handler)
.extracting(SUCCESS, optional(String.class))
.isEmpty();

assertThat(handler)
.extracting(ERROR, optional(Exception.class))
.isEmpty();
}
}
}

@Nested class when_the_error_is_present {
@Test void returns_a_new_handler_with_the_previous_error() {
final ResolveHandler<?, IOException> handler = ResolveHandler.withError(FAIL_EXCEPTION)
.filter(Objects::isNull);

assertThat(handler)
.extracting(SUCCESS, optional(String.class))
.isEmpty();

assertThat(handler)
.extracting(ERROR, optional(IOException.class))
.contains(FAIL_EXCEPTION);
}
}

@Nested class when_neither_the_value_nor_the_error_is_present {
@Test void returns_an_empty_handler() {
final ResolveHandler<?, ?> handler = ResolveHandler.withNothing()
.filter(Objects::isNull);

assertThat(handler)
.extracting(SUCCESS, optional(String.class))
.isEmpty();

assertThat(handler)
.extracting(ERROR, optional(Exception.class))
.isEmpty();
}
}
}

@Nested class orDefault {
@Nested class when_the_value_is_present {
@Test void returns_the_value() {
Expand Down

0 comments on commit b5694b6

Please sign in to comment.