Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): Allow mapper to throw exceptions #224

Merged
merged 1 commit into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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