Skip to content

Commit

Permalink
fix(core): Allow mapper to throw exceptions (#224)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLion authored Dec 6, 2023
1 parent 25f50ea commit beea222
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 70 deletions.
18 changes: 8 additions & 10 deletions src/main/java/io/github/joselion/maybe/Maybe.java
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,10 @@ public static <R extends Closeable, E extends Throwable> CloseableHandler<R, E>
* {@link #empty()} otherwise
*/
public <U> Maybe<U> map(final Function<? super T, ? extends U> mapper) {
return Maybe
.of(this.value)
.<U, Throwable>solve(mapper::apply)
.toMaybe();
return this.value
.map(mapper)
.map(Maybe::<U>of)
.orElseGet(Maybe::empty);
}

/**
Expand All @@ -416,9 +416,8 @@ public <U> Maybe<U> map(final Function<? super T, ? extends U> mapper) {
* {@link #empty()} otherwise
*/
public <U> Maybe<U> flatMap(final Function<? super T, Maybe<? extends U>> mapper) {
return Maybe
.of(this.value)
.solve(mapper::apply)
return this.value
.map(mapper)
.map(Commons::<Maybe<U>>cast)
.orElseGet(Maybe::empty);
}
Expand Down Expand Up @@ -514,11 +513,10 @@ public <E extends Throwable> EffectHandler<E> runEffect(// NOSONAR
* @return a new {@code Maybe} with the cast value if it can be cast,
* {@link #empty()} otherwise
*/
public <U> Maybe<U> cast(final Class<U> type) {
public <U> SolveHandler<U, ClassCastException> cast(final Class<U> type) {
return Maybe
.of(this.value)
.solve(type::cast)
.toMaybe();
.solve(type::cast);
}

/**
Expand Down
12 changes: 1 addition & 11 deletions src/main/java/io/github/joselion/maybe/SolveHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -393,16 +393,7 @@ public <U> SolveHandler<U, E> flatMap(final Function<? super T, Maybe<? extends
* error
*/
public <U> SolveHandler<U, ClassCastException> cast(final Class<U> type) {
return this.value.unwrap(
error -> failure(new ClassCastException(error.getMessage())),
success -> {
try {
return from(type.cast(success));
} catch (ClassCastException error) {
return failure(error);
}
}
);
return this.solve(type::cast);
}

/**
Expand Down Expand Up @@ -577,7 +568,6 @@ public <R extends AutoCloseable, X extends Throwable> CloseableHandler<R, X> sol
.of(prev)
.solve(solver)
.map(CloseableHandler::<R, X>from)
.catchError(CloseableHandler::failure)
.orElse(CloseableHandler::failure)
);
}
Expand Down
18 changes: 8 additions & 10 deletions src/main/java17/io/github/joselion/maybe/Maybe.java
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,10 @@ public static <R extends Closeable, E extends Throwable> CloseableHandler<R, E>
* {@link #empty()} otherwise
*/
public <U> Maybe<U> map(final Function<? super T, ? extends U> mapper) {
return Maybe
.of(this.value)
.<U, Throwable>solve(mapper::apply)
.toMaybe();
return this.value
.map(mapper)
.map(Maybe::<U>of)
.orElseGet(Maybe::empty);
}

/**
Expand All @@ -416,9 +416,8 @@ public <U> Maybe<U> map(final Function<? super T, ? extends U> mapper) {
* {@link #empty()} otherwise
*/
public <U> Maybe<U> flatMap(final Function<? super T, Maybe<? extends U>> mapper) {
return Maybe
.of(this.value)
.solve(mapper::apply)
return this.value
.map(mapper)
.map(Commons::<Maybe<U>>cast)
.orElseGet(Maybe::empty);
}
Expand Down Expand Up @@ -514,11 +513,10 @@ public <E extends Throwable> EffectHandler<E> runEffect(// NOSONAR
* @return a new {@code Maybe} with the cast value if it can be cast,
* {@link #empty()} otherwise
*/
public <U> Maybe<U> cast(final Class<U> type) {
public <U> SolveHandler<U, ClassCastException> cast(final Class<U> type) {
return Maybe
.of(this.value)
.solve(type::cast)
.toMaybe();
.solve(type::cast);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/io/github/joselion/maybe/MaybeTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -470,18 +470,18 @@

@Nested class cast {
@Nested class when_the_value_is_castable_to_the_passed_type {
@Test void returns_a_maybe_with_the_value_cast() {
@Test void returns_a_solve_handler_with_the_cast_value() {
final var maybe = Maybe.<Number>of(3);

assertThat(maybe.cast(Integer.class).value()).contains(3);
assertThat(maybe.cast(Integer.class).success()).contains(3);
}
}

@Nested class when_the_value_is_not_castable_to_the_passed_type {
@Test void returns_an_empty_Maybe() {
@Test void returns_a_solve_handler_with_a_ClassCastException() {
final var maybe = Maybe.of("3");

assertThat(maybe.cast(Integer.class).value()).isEmpty();
assertThat(maybe.cast(Integer.class).error()).containsInstanceOf(ClassCastException.class);
}
}
}
Expand Down
65 changes: 30 additions & 35 deletions src/test/java/io/github/joselion/maybe/SolveHandlerTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@

private static final String OTHER = "OTHER";

private static final FileSystemException FAIL_EXCEPTION = new FileSystemException("FAIL");
private static final FileSystemException FAILURE = new FileSystemException("FAIL");

private final ThrowingSupplier<String, FileSystemException> throwingOp = () -> {
throw FAIL_EXCEPTION;
throw FAILURE;
};

private final ThrowingSupplier<String, RuntimeException> okOp = () -> OK;
Expand Down Expand Up @@ -66,10 +66,10 @@
@Nested class failure {
@Nested class when_the_error_is_not_null {
@Test void returns_a_handler_with_the_error() {
final var handler = SolveHandler.failure(FAIL_EXCEPTION);
final var handler = SolveHandler.failure(FAILURE);

assertThat(handler.success()).isEmpty();
assertThat(handler.error()).containsSame(FAIL_EXCEPTION);
assertThat(handler.error()).containsSame(FAILURE);
}
}

Expand Down Expand Up @@ -120,7 +120,7 @@
Maybe.from(throwingOp)
.doOnError(FileSystemException.class, consumerSpy);

verify(consumerSpy, times(1)).accept(FAIL_EXCEPTION);
verify(consumerSpy, times(1)).accept(FAILURE);
}
}

Expand All @@ -143,7 +143,7 @@
Maybe.from(throwingOp)
.doOnError(consumerSpy);

verify(consumerSpy, times(1)).accept(FAIL_EXCEPTION);
verify(consumerSpy, times(1)).accept(FAILURE);
}
}
}
Expand Down Expand Up @@ -173,7 +173,7 @@
assertThat(handler.success()).contains(OK);
assertThat(handler.error()).isEmpty();

verify(functionSpy, times(1)).apply(FAIL_EXCEPTION);
verify(functionSpy, times(1)).apply(FAILURE);
}
}

Expand All @@ -184,7 +184,7 @@
.catchError(AccessDeniedException.class, functionSpy);

assertThat(handler.success()).isEmpty();
assertThat(handler.error()).contains(FAIL_EXCEPTION);
assertThat(handler.error()).contains(FAILURE);

verify(functionSpy, never()).apply(any());
}
Expand All @@ -200,7 +200,7 @@
assertThat(solver.success()).contains(OK);
assertThat(solver.error()).isEmpty();

verify(handlerSpy, times(1)).apply(FAIL_EXCEPTION);
verify(handlerSpy, times(1)).apply(FAILURE);
}
}
}
Expand Down Expand Up @@ -255,8 +255,8 @@
assertThat(handler.success()).isEmpty();
assertThat(handler.error())
.get(THROWABLE)
.isExactlyInstanceOf(FAIL_EXCEPTION.getClass())
.isEqualTo(FAIL_EXCEPTION);
.isExactlyInstanceOf(FAILURE.getClass())
.isEqualTo(FAILURE);

verify(successSpy, never()).apply(any());
}
Expand All @@ -273,7 +273,7 @@
assertThat(handler.error()).isEmpty();

verify(successSpy, never()).apply(any());
verify(errorSpy, times(1)).apply(FAIL_EXCEPTION);
verify(errorSpy, times(1)).apply(FAILURE);
}
}
}
Expand Down Expand Up @@ -304,7 +304,7 @@
);

assertThat(newHandlers).isNotEmpty().allSatisfy(newHandler -> {
assertThat(newHandler.error()).contains(FAIL_EXCEPTION);
assertThat(newHandler.error()).contains(FAILURE);
});

verify(effectSpy, times(1)).accept(OK);
Expand All @@ -323,10 +323,10 @@
final var handler = Maybe.from(throwingOp);
final var newHandler = handler.effect(successSpy, errorSpy);

assertThat(newHandler.error()).contains(FAIL_EXCEPTION);
assertThat(newHandler.error()).contains(FAILURE);

verify(successSpy, never()).accept(any());
verify(errorSpy, times(1)).accept(FAIL_EXCEPTION);
verify(errorSpy, times(1)).accept(FAILURE);
}
}

Expand All @@ -338,8 +338,8 @@

assertThat(newHandler.error())
.get(THROWABLE)
.isExactlyInstanceOf(FAIL_EXCEPTION.getClass())
.isEqualTo(FAIL_EXCEPTION);
.isExactlyInstanceOf(FAILURE.getClass())
.isEqualTo(FAILURE);

verify(effectSpy, never()).accept(any());
}
Expand Down Expand Up @@ -374,11 +374,11 @@

@Nested class when_the_error_is_present {
@Test void returns_a_handler_with_the_previous_error() {
final var handler = SolveHandler.failure(FAIL_EXCEPTION)
final var handler = SolveHandler.failure(FAILURE)
.map(Object::toString);

assertThat(handler.success()).isEmpty();
assertThat(handler.error()).contains(FAIL_EXCEPTION);
assertThat(handler.error()).contains(FAILURE);
}
}
}
Expand All @@ -396,11 +396,11 @@

@Nested class when_the_error_is_present {
@Test void returns_a_handler_with_the_previous_error() {
final var handler = SolveHandler.failure(FAIL_EXCEPTION)
final var handler = SolveHandler.failure(FAILURE)
.flatMap(x -> Maybe.of(x.toString()));

assertThat(handler.success()).isEmpty();
assertThat(handler.error()).contains(FAIL_EXCEPTION);
assertThat(handler.error()).contains(FAILURE);
}
}
}
Expand All @@ -420,8 +420,7 @@

@Nested class and_the_object_can_not_be_cast {
@Test void returns_a_handler_with_the_cast_exception() {
final var handler = SolveHandler.from(3)
.cast(String.class);
final var handler = SolveHandler.from(3).cast(String.class);

assertThat(handler.success()).isEmpty();
assertThat(handler.error())
Expand All @@ -433,15 +432,11 @@
}

@Nested class when_the_error_is_present {
@Test void returns_a_handler_with_a_cast_exception() {
final var handler = SolveHandler.failure(FAIL_EXCEPTION)
.cast(String.class);
@Test void returns_a_handler_with_the_error() {
final var handler = SolveHandler.failure(FAILURE).cast(String.class);

assertThat(handler.success()).isEmpty();
assertThat(handler.error())
.get(THROWABLE)
.isExactlyInstanceOf(ClassCastException.class)
.hasMessage(FAIL_EXCEPTION.getMessage());
assertThat(handler.error()).get().isSameAs(FAILURE);
}
}
}
Expand All @@ -461,7 +456,7 @@
final var handler = Maybe.from(throwingOp);

assertThat(handler.orElse(OTHER)).isEqualTo(OTHER);
assertThat(handler.orElse(FileSystemException::getMessage)).isEqualTo(FAIL_EXCEPTION.getMessage());
assertThat(handler.orElse(FileSystemException::getMessage)).isEqualTo(FAILURE.getMessage());
}
}
}
Expand Down Expand Up @@ -511,7 +506,7 @@
@Nested class orThrow {
@Nested class when_the_value_is_present {
@Test void returns_the_value() throws FileSystemException {
final var functionSpy = Spy.function((RuntimeException error) -> FAIL_EXCEPTION);
final var functionSpy = Spy.function((RuntimeException error) -> FAILURE);
final var handler = Maybe.from(okOp);

assertThat(handler.orThrow()).isEqualTo(OK);
Expand All @@ -527,10 +522,10 @@
final var functionSpy = Spy.function((FileSystemException error) -> anotherError);
final var handler = Maybe.from(throwingOp);

assertThatThrownBy(handler::orThrow).isEqualTo(FAIL_EXCEPTION);
assertThatThrownBy(handler::orThrow).isEqualTo(FAILURE);
assertThatThrownBy(() -> handler.orThrow(functionSpy)).isEqualTo(anotherError);

verify(functionSpy, times(1)).apply(FAIL_EXCEPTION);
verify(functionSpy, times(1)).apply(FAILURE);
}
}
}
Expand Down Expand Up @@ -583,7 +578,7 @@

assertThat(either.isLeft()).isTrue();
assertThat(either.isRight()).isFalse();
assertThat(either.leftOrNull()).isEqualTo(FAIL_EXCEPTION);
assertThat(either.leftOrNull()).isEqualTo(FAILURE);
assertThat(either.rightOrNull()).isNull();
}
}
Expand Down

0 comments on commit beea222

Please sign in to comment.