diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 075f411..3eaefdb 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -16,17 +16,23 @@ - - - - - + + + + + + + + + + + + + + - - - @@ -38,32 +44,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + @@ -74,9 +130,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -84,6 +174,7 @@ + @@ -93,7 +184,9 @@ - + + + @@ -104,17 +197,53 @@ + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index 9dacd2f..d337e48 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -3,8 +3,16 @@ - + + + + + + + + + + + + diff --git a/gradle.lockfile b/gradle.lockfile index 53d0ccc..4ca7a75 100644 --- a/gradle.lockfile +++ b/gradle.lockfile @@ -9,7 +9,7 @@ com.google.errorprone:error_prone_annotations:2.23.0=checkstyle com.google.guava:failureaccess:1.0.2=checkstyle com.google.guava:guava:33.0.0-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle -com.puppycrawl.tools:checkstyle:10.12.7=checkstyle +com.puppycrawl.tools:checkstyle:10.13.0=checkstyle commons-beanutils:commons-beanutils:1.9.4=checkstyle commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle diff --git a/settings.gradle b/settings.gradle index b0c6b1a..ec533da 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ plugins { - id('org.gradle.toolchains.foojay-resolver-convention') version '0.7.0' + id('org.gradle.toolchains.foojay-resolver-convention') version '0.8.0' } rootProject.name = 'maybe' @@ -7,7 +7,7 @@ rootProject.name = 'maybe' dependencyResolutionManagement { versionCatalogs { libs { - version('checkstyle', '10.12.7') + version('checkstyle', '10.13.0') version('jacoco', '0.8.11') version('junit', '5.10.1') version('sonarlint-core', '9.6.1.76766') diff --git a/src/main/java/io/github/joselion/maybe/CloseableHandler.java b/src/main/java/io/github/joselion/maybe/CloseableHandler.java index 45ae829..dddc9b9 100644 --- a/src/main/java/io/github/joselion/maybe/CloseableHandler.java +++ b/src/main/java/io/github/joselion/maybe/CloseableHandler.java @@ -16,11 +16,10 @@ * * @param The autoclosable type * @param The throwable type - * * @author Jose Luis Leon * @since v1.3.0 */ -public class CloseableHandler { +public final class CloseableHandler { private final Either value; @@ -30,7 +29,7 @@ private CloseableHandler(final Either value) { /** * Internal use method to instatiate a CloseableHandler from a given resource. - * + * * @param the type of the resource * @param the type of the error * @param resource the resource to instantiate the CloseableHandler with @@ -86,11 +85,11 @@ Optional error() { * prepared resource in the argument. The resource is automatically closed * after the operation finishes, just like a common try-with-resources * statement. - *

- * Returs a {@link SolveHandler} which allows to handle the possible error + * + *

Returs a {@link SolveHandler} which allows to handle the possible error * and return a safe value. The returned handler is {@code empty} if neither * the resource nor the error is present. - * + * * @param the type of the value returned by the {@code solver} * @param the type of exception the {@code solver} may throw * @param solver the checked function operation to solve @@ -121,11 +120,11 @@ public SolveHandler solve( * prepared resource in the argument. The resource is automatically closed * after the operation finishes, just like a common try-with-resources * statement. - *

- * Returning then an {@link EffectHandler} which allows to handle the + * + *

Returning then an {@link EffectHandler} which allows to handle the * possible error. The returned handler is {@code empty} if neither the * resource nor the error is present. - * + * * @param the type of exception the {@code effect} may throw * @param effect the checked consumer operation to execute * @return an {@link EffectHandler} with either the thrown exception to be diff --git a/src/main/java/io/github/joselion/maybe/EffectHandler.java b/src/main/java/io/github/joselion/maybe/EffectHandler.java index 010a88e..500db44 100644 --- a/src/main/java/io/github/joselion/maybe/EffectHandler.java +++ b/src/main/java/io/github/joselion/maybe/EffectHandler.java @@ -16,9 +16,8 @@ * EffectHandler is an API to handle the posible error of a {@link Maybe}'s * effect operation. It can return back to maybe to continue linking operations, * or use termimal methods to return a safe value. - * + * * @param the type of exception that the effect may throw - * * @author Jose Luis Leon * @since v0.3.2 */ @@ -43,7 +42,7 @@ static EffectHandler empty() { /** * Internal use method to instantiate an {@link EffectHandler} with an error. - * + * * @param the type of the possible exception * @param error the error to instanciate the EffectHandler * @return a EffectHandler instance with an error value @@ -101,7 +100,7 @@ public EffectHandler doOnError(final Class ofType, f /** * Run an effect if the error is present. The error is passed in the argument * of the {@code effect} consumer. - * + * * @param effect a consumer function that recieves the caught error * @return the same handler to continue chainning operations */ @@ -116,7 +115,7 @@ public EffectHandler doOnError(final Consumer effect) { * The caught error is passed to the argument of the handler consumer. If the * error is caught and handled, the operation returns an empty * {@link EffectHandler}. Otherwise, the same instance is returned. - * + * * @param the type of the error to catch * @param ofType thetype of the error to catch * @param handler a consumer function that receives the caught error @@ -198,7 +197,7 @@ public void orElse(final Consumer effect) { /** * Throws the error if present. Does nothing otherwise. - * + * * @throws E the error thrown by the {@code effect} operation */ public void orThrow() throws E { @@ -210,7 +209,7 @@ public void orThrow() throws E { /** * If an error is present, map the error to another exception and throw it. Does * nothing otherwise. - * + * * @param the new error type * @param mapper a function that maps the new exception to throw * @throws X a mapped exception diff --git a/src/main/java/io/github/joselion/maybe/Maybe.java b/src/main/java/io/github/joselion/maybe/Maybe.java index bdae4b1..786fb28 100644 --- a/src/main/java/io/github/joselion/maybe/Maybe.java +++ b/src/main/java/io/github/joselion/maybe/Maybe.java @@ -17,9 +17,8 @@ * Maybe is a monadic wrapper that may contain a value. Its rich API allows to * process throwing operations in a functional way leveraging {@link Optional} * to unwrap the possible contained value. - * + * * @param the type of the wrapped value - * * @author Jose Luis Leon * @since v0.1.0 */ @@ -43,7 +42,7 @@ Optional value() { /** * Creates a {@link Maybe} wrapper of the given value. If the value is * {@code null}, it returns a {@link #empty()}. - * + * * @param the type of the value * @param value the value be wrapped * @return a {@code Maybe} wrapping the value if it's non-{@code null}, @@ -57,21 +56,17 @@ public static Maybe of(final @Nullable T value) { * Creates a {@link Maybe} wrapper of the given optional if not empty. * Returns {@link #empty()} if the optional is empty or {@code null}. * - * @apiNote - * It is not convenient to create a {@code Maybe} wrapping an - * {@code Optional}. It'll be hard to use the value later on, and it defies - * the purpose of using {@code Maybe} in the first place (Maybe is like - * Optional, but for handling exceptions). But if you really want to do that - * for some reason, here are some workarounds: - *

-   *  Maybe.of(value).map(Optional::of);
-   *       // ^ can be an `Optional<T>` or not
-   * 
- * * @param the type of the value * @param value an optional value to create the wrapper from * @return a {@code Maybe} wrapping the value if it's not empty. * {@link #empty()} otherwise + * @apiNote It is not convenient to create a {@code Maybe} wrapping an + * {@code Optional}. It'll be hard to use the value later on, and it + * defies the purpose of using {@code Maybe} in the first place + * (Maybe is like Optional, but for handling exceptions). But if you + * really want to do that for some reason, here's a workaround where + * {@code value} can be an {@code Optional} or not: + *
{@code Maybe.of(value).map(Optional::of);}
*/ public static Maybe of(final @Nullable Optional value) { // NOSONAR if (value != null) { // NOSONAR @@ -85,7 +80,7 @@ public static Maybe of(final @Nullable Optional value) { // NOSONAR /** * Creates an empty {@link Maybe} instance. - * + * * @param the type of the value * @return an empty {@code Maybe} */ @@ -97,7 +92,7 @@ public static Maybe empty() { * Solves the value of a throwing operation using a {@link ThrowingSupplier} * expression. Returning then a {@link SolveHandler} which allows to handle * the possible error and return a safe value. - * + * * @param the type of the value returned by the {@code solver} * @param the type of exception the {@code solver} may throw * @param solver the checked supplier operation to solve @@ -119,7 +114,7 @@ public static SolveHandler from( * Runs an effect that may throw an exception using a {@link ThrowingRunnable} * expression. Returning then an {@link EffectHandler} which allows to handle * the possible error. - * + * * @param the type of exception the {@code effect} may throw * @param effect the checked runnable operation to execute * @return an {@link EffectHandler} with either the thrown exception to be @@ -141,23 +136,26 @@ public static EffectHandler from(final ThrowingRunnable * {@link SolveHandler} once applied. This is specially useful when we want * to create a {@link Maybe} from a callback argument, like on a * {@link Optional#map(Function)} for instance. - *

- * In other words, the following code - *

-   *  Optional.of(value)
-   *    .map(str -> Maybe.from(() -> decode(str)));
-   * 
- * Is equivalent to - *
-   *  Optional.of(value)
-   *    .map(Maybe.partial(this::decode));
-   * 
+ * + *

In other words, the following code: + *

{@code
+   * Optional
+   *  .of(value)
+   *  .map(str -> Maybe.from(() -> this.decode(str)));
+   * }
+ * + *

Is equivalent to: + *

{@code
+   *  Optional
+   *   .of(value)
+   *   .map(Maybe.partial(this::decode));
+   * }
* * @param the type of the value the returned function receives * @param the type of the value to be solved * @param the type of the error the solver may throw * @param solver a checked function that receives an {@code S} value and - * returns a {@code T} value + * returns a {@code T} value * @return a partially applied {@link SolveHandler}. This means, a function * that receives an {@code S} value, and produces a {@code SolveHandler} */ @@ -173,17 +171,20 @@ public static Function> partia * an {@link EffectHandler} once applied. This is specially useful when we * want to create a {@link Maybe} from a callback argument, like on a * {@link Optional#map(Function)} for instance. - *

- * In other words, the following code - *

-   *  Optional.of(value)
-   *    .map(msg -> Maybe.from(() -> sendMessage(msg)));
-   * 
- * Is equivalent to - *
-   *  Optional.of(value)
-   *    .map(Maybe.partial(this::sendMessage));
-   * 
+ * + *

In other words, the following code: + *

{@code
+   * Optional
+   *  .of(value)
+   *  .map(msg -> Maybe.from(() -> this.sendMessage(msg)));
+   * }
+ * + *

Is equivalent to: + *

{@code
+   * Optional
+   *  .of(value)
+   *  .map(Maybe.partial(this::sendMessage));
+   * }
* * @param the type of the value the returned function receives * @param the type of the error the effect may throw @@ -201,7 +202,7 @@ public static Function> partial( * Prepare an {@link AutoCloseable} resource to use in a solver or effect. * The resource will be automatically closed after the operation is finished, * just like a common try-with-resources statement. - * + * * @param the type of the resource. Extends from {@link AutoCloseable} * @param the type of error the holder may have * @param resource the {@link AutoCloseable} resource to prepare @@ -237,7 +238,7 @@ public static CloseableHandler /** * If present, maps the value to another using the provided mapper function. * Otherwise, ignores the mapper and returns {@link #empty()}. - * + * * @param the type the value will be mapped to * @param mapper the mapper function * @return a {@code Maybe} with the mapped value if present, @@ -254,10 +255,10 @@ public Maybe map(final Function mapper) { * If present, maps the value to another using the provided mapper function. * Otherwise, ignores the mapper and returns {@link #empty()}. * - * This method is similar to {@link #map(Function)}, but the mapping function is - * one whose result is already a {@code Maybe}, and if invoked, flatMap does not - * wrap it within an additional {@code Maybe}. - * + *

This method is similar to {@link #map(Function)}, but the mapping + * function is one whose result is already a {@code Maybe}, and if invoked, + * flatMap does not wrap it within an additional {@code Maybe}. + * * @param the type the value will be mapped to * @param mapper the mapper function * @return a {@code Maybe} with the mapped value if present, @@ -274,7 +275,7 @@ public Maybe flatMap(final Function> mapper * Chain the {@code Maybe} with another solver, if and only if the previous * operation was handled with no errors. The value of the previous operation * is passed as argument of the {@link ThrowingFunction}. - * + * * @param the type of value returned by the next operation * @param the type of exception the new solver may throw * @param solver a checked function that receives the current value and @@ -298,7 +299,7 @@ public SolveHandler solve( /** * Chain the {@code Maybe} with another effect, if and only if the previous * operation was handled with no errors. - * + * * @param the type of exception the new effect may throw * @param effect the checked runnable operation to execute next * @return an {@link EffectHandler} with either the thrown exception to be @@ -318,7 +319,7 @@ public EffectHandler effect(final ThrowingConsumer the type that the value will be cast to * @param type the class instance of the type to cast * @return a new {@code Maybe} with the cast value if it can be cast, @@ -332,7 +333,7 @@ public SolveHandler cast(final Class type) { /** * Checks if the {@code Maybe} has a value. - * + * * @return true if the value is present, false otherwise */ public boolean hasValue() { @@ -341,7 +342,7 @@ public boolean hasValue() { /** * Checks if the {@code Maybe} is empty. That is, when no value is present. - * + * * @return true if the value is not present, false otherwise */ public boolean isEmpty() { @@ -351,7 +352,7 @@ public boolean isEmpty() { /** * Safely unbox the value as an {@link Optional} which may or may not contain * a value. - * + * * @return an optional with the value, if preset. An empty optional otherwise */ public Optional toOptional() { @@ -365,7 +366,7 @@ public Optional toOptional() { *

  • Be an instance of {@code Maybe}
  • *
  • Contain a values equal to via {@code equals()} comparation
  • * - * + * * @param obj an object to be tested for equality * @return {@code true} if the other object is "equal to" this object, * {@code false} otherwise @@ -387,7 +388,7 @@ public boolean equals(final Object obj) { /** * Returns the hash code of the value, if present, otherwise {@code 0} (zero) * if no value is present. - * + * * @return hash code value of the present value or {@code 0} if no value is present */ @Override @@ -399,7 +400,7 @@ public int hashCode() { * Returns a non-empty string representation of this {@code Maybe} suitable * for debugging. The exact presentation format is unspecified and may vary * between implementations and versions. - * + * * @return the string representation of this instance */ @Override diff --git a/src/main/java/io/github/joselion/maybe/SolveHandler.java b/src/main/java/io/github/joselion/maybe/SolveHandler.java index 62743dc..58be97e 100644 --- a/src/main/java/io/github/joselion/maybe/SolveHandler.java +++ b/src/main/java/io/github/joselion/maybe/SolveHandler.java @@ -18,10 +18,9 @@ * SolveHandler is an API to handle the possible error of a {@link Maybe}'s * solve operation. It can return back to maybe to continue linking operations, * or use terminal methods to return a safe value. - * + * * @param the type of the value passed through the {@code Maybe} * @param the type of exception that the solve operation may throw - * * @author Jose Luis Leon * @since v0.3.2 */ @@ -34,8 +33,8 @@ private SolveHandler(final Either value) { } /** - * Internal use method to instantiate a SolveHandler of a success value - * + * Internal use method to instantiate a SolveHandler of a success value. + * * @param the type of the success value * @param the type of the possible exception * @param success the success value to instantiate the SolveHandler @@ -51,8 +50,8 @@ static SolveHandler from(final T success) { } /** - * Internal use method to instantiate a SolveHandler of an error value - * + * Internal use method to instantiate a SolveHandler of an error value. + * * @param the type of the success value * @param the type of the possible exception * @param error the error to instantiate the SolveHandler @@ -121,7 +120,7 @@ public SolveHandler doOnError(final Class ofType, /** * Run an effect if the error is present. The error is passed in the argument * of the {@code effect} consumer. - * + * * @param effect a consumer function that receives the caught error * @return the same handler to continue chainning operations */ @@ -135,7 +134,7 @@ public SolveHandler doOnError(final Consumer effect) { * Catch the error if is present and is an instance of the provided type. * Then handle the error and return a new value. The caught error is passed * in the argument of the {@code handler} function. - * + * * @param the type of the error to catch * @param ofType a class instance of the error type to catch * @param handler a function that receives the caught error and produces @@ -175,8 +174,8 @@ public SolveHandler catchError(final Function hand /** * Chain another solver covering both cases of success or error of the * previous solver in two different callbacks. - *

    - * The first callback receives the solved value, the second callback the + * + *

    The first callback receives the solved value, the second callback the * caught error. Both should solve another value of the same type {@code S}, * but only one of the callbacks is invoked. It depends on whether the * previous value was solved or not. @@ -283,9 +282,9 @@ public SolveHandler map(final Function mapper) * function. If an error is present, the {@code mapper} function is never * applied and the next handler will still contain the error. * - * This method is similar to {@link #map(Function)}, but the mapping function is - * one whose result is a {@code Maybe}, and if invoked, flatMap does not wrap - * it within an additional {@code Maybe}. + *

    This method is similar to {@link #map(Function)}, but the mapping + * function is one whose result is a {@code Maybe}, and if invoked, flatMap + * does not wrap it within an additional {@code Maybe}. * * @param the type the value is mapped to * @param mapper a function which takes the value as argument and returns a @@ -305,7 +304,7 @@ public SolveHandler flatMap(final Function the type the value will be cast to * @param type the class instance of the type to cast * @return a new handler with either the cast value or a ClassCastException @@ -317,7 +316,7 @@ public SolveHandler cast(final Class type) { /** * Returns the solved value if present. Another value otherwise. - * + * * @param fallback the value to return if the operation failed to solve * @return the solved value if present. Another value otherwise */ @@ -357,12 +356,12 @@ public T orElseGet(final Supplier supplier) { /** * Returns the solved value if present. Just {@code null} otherwise. - *

    - * It's strongly encouraged to use {@link #toOptional()} instead to better + * + *

    It's strongly encouraged to use {@link #toOptional()} instead to better * handle nullability, but if you really need to return {@code null} in case * of error, you should only use this method. - *

    - * Using {@code .orElse(null)} will result in ambiguity between + * + *

    Using {@code .orElse(null)} will result in ambiguity between * {@link #orElse(Function)} and {@link #orElse(Object)}. * * @return the solved value if present. Just {@code null} otherwise. @@ -373,7 +372,7 @@ public T orElseGet(final Supplier supplier) { /** * Returns the solved value if present. Throws the error otherwise. - * + * * @return the solved/handled value if present * @throws E the error thrown by the {@code solve} operation */ @@ -385,7 +384,7 @@ public T orThrow() throws E { /** * Returns the value solved/handled if present. Throws another error otherwise. - * + * * @param the new error type * @param mapper a function that receives the caught error and produces * another exception @@ -401,7 +400,7 @@ public T orThrow(final Function ma /** * Transforms the handler to a {@link Maybe} that contains either the * solved value or the error. - * + * * @return the solved value wrapped in a {@link Maybe} or holding the error */ public Maybe toMaybe() { @@ -415,7 +414,7 @@ public Maybe toMaybe() { * Transforms the handler to an {@link Optional}. If the value was solved, * the {@link Optional} will contain it. Returs an {@code empty} optional * otherwise. - * + * * @return the solved value wrapped in an {@link Optional} if present. An * {@code empty} optional otherwise. */ @@ -426,11 +425,11 @@ public Optional toOptional() { /** * Transforms the handler to an {@link Either}, in which the left side might * contain the error and the right side might contain the solved value. - *

    - * The benefit of transforming to {@code Either} is that its implementation + * + *

    The benefit of transforming to {@code Either} is that its implementation * ensures that only one of the two possible values is present at the same * time, never both nor none. - * + * * @return an {@code Either} with the solved value on the right side or the * error on the left */ @@ -443,13 +442,12 @@ public Either toEither() { * {@code solve} or {@code effect} operation. These operations will close the * resource upon completation. If the value was not solved, the error is * propagated to the {@link CloseableHandler}. - * + * * @param the type of the {@link AutoCloseable} resource * @param mapper a function that receives the solved value and produces an * autoclosable resource * @return a {@link CloseableHandler} with the mapped resource if the value is * present or the error otherwise. - * * @see CloseableHandler#solve(ThrowingFunction) * @see CloseableHandler#effect(ThrowingConsumer) */ diff --git a/src/main/java/io/github/joselion/maybe/helpers/Commons.java b/src/main/java/io/github/joselion/maybe/helpers/Commons.java index 4471d4d..a71568a 100644 --- a/src/main/java/io/github/joselion/maybe/helpers/Commons.java +++ b/src/main/java/io/github/joselion/maybe/helpers/Commons.java @@ -1,11 +1,21 @@ package io.github.joselion.maybe.helpers; -public class Commons { +/** + * Common helpers. + */ +public final class Commons { - Commons() { + protected Commons() { throw new UnsupportedOperationException("Cannot instantiate a helper class"); } + /** + * Casts a value to the generic type {@code T} of the method. + * + * @param the type to cast the value + * @param value the value to cast + * @return the {@code value} cast to {@code T} type + */ @SuppressWarnings("unchecked") public static T cast(final Object value) { return (T) value; diff --git a/src/main/java/io/github/joselion/maybe/util/Either.java b/src/main/java/io/github/joselion/maybe/util/Either.java index 1e197ef..cc630db 100644 --- a/src/main/java/io/github/joselion/maybe/util/Either.java +++ b/src/main/java/io/github/joselion/maybe/util/Either.java @@ -13,13 +13,12 @@ * Either is a monadic wrapper that contains one of two possible values which * are represented as {@code Left} or {@code Right}. the values can be of * different types, and the API allows to safely transform an unwrap the value. - * - * The sealed interface implementation ensures only one of the two can be + * + *

    The sealed interface implementation ensures only one of the two can be * present at the same time. - * + * * @param the {@code Left} data type * @param the {@code Right} data type - * * @author Jose Luis Leon * @since v3.0.0 */ @@ -167,10 +166,10 @@ default Either map( /** * Map the {@code Left} value to another if present. Does nothing otherwise. - * - * This method is similar to {@link #mapLeft(Function)}, but the - * mapping function can return another {@code Either} without wrapping the - * left value within an additional {@code Either}. + * + *

    This method is similar to {@link #mapLeft(Function)}, but the mapping + * function can return another {@code Either} without wrapping the left value + * within an additional {@code Either}. * * @param the type the left value will be mapped to * @param mapper a function that receives the left value and returns an {@code Either} @@ -184,10 +183,10 @@ default Either flatMapLeft(final FunctionThis method is similar to {@link #mapRight(Function)}, but the mapping + * function can return another {@code Either} without wrapping the right + * value within an additional {@code Either}. * * @param the type the right value will be mapped to * @param mapper a function that receives the right value and returns an {@code Either} @@ -271,7 +270,7 @@ default R rightOrElse(final R fallback) { * @return an {@code Optional} instance */ default Optional leftToOptional() { - return Optional.ofNullable(leftOrNull()); + return Optional.ofNullable(this.leftOrNull()); } /** @@ -281,11 +280,11 @@ default Optional leftToOptional() { * @return an {@code Optional} instance */ default Optional rightToOptional() { - return Optional.ofNullable(rightOrNull()); + return Optional.ofNullable(this.rightOrNull()); } /** - * The {@code Left} implementation of {@link Either} + * The {@code Left} implementation of {@link Either}. * * @param the {@code Left} data type * @param the {@code Right} data type @@ -339,7 +338,7 @@ public String toString() { } /** - * The {@code Right} implementation of {@link Either} + * The {@code Right} implementation of {@link Either}. * * @param the {@code Left} data type * @param the {@code Right} data type diff --git a/src/main/java/io/github/joselion/maybe/util/function/ThrowingConsumer.java b/src/main/java/io/github/joselion/maybe/util/function/ThrowingConsumer.java index a13d296..ab38db6 100644 --- a/src/main/java/io/github/joselion/maybe/util/function/ThrowingConsumer.java +++ b/src/main/java/io/github/joselion/maybe/util/function/ThrowingConsumer.java @@ -3,10 +3,10 @@ /** * The same as {@link java.util.function.Consumer Consumer}, but the lambda * expression throws an {@code E} checked exception. - * - * This is a functional interface whose functional method is + * + *

    This is a functional interface whose functional method is * {@link #accept(Object)} - * + * * @param the type of argument passed to the function * @param the type of exception that the function throws * @author Jose Luis Leon @@ -17,7 +17,7 @@ public interface ThrowingConsumer { /** * Accepts this function with the given argument, or throws an exception. - * + * * @param t the consumer argument * @throws E which extends from {@link Throwable} */ diff --git a/src/main/java/io/github/joselion/maybe/util/function/ThrowingFunction.java b/src/main/java/io/github/joselion/maybe/util/function/ThrowingFunction.java index d0b0759..6ec6c84 100644 --- a/src/main/java/io/github/joselion/maybe/util/function/ThrowingFunction.java +++ b/src/main/java/io/github/joselion/maybe/util/function/ThrowingFunction.java @@ -3,10 +3,10 @@ /** * The same as {@link java.util.function.Function Function}, but the lambda * expression throws an {@code E} checked exception. - * - * This is a functional interface whose functional method is + * + *

    This is a functional interface whose functional method is * {@link #apply(Object)} - * + * * @param the type of argument passed to the function * @param the type of results returned by the function * @param the type of exception that the function throws @@ -18,7 +18,7 @@ public interface ThrowingFunction { /** * Applies this function to the given argument, or throws an exception. - * + * * @param t the function argument * @return the function result * @throws E which extends from {@link Throwable} @@ -33,6 +33,6 @@ public interface ThrowingFunction { * @return a function that always returns its input argument */ static ThrowingFunction identity() { - return t -> t; + return t -> t; } } diff --git a/src/main/java/io/github/joselion/maybe/util/function/ThrowingRunnable.java b/src/main/java/io/github/joselion/maybe/util/function/ThrowingRunnable.java index d6116a2..1b18a4c 100644 --- a/src/main/java/io/github/joselion/maybe/util/function/ThrowingRunnable.java +++ b/src/main/java/io/github/joselion/maybe/util/function/ThrowingRunnable.java @@ -3,10 +3,10 @@ /** * The same as {@link java.lang.Runnable Runnable}, but the lambda expression * throws an {@code E} exception. - * - * This is a functional interface whose functional method is + * + *

    This is a functional interface whose functional method is * {@link #run()} - * + * * @param the type of checked exception that the runnable throws * @author Jose Luis Leon * @since v0.1.0 @@ -16,7 +16,7 @@ public interface ThrowingRunnable { /** * Runs the operation, or throws an exception. - * + * * @throws E which extends from {@link Throwable} */ void run() throws E; diff --git a/src/main/java/io/github/joselion/maybe/util/function/ThrowingSupplier.java b/src/main/java/io/github/joselion/maybe/util/function/ThrowingSupplier.java index 6dd2ed5..1306863 100644 --- a/src/main/java/io/github/joselion/maybe/util/function/ThrowingSupplier.java +++ b/src/main/java/io/github/joselion/maybe/util/function/ThrowingSupplier.java @@ -3,10 +3,10 @@ /** * The same as {@link java.util.function.Supplier Supplier}, but the lambda * expression throws an {@code E} exception. - * - * This is a functional interface whose functional method is + * + *

    This is a functional interface whose functional method is * {@link #get()} - * + * * @param the type of results supplied by the supplier * @param the type of checked exception that the supplier throws * @author Jose Luis Leon @@ -17,7 +17,7 @@ public interface ThrowingSupplier { /** * Gets a result or throws an exception. - * + * * @return a result * @throws E which extends from {@link Throwable} */ diff --git a/src/main/java17/io/github/joselion/maybe/Maybe.java b/src/main/java17/io/github/joselion/maybe/Maybe.java index 63b5d55..1366615 100644 --- a/src/main/java17/io/github/joselion/maybe/Maybe.java +++ b/src/main/java17/io/github/joselion/maybe/Maybe.java @@ -17,9 +17,8 @@ * Maybe is a monadic wrapper that may contain a value. Its rich API allows to * process throwing operations in a functional way leveraging {@link Optional} * to unwrap the possible contained value. - * + * * @param the type of the wrapped value - * * @author Jose Luis Leon * @since v0.1.0 */ @@ -43,7 +42,7 @@ Optional value() { /** * Creates a {@link Maybe} wrapper of the given value. If the value is * {@code null}, it returns a {@link #empty()}. - * + * * @param the type of the value * @param value the value be wrapped * @return a {@code Maybe} wrapping the value if it's non-{@code null}, @@ -57,16 +56,13 @@ public static Maybe of(final @Nullable T value) { * Creates a {@link Maybe} wrapper of the given optional if not empty. * Returns {@link #empty()} if the optional is empty or {@code null}. * - * @apiNote - * It is not convenient to create a {@code Maybe} wrapping an - * {@code Optional}. It'll be hard to use the value later on, and it defies - * the purpose of using {@code Maybe} in the first place (Maybe is like - * Optional, but for handling exceptions). But if you really want to do that - * for some reason, here are some workarounds: - *

    -   *  Maybe.of(value).map(Optional::of);
    -   *       // ^ can be an `Optional<T>` or not
    -   * 
    + * @apiNote It is not convenient to create a {@code Maybe} wrapping an + * {@code Optional}. It'll be hard to use the value later on, and it + * defies the purpose of using {@code Maybe} in the first place + * (Maybe is like Optional, but for handling exceptions). But if you + * really want to do that for some reason, here's a workaround where + * {@code value} can be an {@code Optional} or not: + *
    {@code Maybe.of(value).map(Optional::of);}
    * * @param the type of the value * @param value an optional value to create the wrapper from @@ -85,7 +81,7 @@ public static Maybe of(final @Nullable Optional value) { // NOSONAR /** * Creates an empty {@link Maybe} instance. - * + * * @param the type of the value * @return an empty {@code Maybe} */ @@ -97,7 +93,7 @@ public static Maybe empty() { * Solves the value of a throwing operation using a {@link ThrowingSupplier} * expression. Returning then a {@link SolveHandler} which allows to handle * the possible error and return a safe value. - * + * * @param the type of the value returned by the {@code solver} * @param the type of exception the {@code solver} may throw * @param solver the checked supplier operation to solve @@ -119,7 +115,7 @@ public static SolveHandler from( * Runs an effect that may throw an exception using a {@link ThrowingRunnable} * expression. Returning then an {@link EffectHandler} which allows to handle * the possible error. - * + * * @param the type of exception the {@code effect} may throw * @param effect the checked runnable operation to execute * @return an {@link EffectHandler} with either the thrown exception to be @@ -141,17 +137,20 @@ public static EffectHandler from(final ThrowingRunnable * {@link SolveHandler} once applied. This is specially useful when we want * to create a {@link Maybe} from a callback argument, like on a * {@link Optional#map(Function)} for instance. - *

    - * In other words, the following code - *

    -   *  Optional.of(value)
    -   *    .map(str -> Maybe.from(() -> decode(str)));
    -   * 
    - * Is equivalent to - *
    -   *  Optional.of(value)
    -   *    .map(Maybe.partial(this::decode));
    -   * 
    + * + *

    In other words, the following code: + *

    {@code
    +   * Optional
    +   *  .of(value)
    +   *  .map(str -> Maybe.from(() -> decode(str)));
    +   * }
    + * + *

    Is equivalent to: + *

    {@code
    +   * Optional
    +   *  .of(value)
    +   *  .map(Maybe.partial(this::decode));
    +   * }
    * * @param the type of the value the returned function receives * @param the type of the value to be solved @@ -173,17 +172,20 @@ public static Function> partia * an {@link EffectHandler} once applied. This is specially useful when we * want to create a {@link Maybe} from a callback argument, like on a * {@link Optional#map(Function)} for instance. - *

    - * In other words, the following code - *

    -   *  Optional.of(value)
    -   *    .map(msg -> Maybe.from(() -> sendMessage(msg)));
    -   * 
    - * Is equivalent to - *
    -   *  Optional.of(value)
    -   *    .map(Maybe.partial(this::sendMessage));
    -   * 
    + * + *

    In other words, the following code: + *

    {@code
    +   * Optional
    +   *  .of(value)
    +   *  .map(msg -> Maybe.from(() -> sendMessage(msg)));
    +   * }
    + * + *

    Is equivalent to: + *

    {@code
    +   * Optional
    +   *  .of(value)
    +   *  .map(Maybe.partial(this::sendMessage));
    +   * }
    * * @param the type of the value the returned function receives * @param the type of the error the effect may throw @@ -201,7 +203,7 @@ public static Function> partial( * Prepare an {@link AutoCloseable} resource to use in a solver or effect. * The resource will be automatically closed after the operation is finished, * just like a common try-with-resources statement. - * + * * @param the type of the resource. Extends from {@link AutoCloseable} * @param the type of error the holder may have * @param resource the {@link AutoCloseable} resource to prepare @@ -237,7 +239,7 @@ public static CloseableHandler /** * If present, maps the value to another using the provided mapper function. * Otherwise, ignores the mapper and returns {@link #empty()}. - * + * * @param the type the value will be mapped to * @param mapper the mapper function * @return a {@code Maybe} with the mapped value if present, @@ -253,11 +255,11 @@ public Maybe map(final Function mapper) { /** * If present, maps the value to another using the provided mapper function. * Otherwise, ignores the mapper and returns {@link #empty()}. - * - * This method is similar to {@link #map(Function)}, but the mapping function is - * one whose result is already a {@code Maybe}, and if invoked, flatMap does not - * wrap it within an additional {@code Maybe}. - * + * + *

    This method is similar to {@link #map(Function)}, but the mapping + * function is one whose result is already a {@code Maybe}, and if invoked, + * flatMap does not wrap it within an additional {@code Maybe}. + * * @param the type the value will be mapped to * @param mapper the mapper function * @return a {@code Maybe} with the mapped value if present, @@ -274,7 +276,7 @@ public Maybe flatMap(final Function> mapper * Chain the {@code Maybe} with another solver, if and only if the previous * operation was handled with no errors. The value of the previous operation * is passed as argument of the {@link ThrowingFunction}. - * + * * @param the type of value returned by the next operation * @param the type of exception the new solver may throw * @param solver a checked function that receives the current value and @@ -298,7 +300,7 @@ public SolveHandler solve( /** * Chain the {@code Maybe} with another effect, if and only if the previous * operation was handled with no errors. - * + * * @param the type of exception the new effect may throw * @param effect the checked runnable operation to execute next * @return an {@link EffectHandler} with either the thrown exception to be @@ -318,7 +320,7 @@ public EffectHandler effect(final ThrowingConsumer the type that the value will be cast to * @param type the class instance of the type to cast * @return a new {@code Maybe} with the cast value if it can be cast, @@ -332,7 +334,7 @@ public SolveHandler cast(final Class type) { /** * Checks if the {@code Maybe} has a value. - * + * * @return true if the value is present, false otherwise */ public boolean hasValue() { @@ -341,7 +343,7 @@ public boolean hasValue() { /** * Checks if the {@code Maybe} is empty. That is, when no value is present. - * + * * @return true if the value is not present, false otherwise */ public boolean isEmpty() { @@ -351,7 +353,7 @@ public boolean isEmpty() { /** * Safely unbox the value as an {@link Optional} which may or may not contain * a value. - * + * * @return an optional with the value, if preset. An empty optional otherwise */ public Optional toOptional() { @@ -365,7 +367,7 @@ public Optional toOptional() { *

  • Be an instance of {@code Maybe}
  • *
  • Contain a values equal to via {@code equals()} comparation
  • * - * + * * @param obj an object to be tested for equality * @return {@code true} if the other object is "equal to" this object, * {@code false} otherwise @@ -386,7 +388,7 @@ public boolean equals(final Object obj) { /** * Returns the hash code of the value, if present, otherwise {@code 0} (zero) * if no value is present. - * + * * @return hash code value of the present value or {@code 0} if no value is present */ @Override @@ -398,7 +400,7 @@ public int hashCode() { * Returns a non-empty string representation of this {@code Maybe} suitable * for debugging. The exact presentation format is unspecified and may vary * between implementations and versions. - * + * * @return the string representation of this instance */ @Override diff --git a/src/main/java17/io/github/joselion/maybe/util/Either.java b/src/main/java17/io/github/joselion/maybe/util/Either.java index 13498fe..400f852 100644 --- a/src/main/java17/io/github/joselion/maybe/util/Either.java +++ b/src/main/java17/io/github/joselion/maybe/util/Either.java @@ -13,13 +13,12 @@ * Either is a monadic wrapper that contains one of two possible values which * are represented as {@code Left} or {@code Right}. the values can be of * different types, and the API allows to safely transform an unwrap the value. - * - * The sealed interface implementation ensures only one of the two can be + * + *

    The sealed interface implementation ensures only one of the two can be * present at the same time. - * + * * @param the {@code Left} data type * @param the {@code Right} data type - * * @author Jose Luis Leon * @since v3.0.0 */ @@ -167,10 +166,10 @@ default Either map( /** * Map the {@code Left} value to another if present. Does nothing otherwise. - * - * This method is similar to {@link #mapLeft(Function)}, but the - * mapping function can return another {@code Either} without wrapping the - * left value within an additional {@code Either}. + * + *

    This method is similar to {@link #mapLeft(Function)}, but the mapping + * function can return another {@code Either} without wrapping the left value + * within an additional {@code Either}. * * @param the type the left value will be mapped to * @param mapper a function that receives the left value and returns an {@code Either} @@ -184,10 +183,10 @@ default Either flatMapLeft(final FunctionThis method is similar to {@link #mapRight(Function)}, but the mapping + * function can return another {@code Either} without wrapping the right + * value within an additional {@code Either}. * * @param the type the right value will be mapped to * @param mapper a function that receives the right value and returns an {@code Either} @@ -271,7 +270,7 @@ default R rightOrElse(final R fallback) { * @return an {@code Optional} instance */ default Optional leftToOptional() { - return Optional.ofNullable(leftOrNull()); + return Optional.ofNullable(this.leftOrNull()); } /** @@ -281,11 +280,11 @@ default Optional leftToOptional() { * @return an {@code Optional} instance */ default Optional rightToOptional() { - return Optional.ofNullable(rightOrNull()); + return Optional.ofNullable(this.rightOrNull()); } /** - * The {@code Left} implementation of {@link Either} + * The {@code Left} implementation of {@link Either}. * * @param the {@code Left} data type * @param the {@code Right} data type @@ -295,8 +294,6 @@ record Left(L value) implements Either { /** * Compact constructor to validate the value is not null. - * - * @param value the value of the instance */ public Left { Objects.requireNonNull(value, "An Either cannot be created with a null value"); @@ -332,7 +329,7 @@ public String toString() { } /** - * The {@code Right} implementation of {@link Either} + * The {@code Right} implementation of {@link Either}. * * @param the {@code Left} data type * @param the {@code Right} data type @@ -342,8 +339,6 @@ record Right(R value) implements Either { /** * Compact constructor to validate the value is not null. - * - * @param value the value of the instance */ public Right { Objects.requireNonNull(value, "An Either cannot be created with a null value"); diff --git a/src/test/java/io/github/joselion/maybe/CloseableHandlerTests.java b/src/test/java/io/github/joselion/maybe/CloseableHandlerTest.java similarity index 99% rename from src/test/java/io/github/joselion/maybe/CloseableHandlerTests.java rename to src/test/java/io/github/joselion/maybe/CloseableHandlerTest.java index a104b2a..f18344f 100644 --- a/src/test/java/io/github/joselion/maybe/CloseableHandlerTests.java +++ b/src/test/java/io/github/joselion/maybe/CloseableHandlerTest.java @@ -18,7 +18,7 @@ import io.github.joselion.testing.Spy; import io.github.joselion.testing.UnitTest; -@UnitTest class CloseableHandlerTests { +@UnitTest class CloseableHandlerTest { private static final String FILE_PATH = "./src/test/resources/readTest.txt"; diff --git a/src/test/java/io/github/joselion/maybe/EffectHandlerTests.java b/src/test/java/io/github/joselion/maybe/EffectHandlerTest.java similarity index 99% rename from src/test/java/io/github/joselion/maybe/EffectHandlerTests.java rename to src/test/java/io/github/joselion/maybe/EffectHandlerTest.java index 4a31a0b..560c8ef 100644 --- a/src/test/java/io/github/joselion/maybe/EffectHandlerTests.java +++ b/src/test/java/io/github/joselion/maybe/EffectHandlerTest.java @@ -20,7 +20,7 @@ import io.github.joselion.testing.Spy; import io.github.joselion.testing.UnitTest; -@UnitTest class EffectHandlerTests { +@UnitTest class EffectHandlerTest { private static final FileSystemException FAIL_EXCEPTION = new FileSystemException("FAIL"); diff --git a/src/test/java/io/github/joselion/maybe/MaybeTests.java b/src/test/java/io/github/joselion/maybe/MaybeTest.java similarity index 99% rename from src/test/java/io/github/joselion/maybe/MaybeTests.java rename to src/test/java/io/github/joselion/maybe/MaybeTest.java index 38ae5e1..b8d7154 100644 --- a/src/test/java/io/github/joselion/maybe/MaybeTests.java +++ b/src/test/java/io/github/joselion/maybe/MaybeTest.java @@ -26,7 +26,7 @@ import io.github.joselion.testing.Spy; import io.github.joselion.testing.UnitTest; -@UnitTest class MaybeTests { +@UnitTest class MaybeTest { private static final String OK = "OK"; diff --git a/src/test/java/io/github/joselion/maybe/SolveHandlerTests.java b/src/test/java/io/github/joselion/maybe/SolveHandlerTest.java similarity index 99% rename from src/test/java/io/github/joselion/maybe/SolveHandlerTests.java rename to src/test/java/io/github/joselion/maybe/SolveHandlerTest.java index 2fb0bc6..db570c2 100644 --- a/src/test/java/io/github/joselion/maybe/SolveHandlerTests.java +++ b/src/test/java/io/github/joselion/maybe/SolveHandlerTest.java @@ -25,7 +25,7 @@ import io.github.joselion.testing.Spy; import io.github.joselion.testing.UnitTest; -@UnitTest class SolveHandlerTests { +@UnitTest class SolveHandlerTest { private static final String OK = "OK"; diff --git a/src/test/java/io/github/joselion/maybe/helpers/CommonTests.java b/src/test/java/io/github/joselion/maybe/helpers/CommonTest.java similarity index 97% rename from src/test/java/io/github/joselion/maybe/helpers/CommonTests.java rename to src/test/java/io/github/joselion/maybe/helpers/CommonTest.java index 274920a..309b1a9 100644 --- a/src/test/java/io/github/joselion/maybe/helpers/CommonTests.java +++ b/src/test/java/io/github/joselion/maybe/helpers/CommonTest.java @@ -8,7 +8,7 @@ import io.github.joselion.testing.UnitTest; -@UnitTest class CommonTests { +@UnitTest class CommonTest { @Nested class helper { @Nested class when_the_class_is_instantiated { diff --git a/src/test/java/io/github/joselion/maybe/util/EitherTests.java b/src/test/java/io/github/joselion/maybe/util/EitherTest.java similarity index 99% rename from src/test/java/io/github/joselion/maybe/util/EitherTests.java rename to src/test/java/io/github/joselion/maybe/util/EitherTest.java index 15557dd..6011d9e 100644 --- a/src/test/java/io/github/joselion/maybe/util/EitherTests.java +++ b/src/test/java/io/github/joselion/maybe/util/EitherTest.java @@ -13,7 +13,7 @@ import io.github.joselion.testing.Spy; import io.github.joselion.testing.UnitTest; -@UnitTest class EitherTests { +@UnitTest class EitherTest { @Nested class ofLeft { @Nested class when_the_value_is_not_null { diff --git a/src/test/java/io/github/joselion/testing/Spy.java b/src/test/java/io/github/joselion/testing/Spy.java index fc96731..c763e10 100644 --- a/src/test/java/io/github/joselion/testing/Spy.java +++ b/src/test/java/io/github/joselion/testing/Spy.java @@ -1,36 +1,74 @@ package io.github.joselion.testing; import static org.mockito.AdditionalAnswers.delegatesTo; +import static org.mockito.Mockito.mock; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -import org.mockito.Mockito; - import io.github.joselion.maybe.helpers.Commons; -public class Spy { +public final class Spy { + + private Spy() { + throw new UnsupportedOperationException("Spy is a helper class"); + } + /** + * Creates a spy of a generic {@code T} lambda expression. + * + * @param the type of the lambda expression + * @param lambda the lambda expression to spy on + * @return a spy of the provided lambda expression + */ public static T lambda(final T lambda) { final var interfaces = lambda.getClass().getInterfaces(); final var toMock = Commons.>cast(interfaces[0]); - return Mockito.mock(toMock, delegatesTo(lambda)); + return mock(toMock, delegatesTo(lambda)); } + /** + * Creates a spy of a generic {@link Function} interface. + * + * @param the type of the input to the function + * @param the type of the result of the function + * @param function the function to spy on + * @return a spy of the provided function + */ public static Function function(final Function function) { return lambda(function); } + /** + * Creates a spy of a generic {@link Consumer} interface. + * + * @param the type of the input to the operation + * @param consumer the consumer to spy on + * @return a spy of the provided consumer + */ public static Consumer consumer(final Consumer consumer) { return lambda(consumer); } + /** + * Creates a spy of a generic {@link Supplier} interface. + * + * @param the type of results supplied by this supplier + * @param supplier the supplier to spy on + * @return a spy of the provided supplier + */ public static Supplier supplier(final Supplier supplier) { return lambda(supplier); } + /** + * Creates a spy of a generic {@link Runnable} interface. + * + * @param runnable the runneble to spy on + * @return a spy of the provided runnable + */ public static Runnable runnable(final Runnable runnable) { return lambda(runnable); }