Skip to content

Commit

Permalink
Merge pull request #212 from bobaikato/Try-Value-Developement
Browse files Browse the repository at this point in the history
Try value developement
  • Loading branch information
bobaikato committed Nov 20, 2023
2 parents b13170a + 34b7da0 commit c3be977
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 75 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -305,5 +305,5 @@
<url>http://github.com/bobaikato/cutils/tree/master</url>
</scm>
<url>https://github.com/bobaikato/cutils</url>
<version>2.6.6</version>
<version>2.6.7</version>
</project>
182 changes: 108 additions & 74 deletions src/main/java/art/cutils/value/Try.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,31 +142,12 @@ public Try<T> onSuccess(final Consumer<? super T> result) {
public abstract boolean isSuccess();

/**
* Try is Empty if operation is Failed or Filter condition is not met.
*
* @return a {@link Boolean} depending on the state: {@code true} if try is empty else {@code
* false}
* @see Try#filter(Predicate)
* @see Try#isFailure()
* @see Try#isSuccess()
* @see Try#isNotEmpty()
* @since v2.4
*/
public abstract boolean isEmpty();

/**
* If try filter condition is not met, invoke the specified {@link Runnable}.
* Use to check the state of a successful try operation whether or not it has a result.
*
* @implNote this method is not intended to be used for handling failed operations. Use {@link
* Try#onFailure(Runnable)} to handle failed operation.
* @implSpec Try will invoke {@link Try#onEmpty(Runnable)} only if filter condition is not met.
* @param run the operation to be executed if filter condition is not met.
* @return existing instance of {@link Try}
* @since v2.4.5
* @see Try#onFailure(Runnable)
* @see Try#filter(Predicate)
* @return a {@link Boolean} depending on the state: {@code true} if try operation was successful
* and has a result or {@code false} if operation fails or successful but without a result.
*/
public abstract Try<T> onEmpty(final Runnable run);
public abstract boolean isResult();

/**
* Try is Not Empty if operation is Successful or filter condition is met.
Expand Down Expand Up @@ -194,6 +175,33 @@ public boolean isNotEmpty() {
*/
public abstract T get();

/**
* Try is Empty if operation is Failed or Filter condition is not met.
*
* @return a {@link Boolean} depending on the state: {@code true} if try is empty else {@code
* false}
* @see Try#filter(Predicate)
* @see Try#isFailure()
* @see Try#isSuccess()
* @see Try#isNotEmpty()
* @since v2.4
*/
public abstract boolean isEmpty();

/**
* If try filter condition is not met, invoke the specified {@link Runnable}.
*
* @implNote this method is not intended to be used for handling failed operations. Use {@link
* Try#onFailure(Runnable)} to handle failed operation.
* @implSpec Try will invoke {@link Try#onEmpty(Runnable)} only if filter condition is not met.
* @param run the operation to be executed if filter condition is not met.
* @return existing instance of {@link Try}
* @since v2.4.5
* @see Try#onFailure(Runnable)
* @see Try#filter(Predicate)
*/
public abstract Try<T> onEmpty(final Runnable run);

/**
* If a result is present, and the result matches the given predicate, returns a {@code Try}
* describing the result, otherwise returns an empty {@link Try}
Expand Down Expand Up @@ -296,7 +304,7 @@ public Try<T> onFailure(final Runnable run) {
}

/**
* If a try operation return a result, apply the provided mapping function to it, and return and
* If a try operation returns a result, apply the provided mapping function to it, and return and
* instance of {@link Try} with the applied result.
*
* @param mapper a mapping function to apply to the result is available.
Expand All @@ -309,6 +317,21 @@ public Try<T> onFailure(final Runnable run) {
*/
public abstract <M> Try<M> map(final ThrowingFunction<? super T, ? extends M> mapper);

/**
* If the try operation does not return a result after a {@link Try#filter(Predicate)}, apply the
* provided dealer function to provide a default value, and return an instance of {@link Try} with
* the provided default value.
*
* @param dealer a dealer function to provide a default value when the try operation does not
* return a result.
* @param <D> The type of the dealer value
* @return an instance of {@link Try} with the provided default value.
* @throws NullPointerException if the dealer function is null
* @throws IllegalStateException if a try operation state is {@link Success} but without a result.
* @throws UnsupportedOperationException if a try operation state is {@link Failure}.
*/
public abstract <D> Try<D> onEmpty(final Dealer<? extends D> dealer);

/**
* Return the result if try operation is successful and has a result, otherwise return {@code
* other} value.
Expand Down Expand Up @@ -351,36 +374,30 @@ public abstract <X extends Throwable> T orElseThrow(final Supplier<? extends X>
*/
public abstract T orElseThrow(final Throwable throwable);

/**
* Use to check the state of a successful try operation whether or not it has a result.
*
* @return a {@link Boolean} depending on the state: {@code true} if try operation was successful
* and has a result or {@code false} if operation fails or successful but without a result.
*/
public abstract boolean isResult();

private static class Success<S> extends Try<S> implements Serializable {
private static final long serialVersionUID = 4332649928027329163L;
private boolean isResult;

private S result;

/** Indicates whether the variable is empty or not. */
private boolean empty;

private Success(final boolean empty) {
this();
this.empty = empty;
}

private Success(final S result) {
this.isResult = true;
this.result = result;
}

private Success() {
super();
this.isResult = false;
}

private Success(final S result) {
this.isResult = true;
this.result = result;
}

/** {@inheritDoc} */
@Override
public int hashCode() {
Expand Down Expand Up @@ -414,18 +431,8 @@ public boolean isSuccess() {
/** {@inheritDoc} */
@Override
@Contract(pure = true)
public boolean isEmpty() {
return this.empty;
}

/** {@inheritDoc} */
@Override
public @Nullable Try<S> onEmpty(final Runnable task) {
Objects.requireNonNull(task, "on Empty Runnable cannot be null.");
if (this.isEmpty()) {
task.run();
}
return this;
public boolean isResult() {
return this.isResult;
}

/** {@inheritDoc} */
Expand All @@ -442,6 +449,23 @@ public S get() {
return this.result;
}

/** {@inheritDoc} */
@Override
@Contract(pure = true)
public boolean isEmpty() {
return this.empty;
}

/** {@inheritDoc} */
@Override
public Try<S> onEmpty(final Runnable task) {
Objects.requireNonNull(task, "onEmpty Runnable cannot be null.");
if (this.isEmpty()) {
task.run();
}
return this;
}

/** {@inheritDoc} */
@Override
@Contract("_ -> this")
Expand Down Expand Up @@ -471,7 +495,7 @@ private void clean() {
/** {@inheritDoc} */
@Override
@Contract(pure = true)
public @Nullable Try<S> peek(final Accepter<? super S> acceptor) {
public Try<S> peek(final Accepter<? super S> acceptor) {
Objects.requireNonNull(acceptor, "Accepter cannot be null.");
if (this.isResult && this.isNotEmpty()) {
try {
Expand Down Expand Up @@ -508,11 +532,21 @@ public boolean isFailure() {
@Override
public <M> @NotNull Try<M> map(final ThrowingFunction<? super S, ? extends M> mapper) {
Objects.requireNonNull(mapper, "Mapper cannot be null.");
if (this.isResult && this.isNotEmpty()) {
return Try.of(() -> mapper.apply(this.result));
return this.isResult && this.isNotEmpty()
? Try.of(() -> mapper.apply(this.result))
: new Success<>(true);
}

/** {@inheritDoc} */
@Override
@Contract(pure = true)
public <D> Try<D> onEmpty(final Dealer<? extends D> dealer) {
Objects.requireNonNull(dealer, "onEmpty Dealer cannot be null.");
if (this.isEmpty()) {
return Try.of(dealer);
}

return new Success<>(true);
return this.getClass().cast(this);
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -543,13 +577,6 @@ public <X extends Throwable> S orElseThrow(final Supplier<? extends X> exception
public S orElseThrow(final Throwable throwable) {
return this.get();
}

/** {@inheritDoc} */
@Override
@Contract(pure = true)
public boolean isResult() {
return this.isResult;
}
}

private static class Failure<F> extends Try<F> implements Serializable {
Expand All @@ -571,22 +598,29 @@ public boolean isSuccess() {
/** {@inheritDoc} */
@Override
@Contract(pure = true)
public boolean isEmpty() {
return true;
public boolean isResult() {
return false;
}

/** {@inheritDoc} */
@Override
@Contract(value = " -> this", pure = true)
public Try<F> onEmpty(final Runnable run) {
return this;
@Contract(pure = true)
public @Nullable F get() {
return null;
}

/** {@inheritDoc} */
@Override
@Contract(pure = true)
public @Nullable F get() {
return null;
public boolean isEmpty() {
return true;
}

/** {@inheritDoc} */
@Override
@Contract(value = " -> this", pure = true)
public Try<F> onEmpty(final Runnable run) {
return this;
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -635,6 +669,13 @@ public Throwable getCause() {
return new Failure<>(this.exception);
}

/** {@inheritDoc} */
@Override
@Contract(pure = true)
public <D> @NotNull Try<D> onEmpty(final Dealer<? extends D> dealer) {
return new Failure<>(this.exception);
}

/** {@inheritDoc} */
@Override
@Contract(value = "_ -> param1", pure = true)
Expand Down Expand Up @@ -669,13 +710,6 @@ public F orElseThrow(final @NotNull Throwable throwable) {
}
}

/** {@inheritDoc} */
@Override
@Contract(pure = true)
public boolean isResult() {
return false;
}

/** {@inheritDoc} */
@Override
public int hashCode() {
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/value/TryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ void testTryPeekSuccess() {

assertEquals(25, sameResult);
}

// test PeekFailure
@Test
void testTryPeekFailureAffectingTryState() {
Expand Down Expand Up @@ -364,4 +365,20 @@ void test_onSuccess_when_try_is_empty_to_not_invoke() {

assertEquals(26, value.get());
}

@Test
void onEmpty_whenTryIsEmpty_returnsDealerResult() {
Try.of(() -> null)
.filter(Objects::nonNull)
.onEmpty(() -> 42)
.onSuccess(result -> assertEquals(42, result));
}

@Test
void onEmpty_whenTryIsNotEmpty_returnsSameTry() {
Try.of(() -> 100)
.filter(Objects::nonNull)
.onEmpty(() -> 42)
.onSuccess(result -> assertEquals(100, result));
}
}

0 comments on commit c3be977

Please sign in to comment.