Bump kemitix-maven-tiles to 3.0.0 and kemitix-checkstye to 5.5.0 (#181)
* Bump kemitix-maven-tiles to 3.0.0 * Bump kemitix-maven-tiles to 3.0.1 * Bump kemitix-checkstyle to 5.5.0 * Docs updates - more to come * Checkstyle and PMD compliance updates * result: map on Success should become Error on exception * README: reformat in markdown
This commit is contained in:
parent
ee97d6065f
commit
5737e11395
28 changed files with 1149 additions and 1341 deletions
994
README.md
Normal file
994
README.md
Normal file
|
@ -0,0 +1,994 @@
|
|||
# Mon
|
||||
|
||||
Wrapper, TypeAlias, Result, Lazy, Maybe and combinators for Java.
|
||||
|
||||
![GitHub release (latest by date)](
|
||||
https://img.shields.io/github/v/release/kemitix/mon?style=for-the-badge)
|
||||
![GitHub Release Date](
|
||||
https://img.shields.io/github/release-date/kemitix/mon?style=for-the-badge)
|
||||
|
||||
[![Nexus](
|
||||
https://img.shields.io/nexus/r/https/oss.sonatype.org/net.kemitix/mon.svg?style=for-the-badge)](
|
||||
https://oss.sonatype.org/content/repositories/releases/net/kemitix/mon/)
|
||||
[![Maven-Central](
|
||||
https://img.shields.io/maven-central/v/net.kemitix/mon.svg?style=for-the-badge)](
|
||||
https://search.maven.org/artifact/net.kemitix/mon)
|
||||
|
||||
- [Maven Usage](#Maven-Usage)
|
||||
- [Wrapper](#Wrapper)
|
||||
- [TypeAlias](#TypeAlias)
|
||||
- [Maybe](#Maybe)
|
||||
- [Result](#Result)
|
||||
- [Tree](#Tree)
|
||||
|
||||
---
|
||||
## Maven Usage
|
||||
|
||||
``` xml
|
||||
<dependency>
|
||||
<groupId>net.kemitix</groupId>
|
||||
<artifactId>mon</artifactId>
|
||||
<version>${mon.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
---
|
||||
## Wrapper
|
||||
|
||||
A simple `@FunctionalInterface` that contains a value. Can be used to implement
|
||||
a form of type-alias in Java.
|
||||
|
||||
In Haskell, it is possible to create an alias for a Type, and to then use
|
||||
that alias with the same behaviour as the original, except that the compiler
|
||||
doesn't treat the alias as the same Type and will generate compiler errors
|
||||
if you try to use them together. e.g.:
|
||||
|
||||
``` haskell
|
||||
newtype PhoneNumber = PhoneNumber String
|
||||
newtype Name = Name String
|
||||
newtype PhoneBookEntry = PhoneBookEntry (Name, PhoneNumber)
|
||||
newtype PhoneBook = PhoneBook [PhoneBookEntry]
|
||||
```
|
||||
|
||||
In Java, we don't have the ability to have that true alias, so `Wrapper` simply
|
||||
wraps the value within a new type. It's as close as I could get to a Haskell
|
||||
type alias in Java.
|
||||
|
||||
The benefits of using `Wrapper` in this way are:
|
||||
|
||||
- encapsulation of the wrapped type when passing references through code
|
||||
that doesn't need to access the actual value, but only to pass it on
|
||||
- type-safe parameters where you would otherwise be passing generic `String`s,
|
||||
`Integer`s, `List`s, or other general classes
|
||||
- less verbose than implementing your own
|
||||
|
||||
### Example
|
||||
|
||||
``` java
|
||||
interface PhoneNumber extends Wrapper<String> {}
|
||||
|
||||
PhoneNumber pn = () -> "01234 567890";
|
||||
String v = pn.value();
|
||||
```
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `T value()`
|
||||
|
||||
Returns the value in the `Wrapper`.
|
||||
|
||||
---
|
||||
## TypeAlias
|
||||
|
||||
This was a precursor to `Wrapper` and should be considered deprecated. It is
|
||||
also a form of wrapper, but is also a Monadic wrapper, unlike `Wrapper`.
|
||||
|
||||
### Example
|
||||
|
||||
``` java
|
||||
class PhoneNumber extends TypeAlias<String> {
|
||||
private PhoneNumber(final String value) {
|
||||
super(value);
|
||||
}
|
||||
public static PhoneNumber of(final String phoneNumber) {
|
||||
return new PhoneNumber(phoneNumber);
|
||||
}
|
||||
}
|
||||
|
||||
PhoneNumber pn = PhoneNumber.of("01234 567890");
|
||||
String v = pn.getValue();
|
||||
```
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `final <R> R map(final Function<T, R> f)`
|
||||
|
||||
Map the `TypeAlias` into another value.
|
||||
|
||||
``` java
|
||||
StudentId studentId = StudentId.of(123);
|
||||
String idString = studentId.map(id -> String.valueOf(id));
|
||||
|
||||
class StudentId extends TypeAlias<Integer> {
|
||||
private StudentId(Integer value) {
|
||||
super(value);
|
||||
}
|
||||
static StudentId of(Integer id) {
|
||||
return new StudentId(id);
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
#### `final <R, U extends TypeAlias<R>> U flatMap(final Function<T, U> f)`
|
||||
|
||||
Map the `TypeAlias` into another `TypeAlias`.
|
||||
|
||||
``` java
|
||||
StudentId studentId = StudentId.of(123);
|
||||
StudentName studentName = studentId.flatMap(id -> getStudentName(id));
|
||||
|
||||
class StudentName extends TypeAlias<String> {
|
||||
private StudentName(String value) {
|
||||
super(value);
|
||||
}
|
||||
static StudentName of(final String name) {
|
||||
return new StudentName(name);
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
#### `T getValue()`
|
||||
|
||||
Get the value of the `TypeAlias`.
|
||||
|
||||
``` java
|
||||
String name = studentName.getValue();
|
||||
```
|
||||
---
|
||||
## Maybe
|
||||
|
||||
Allows specifying that a value may or may not be present. Similar to
|
||||
`Optional`. `Maybe` provides additional methods that `Optional` doesn't (as of
|
||||
Java 8): `isNothing()`, `stream()`, `ifNothing()` and `match()`. `Maybe` does
|
||||
not have a `get()` method.
|
||||
|
||||
`Maybe` is a Monad.
|
||||
|
||||
Unlike `Optional`, when a `map()` results in a `null`, the `Maybe` will
|
||||
continue to be a `Just` (i.e. have a value - that value is `null`). `Optional`
|
||||
would switch to being empty.
|
||||
|
||||
### Example
|
||||
|
||||
``` java
|
||||
import net.kemitix.mon.maybe.Maybe;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
class MaybeExample {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Maybe.just(countArgs(args))
|
||||
.filter(isEven())
|
||||
.map(validMessage())
|
||||
.match(
|
||||
just -> System.out.println(just),
|
||||
() -> System.out.println("Not an valid value")
|
||||
);
|
||||
}
|
||||
|
||||
private static Function<Integer, String> validMessage() {
|
||||
return v -> String.format("Value %d is even", v);
|
||||
}
|
||||
|
||||
private static Predicate<Integer> isEven() {
|
||||
return v -> v % 2 == 0;
|
||||
}
|
||||
|
||||
private static Integer countArgs(String[] args) {
|
||||
return args.length;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In the above example, the number of command line arguments are counted, if
|
||||
there are an even number of them then a message is created and printed by
|
||||
the `Consumer` parameter in the `match` call. If there is an odd number of
|
||||
arguments, then the filter will return `Maybe.nothing()`, meaning that the
|
||||
`nothing` drops straight through the `map` and triggers the `Runnable` parameter
|
||||
in the `match` call.
|
||||
|
||||
### Static Constructors
|
||||
|
||||
#### `static <T> Maybe<T> maybe(T value)`
|
||||
|
||||
Create a Maybe for the value that may or may not be present.
|
||||
|
||||
Where the value is `null`, that is taken as not being present.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> just = Maybe.maybe(1);
|
||||
Maybe<Integer> nothing = Maybe.maybe(null);
|
||||
```
|
||||
---
|
||||
#### `static <T> Maybe<T> just(T value)`
|
||||
|
||||
Create a `Maybe` for the value that is present.
|
||||
|
||||
The `value` must not be `null` or a `NullPointerException` will be thrown.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> just = Maybe.just(1);
|
||||
```
|
||||
---
|
||||
#### `static <T> Maybe<T> nothing()`
|
||||
|
||||
Create a `Maybe` for a lack of a value.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> nothing = Maybe.nothing();
|
||||
```
|
||||
---
|
||||
#### `static <T> Maybe<T> findFirst(Stream<T> stream)`
|
||||
|
||||
Creates a `Maybe` from the first item in the stream, or nothing if the stream
|
||||
is empty.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> just3 = Maybe.findFirst(Stream.of(3, 4, 2, 4));
|
||||
Maybe<Integer> nothing = Maybe.findFirst(Stream.empty());
|
||||
```
|
||||
---
|
||||
### Instance Methods
|
||||
|
||||
#### `Maybe<T> filter(Predicate<T> predicate)`
|
||||
|
||||
Filter a Maybe by the predicate, replacing with Nothing when it fails.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> maybe = Maybe.maybe(getValue())
|
||||
.filter(v -> v % 2 == 0);
|
||||
```
|
||||
---
|
||||
#### `<R> Maybe<R> map(Function<T,R> f)`
|
||||
|
||||
Applies the function to the value within the `Maybe`, returning the result
|
||||
within another `Maybe`.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> maybe = Maybe.maybe(getValue())
|
||||
.map(v -> v * 100);
|
||||
```
|
||||
---
|
||||
#### `<R> Maybe<R> flatMap(Function<T,Maybe<R>> f)`
|
||||
|
||||
Applies the function to the value within the `Maybe`, resulting in another
|
||||
`Maybe`, then flattens the resulting `Maybe<Maybe<T>>` into `Maybe<T>`.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> maybe = Maybe.maybe(getValue())
|
||||
.flatMap(v -> Maybe.maybe(getValueFor(v)));
|
||||
```
|
||||
---
|
||||
#### `void match(Consumer<T> just, Runnable nothing)`
|
||||
|
||||
Matches the `Maybe`, either to `just` or `nothing`, and performs either the
|
||||
`Consumer`, for a `Just` value, or the `Runnable` for a `Nothing` value.
|
||||
|
||||
``` java
|
||||
Maybe.maybe(getValue())
|
||||
.match(
|
||||
just -> workWithValue(just),
|
||||
() -> nothingToWorkWith()
|
||||
);
|
||||
```
|
||||
---
|
||||
#### `<R> R matchValue(Function<T, R> justMatcher, Supplier<R> nothingMatcher)`
|
||||
|
||||
Matches the `Maybe`, either `Just` or `Nothing`, and performs either the
|
||||
`Function`, for a `Just` value, or the `Supplier` for a `Nothing` value,
|
||||
returning the result.
|
||||
|
||||
``` java
|
||||
String value = Maybe.maybe(getValue())
|
||||
.matchValue(
|
||||
just -> Integer.toString(just),
|
||||
() -> "nothing"
|
||||
);
|
||||
```
|
||||
---
|
||||
#### `T orElse(T otherValue)`
|
||||
|
||||
A value to use when the `Maybe` is `Nothing`.
|
||||
|
||||
``` java
|
||||
Integer value = Maybe.maybe(getValue())
|
||||
.orElse(1);
|
||||
```
|
||||
---
|
||||
#### `T orElseGet(Supplier<T> otherValueSupplier)`
|
||||
|
||||
Provide a value to use when the `Maybe` is `Nothing`.
|
||||
|
||||
``` java
|
||||
Integer value = Maybe.maybe(getValue())
|
||||
.orElseGet(() -> getDefaultValue());
|
||||
```
|
||||
---
|
||||
#### `T or(Supplier<Maybe<T> alternative)`
|
||||
|
||||
Provide an alternative `Maybe` to use when the `Maybe` is `Nothing`.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> value = Maybe.maybe(getValue())
|
||||
.or(() -> Maybe.just(defaultValue));
|
||||
```
|
||||
---
|
||||
#### `void orElseThrow(Supplier<Exception> error)`
|
||||
|
||||
Throw the exception if the `Maybe` is `Nothing`.
|
||||
|
||||
``` java
|
||||
Integer value = Maybe.maybe(getValue())
|
||||
.orElseThrow(() -> new RuntimeException("error"));
|
||||
```
|
||||
---
|
||||
#### `Maybe<T> peek(Consumer<T> consumer)`
|
||||
|
||||
Provide the value within the `Maybe`, if it exists, to the `Consumer`, and
|
||||
returns the original `Maybe`.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> maybe = Maybe.maybe(getValue())
|
||||
.peek(v -> v.foo());
|
||||
```
|
||||
#### `void ifNothing(Runnable runnable)`
|
||||
|
||||
Run the `Runnable` if the `Maybe` is `Nothing`, otherwise do nothing.
|
||||
|
||||
``` java
|
||||
Maybe.maybe(getValue())
|
||||
.ifNothing(() -> doSomething());
|
||||
```
|
||||
---
|
||||
#### `Stream<T> stream()`
|
||||
|
||||
Converts the `Maybe` into either a single value stream or an empty stream.
|
||||
|
||||
``` java
|
||||
Stream<Integer> stream = Maybe.maybe(getValue())
|
||||
.stream();
|
||||
```
|
||||
---
|
||||
#### `boolean isJust()`
|
||||
|
||||
Checks if the `Maybe` is a `Just`.
|
||||
|
||||
``` java
|
||||
boolean isJust = Maybe.maybe(getValue())
|
||||
.isJust();
|
||||
```
|
||||
---
|
||||
#### `boolean isNothing()`
|
||||
|
||||
Checks if the `Maybe` is `Nothing`.
|
||||
|
||||
``` java
|
||||
boolean isNothing = Maybe.maybe(getValue())
|
||||
.isNothing();
|
||||
```
|
||||
---
|
||||
#### `Optional<T> toOptional()`
|
||||
|
||||
Convert the `Maybe` to an `Optional`.
|
||||
|
||||
``` java
|
||||
Optional<Integer> optional = Maybe.maybe(getValue())
|
||||
.toOptional();
|
||||
```
|
||||
---
|
||||
## Result
|
||||
|
||||
Allows handling error conditions without the need to `catch` exceptions.
|
||||
|
||||
When a `Result` is returned from a method, it will contain one of two values.
|
||||
Either the actual result, or an error in the form of an `Exception`. The
|
||||
exception is returned within the `Result` and is not thrown.
|
||||
|
||||
`Result` is a Monad.
|
||||
|
||||
### Example
|
||||
|
||||
``` java
|
||||
import net.kemitix.mon.result.Result;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class ResultExample implements Runnable {
|
||||
|
||||
public static void main(final String[] args) {
|
||||
new ResultExample().run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Result.of(() -> callRiskyMethod())
|
||||
.flatMap(state -> doSomething(state))
|
||||
.match(
|
||||
success -> System.out.println(success),
|
||||
error -> error.printStackTrace()
|
||||
);
|
||||
}
|
||||
|
||||
private String callRiskyMethod() throws IOException {
|
||||
return "I'm fine";
|
||||
}
|
||||
|
||||
private Result<String> doSomething(final String state) {
|
||||
return Result.of(() -> state + ", it's all good.");
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
In the above example the string `"I'm fine"` is returned by
|
||||
`callRiskyMethod()` within a successful `Result`. The `.flatMap()` call,
|
||||
unwraps that `Result` and, as it is a success, passes the contents to
|
||||
`doSomething()`, which in turn returns a `Result` that the `.flatMap()` call
|
||||
returns. `match()` is called on the `Result` and, being a success, will call
|
||||
the success `Consumer`.
|
||||
|
||||
Had `callRiskyMethod()` thrown an exception it would have been caught by the
|
||||
`Result.of()` method, which would then return an error `Result`. An error
|
||||
`Result` would skip the `flatMap` and continue at the `match()` where it
|
||||
would have called the error `Consumer`.
|
||||
|
||||
### Static Constructors
|
||||
|
||||
#### `static <T> Result<T> of(Callable<T> callable)`
|
||||
|
||||
Create a `Result` for the output of the `Callable`.
|
||||
|
||||
If the `Callable` throws an `Exception`, then the `Result` will be an error and
|
||||
will contain that exception.
|
||||
|
||||
This will be the main starting point for most `Result`s where the callable
|
||||
could throw an `Exception`.
|
||||
|
||||
``` java
|
||||
Result<Integer> okay = Result.of(() -> 1);
|
||||
Result<Integer> error = Result.of(() -> {throw new RuntimeException();});
|
||||
```
|
||||
---
|
||||
#### `static <T> Result<T> ok(T value)`
|
||||
|
||||
Create a `Result` for a success.
|
||||
|
||||
Use this where you have a value that you want to place into the `Result` context.
|
||||
|
||||
``` java
|
||||
Result<Integer> okay = Result.ok(1);
|
||||
```
|
||||
---
|
||||
#### `static <T> Result<T> error(Throwable error)`
|
||||
|
||||
Create a `Result` for an error.
|
||||
|
||||
``` java
|
||||
Result<Integer> error = Result.error(new RuntimeException());
|
||||
```
|
||||
---
|
||||
### Static Methods
|
||||
|
||||
These static methods provide integration with the `Maybe` class.
|
||||
|
||||
#### `static <T> Maybe<T> toMaybe(Result<T> result)`
|
||||
|
||||
Creates a `Maybe` from the `Result`, where the `Result` is a success, then
|
||||
the `Maybe` will be a `Just` contain the value of the `Result`. However, if the
|
||||
`Result` is an error, then the `Maybe` will be `Nothing`.
|
||||
|
||||
``` java
|
||||
Result<Integer> result = Result.of(() -> getValue());
|
||||
Maybe<Integer> maybe = Result.toMaybe(result);
|
||||
```
|
||||
---
|
||||
#### `static <T> Result<T> fromMaybe(Maybe<T> maybe, Supplier<Throwable> error)`
|
||||
|
||||
Creates a `Result` from the `Maybe`, where the `Result` will be an error
|
||||
if the `Maybe` is nothing. Where the `Maybe` is nothing, then the
|
||||
`Supplier<Throwable>` will provide the error for the `Result`.
|
||||
|
||||
``` java
|
||||
Maybe<Integer> maybe = Maybe.maybe(getValue());
|
||||
Result<Integer> result = Result.fromMaybe(maybe,
|
||||
() -> new NoSuchFileException("filename"));
|
||||
```
|
||||
---
|
||||
#### `static <T> Result<Maybe<T>> invert(Maybe<Result<T>> maybeResult)`
|
||||
|
||||
Swaps the `Result` within a `Maybe`, so that `Result` contains a `Maybe`.
|
||||
|
||||
``` java
|
||||
Maybe<Result<Integer>> maybe = Maybe.maybe(Result.of(() -> getValue()));
|
||||
Result<Maybe<Integer>> result = Result.invert(maybe);
|
||||
```
|
||||
---
|
||||
#### `static <T,R> Result<Maybe<R>> flatMapMaybe(Result<Maybe<T>> maybeResult, Function<Maybe<T>,Result<Maybe<R>>> f)`
|
||||
|
||||
Applies the function to the contents of a `Maybe` within the `Result`.
|
||||
|
||||
``` java
|
||||
Result<Maybe<Integer>> result = Result.of(() -> Maybe.maybe(getValue()));
|
||||
Result<Maybe<Integer>> maybeResult = Result.flatMapMaybe(result,
|
||||
maybe -> Result.of(() -> maybe.map(v -> v * 2)));
|
||||
```
|
||||
---
|
||||
### Instance Methods
|
||||
|
||||
#### `<R> Result<R> map(Function<T,R> f)`
|
||||
|
||||
If the `Result` is a success, then apply the function to the value within the
|
||||
`Result`, returning the result within another `Result`. If the `Result` is an
|
||||
error, then return the error.
|
||||
|
||||
``` java
|
||||
Result<String> result = Result.of(() -> getValue())
|
||||
.map(v -> String.valueOf(v));
|
||||
```
|
||||
---
|
||||
#### `<R> Result<R> flatMap(Function<T,Result<R>> f)`
|
||||
|
||||
If the `Result` is a success, then return a new `Result` containing the result
|
||||
of applying the function to the contents of the `Result`. If the `Result` is an
|
||||
error, then return the error.
|
||||
|
||||
``` java
|
||||
Result<String> result =
|
||||
Result.of(() -> getValue())
|
||||
.flatMap(v -> Result.of(() -> String.valueOf(v)));
|
||||
```
|
||||
---
|
||||
#### `<R> Result<R> andThen(Function<T,Callable<R>> f)`
|
||||
|
||||
Maps a successful `Result` to another `Result` using a `Callable` that is able
|
||||
to throw a checked exception.
|
||||
|
||||
``` java
|
||||
Result<String> result =
|
||||
Result.of(() -> getValue())
|
||||
.andThen(v -> () -> {throw new IOException();});
|
||||
```
|
||||
---
|
||||
#### `void match(Consumer<T> onSuccess, Consumer<Throwable> onError)`
|
||||
|
||||
Matches the `Result`, either success or error, and supplies the appropriate
|
||||
`Consumer` with the value or error.
|
||||
|
||||
``` java
|
||||
Result.of(() -> getValue())
|
||||
.match(
|
||||
success -> System.out.println(success),
|
||||
error -> System.err.println(error.getMessage())
|
||||
);
|
||||
```
|
||||
---
|
||||
#### `Result<T> recover(Function<Throwable,Result<T>> f)`
|
||||
|
||||
Provide a way to attempt to recover from an error state.
|
||||
|
||||
``` java
|
||||
Result<Integer> result = Result.of(() -> getValue())
|
||||
.recover(e -> Result.of(() -> getSafeValue(e)));
|
||||
```
|
||||
---
|
||||
#### `Result<T> peek(Consumer<T> consumer)`
|
||||
|
||||
Provide the value within the Result, if it is a success, to the `Consumer`,
|
||||
and returns this Result.
|
||||
|
||||
``` java
|
||||
Result<Integer> result = Result.of(() -> getValue())
|
||||
.peek(v -> System.out.println(v));
|
||||
```
|
||||
---
|
||||
#### `Result<T> thenWith(Function<T,WithResultContinuation<T>> f)`
|
||||
|
||||
Perform the continuation with the current `Result` value then return the
|
||||
current `Result`, assuming there was no error in the continuation.
|
||||
|
||||
``` java
|
||||
Result<Integer> result =
|
||||
Result.of(() -> getValue())
|
||||
.thenWith(v -> () -> System.out.println(v))
|
||||
.thenWith(v -> () -> {throw new IOException();});
|
||||
```
|
||||
---
|
||||
#### `Result<Maybe<T>> maybe(Predicate<T> predicate)
|
||||
|
||||
Wraps the value within the `Result` in a `Maybe`, either a `Just` if the
|
||||
predicate is true, or `Nothing`.
|
||||
|
||||
``` java
|
||||
Result<Maybe<Integer>> result = Result.of(() -> getValue())
|
||||
.maybe(v -> v % 2 == 0);
|
||||
```
|
||||
---
|
||||
#### `T orElseThrow()`
|
||||
|
||||
Extracts the successful value from the `Result`, or throws the error
|
||||
within a `CheckedErrorResultException`.
|
||||
|
||||
``` java
|
||||
Integer result = Result.of(() -> getValue())
|
||||
.orElseThrow();
|
||||
```
|
||||
---
|
||||
#### `<E extends Exception> T orElseThrow(Class<E> type) throws E`
|
||||
|
||||
Extracts the successful value from the `Result`, or throws the error when it
|
||||
is of the given type. Any other errors will be thrown inside an
|
||||
`UnexpectedErrorResultException`.
|
||||
|
||||
``` java
|
||||
Integer result = Result.of(() -> getValue())
|
||||
.orElseThrow(IOException.class);
|
||||
```
|
||||
---
|
||||
#### `T orElseThrowUnchecked()`
|
||||
|
||||
Extracts the successful value from the `Result`, or throws the error within
|
||||
an `ErrorResultException`.
|
||||
|
||||
``` java
|
||||
Integer result = Result.of(() -> getValue())
|
||||
.orElseThrowUnchecked();
|
||||
```
|
||||
---
|
||||
#### `void onError(Consumer<Throwable> errorConsumer)`
|
||||
|
||||
A handler for error states. If the `Result` is an error, then supply the error
|
||||
to the `Consumer`. Does nothing if the `Result` is a success.
|
||||
|
||||
``` java
|
||||
Result.of(() -> getValue())
|
||||
.onError(e -> handleError(e));
|
||||
```
|
||||
---
|
||||
#### `boolean isOkay()`
|
||||
|
||||
Checks if the `Result` is a success.
|
||||
|
||||
``` java
|
||||
boolean isOkay = Result.of(() -> getValue())
|
||||
.isOkay();
|
||||
```
|
||||
---
|
||||
#### `boolean isError()`
|
||||
|
||||
Checks if the `Result` is an error.
|
||||
|
||||
``` java
|
||||
boolean isError = Result.of(() -> getValue())
|
||||
.isError();
|
||||
```
|
||||
---
|
||||
## Tree
|
||||
|
||||
A Generalised tree, where each node may or may not have an item, and may have
|
||||
any number of sub-trees. Leaf nodes are Trees with zero sub-trees.
|
||||
|
||||
### Static Constructors
|
||||
|
||||
#### `static <R> Tree<R> leaf(R item)`
|
||||
|
||||
Create a leaf containing the item. The leaf has no sub-trees.
|
||||
|
||||
``` java
|
||||
Tree<String> tree = Tree.leaf("item");
|
||||
```
|
||||
---
|
||||
#### `static<R> Tree<R> of(R item, Collection<Tree<R>> subtrees)`
|
||||
|
||||
Create a tree containing the item and sub-trees.
|
||||
|
||||
``` java
|
||||
Tree<String> tree = Tree.of("item", Collections.singletonList(Tree.leaf("leaf"));
|
||||
```
|
||||
---
|
||||
#### `static <B> TreeBuilder<B> builder(final Class<B> type)`
|
||||
|
||||
Create a new `TreeBuilder` starting with an empty tree.
|
||||
|
||||
``` java
|
||||
TreeBuilder<Integer> builder = Tree.builder(Integer.class);
|
||||
```
|
||||
---
|
||||
#### `static <B> TreeBuilder<B> builder(final Tree<B> tree)`
|
||||
|
||||
Create a new `TreeBuilder` for the given tree.
|
||||
|
||||
``` java
|
||||
Tree<Integer> tree = ...;
|
||||
TreeBuilder<Integer> builder = Tree.builder(tree);
|
||||
```
|
||||
---
|
||||
### Instance Methods
|
||||
|
||||
#### `<R> Tree<R> map(Function<T, R> f)`
|
||||
|
||||
Applies the function to the item within the `Tree` and to all sub-trees,
|
||||
returning a new `Tree`.
|
||||
|
||||
``` java
|
||||
Tree<UUID> tree = ...;
|
||||
Tree<String> result = tree.map(UUID::toString);
|
||||
```
|
||||
---
|
||||
#### `Maybe<T> item()`
|
||||
|
||||
Returns the contents of the `Tree` node within a `Maybe`.
|
||||
|
||||
``` java
|
||||
Tree<Item> tree = ...;
|
||||
Maybe<Item> result = tree.item();
|
||||
```
|
||||
---
|
||||
#### `int count()`
|
||||
|
||||
Returns the total number of items in the `Tree`, including sub-trees. `Null`
|
||||
items don't count.
|
||||
|
||||
``` java
|
||||
Tree<Item> tree = ...;
|
||||
int result = tree.count();
|
||||
```
|
||||
---
|
||||
#### `List<Tree<T> subTrees()`
|
||||
|
||||
Returns a list of sub-trees within the `Tree`.
|
||||
|
||||
``` java
|
||||
Tree<Item> tree = ...;
|
||||
List<Tree<Item>> result = tree.subTrees();
|
||||
```
|
||||
---
|
||||
## TreeBuilder
|
||||
|
||||
A mutable builder for a `Tree`. Each `TreeBuilder` allows modification of a
|
||||
single `Tree` node. You can use the `select(childItem)` method to get a
|
||||
`TreeBuilder` for the subtree that has the given child item.
|
||||
|
||||
### Example
|
||||
|
||||
``` java
|
||||
TreeBuilder<Integer> builder = Tree.builder();
|
||||
builder.set(12).addChildren(Arrays.asList(1, 3, 5, 7));
|
||||
TreeBuilder<Integer> builderFor3 = builder.select(3);
|
||||
builderFor3.addChildren(Arrays.asList(2, 4));
|
||||
Tree<Integer> tree = builder.build();
|
||||
```
|
||||
|
||||
Will produce a `Tree` like:
|
||||
|
||||
![](images/treebuilder-example.svg)
|
||||
---
|
||||
### Static Constructors
|
||||
|
||||
None. The `TreeBuilder` is instantiated by `Tree.builder()`.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `Tree<T> build()`
|
||||
|
||||
Create the immutable Tree.
|
||||
|
||||
``` java
|
||||
TreeBuilder<Integer> builder = Tree.builder();
|
||||
Tree<Integer> tree = builder.build();
|
||||
```
|
||||
---
|
||||
#### `TreeBuilder<T> item(T item)`
|
||||
|
||||
Set the current `Tree`'s item and return the `TreeBuilder`.
|
||||
|
||||
#### `TreeBuilder<T> add(Tree<T> subtree)`
|
||||
|
||||
Adds the subtree to the current tree.
|
||||
|
||||
#### `TreeBuilder<T> addChild(T childItem)`
|
||||
|
||||
Add the Child item as a sub-Tree.
|
||||
|
||||
#### `TreeBuilder<T> addChildren(List<T> children)`
|
||||
|
||||
Add all the child items as subTrees.
|
||||
|
||||
#### `Maybe<TreeBuilder<T>> select(T childItem)`
|
||||
|
||||
Create a `TreeBuilder` for the subTree of the current `Tree` that has the
|
||||
childItem.
|
||||
|
||||
## Lazy
|
||||
|
||||
A lazily evaluated expression. Using a `Supplier` to provide the value, only
|
||||
evaluates the value when required, and never more than once.
|
||||
|
||||
### Static Constructors
|
||||
|
||||
#### `static <R> Lazy<R> of(Supplier<R> supplier)`
|
||||
|
||||
Create a new `Lazy` value from the `Supplier`.
|
||||
|
||||
``` java
|
||||
Suppler<UUID> supplier = ...;
|
||||
Lazy<UUID> lazy = Lazy.of(supplier);
|
||||
```
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `boolean isEvaluated()`
|
||||
|
||||
Checks if the value has been evaluated.
|
||||
|
||||
``` java
|
||||
Lazy<UUID> lazy = ...;
|
||||
boolean isEvaluated = lazy.isEvaluated();
|
||||
```
|
||||
---
|
||||
#### `T value()`
|
||||
|
||||
The value, evaluating it if necessary.
|
||||
|
||||
``` java
|
||||
Lazy<UUID> lazy = ...;
|
||||
UUID value = lazy.value();
|
||||
```
|
||||
---
|
||||
#### `<R> Lazy<R> map(Function<T, R> f)`
|
||||
|
||||
Maps the `Lazy` instance into a new `Lazy` instance using the `Function`.
|
||||
|
||||
``` java
|
||||
Lazy<UUID> uuidLazy = ...;
|
||||
Lazy<String> stringLazy = uuidLazy.map(v -> v.toString());
|
||||
```
|
||||
---
|
||||
## Either
|
||||
|
||||
Allows handling a value that can be one of two types, a left value/type, or a
|
||||
right value/type.
|
||||
|
||||
`Either` *is not* a Monad.
|
||||
|
||||
When an `Either` is returned from a method it will contain either a left or a
|
||||
right.
|
||||
|
||||
Where the `Either` is used to represent success/failure, the left case is, by
|
||||
convention, used to indicate the error, and right the success. An alternative
|
||||
is to use the `Result` which more clearly distinguishes success from failure.
|
||||
---
|
||||
### Static Constructors
|
||||
|
||||
#### `static <L, R> Either<L, R> left(final L l)`
|
||||
|
||||
Create a new `Either` holding a left value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> left = Either.left(getIntegerValue());
|
||||
```
|
||||
---
|
||||
#### `static <L, R> Either<L, R> right(final R r)`
|
||||
|
||||
Create a new `Either` holding a right value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> right = Either.right(getStringValue());
|
||||
```
|
||||
---
|
||||
### Instance Methods
|
||||
|
||||
#### `boolean isLeft()`
|
||||
|
||||
Checks if the `Either` holds a left value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.left(getIntegerValue());
|
||||
boolean leftIsLeft = either.isLeft();
|
||||
boolean rightIsLeft = either.isLeft();
|
||||
```
|
||||
---
|
||||
#### `boolean isRight()`
|
||||
|
||||
Checks if the `Either` holds a right value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.left(getIntegerValue());
|
||||
boolean leftIsRight = either.isRight();
|
||||
boolean rightIsRight = either.isRight();
|
||||
```
|
||||
---
|
||||
#### `void match(Consumer<L> onLeft, Consumer<R> onRight)`
|
||||
|
||||
Matches the `Either`, invoking the correct `Consumer`.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.left(getIntegerValue());
|
||||
either.match(
|
||||
left -> handleIntegerValue(left),
|
||||
right -> handleStringValue(right)
|
||||
);
|
||||
```
|
||||
---
|
||||
#### `<T> Either<T, R> mapLeft(Function<L, T> f)`
|
||||
|
||||
Map the `Function` across the left value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.left(getIntegerValue());
|
||||
Either<Double, String> either = either.mapLeft(i -> i.doubleValue());
|
||||
```
|
||||
---
|
||||
#### `<T> Either<L, T> mapRight(Function<R, T> f)`
|
||||
|
||||
Map the function across the right value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.left(getIntegerValue());
|
||||
Either<Integer, String> either = either.mapRight(s -> s + "x");
|
||||
```
|
||||
---
|
||||
#### `<T> Either<T, R> flatMapLeft(Function<L, Either<T, R>> f)`
|
||||
|
||||
FlatMap the function across the left value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.left(2);
|
||||
Either<Integer, String> resultLeft = either.flatMapLeft(l -> Either.left(l * 2));
|
||||
Either<Integer, String> resultRight = either.flatMapLeft(l -> Either.right(l * 2));
|
||||
```
|
||||
---
|
||||
#### `<T> Either<T, R> flatMapRight(Function<L, Either<T, R>> f)`
|
||||
|
||||
FlatMap the function across the right value.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.right("2");
|
||||
Either<Integer, String> resultLeft = either.flatMapRight(l -> Either.left(l * 2));
|
||||
Either<Integer, String> resultRight = either.flatMapRight(l -> Either.right(l * 2));
|
||||
```
|
||||
---
|
||||
#### `Optional<L> getLeft()`
|
||||
|
||||
Returns an `Optional` containing the left value, if is a left, otherwise returns
|
||||
an empty `Optional`.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.right("2");
|
||||
Optional<Integer> left = either.getLeft();
|
||||
```
|
||||
---
|
||||
#### `Optional<R> getRight()`
|
||||
|
||||
Returns an `Optional` containing the right value, if is a right, otherwise
|
||||
returns an empty `Optional`.
|
||||
|
||||
``` java
|
||||
Either<Integer, String> either = Either.right("2");
|
||||
Optional<String> right = either.getRight();
|
||||
```
|
||||
|
||||
## Combinators
|
||||
|
||||
### After
|
||||
|
||||
TODO
|
||||
|
||||
### Before
|
||||
|
||||
TODO
|
||||
|
||||
### Around
|
||||
|
||||
TODO
|
1228
README.org
1228
README.org
File diff suppressed because it is too large
Load diff
15
pom.xml
15
pom.xml
|
@ -14,7 +14,7 @@
|
|||
<version>2.3.0</version>
|
||||
|
||||
<name>Mon</name>
|
||||
<description>TypeAlias, Result and Maybe for Java</description>
|
||||
<description>Wrapper, TypeAlias, Result, Lazy, Maybe and combinators for Java</description>
|
||||
|
||||
<issueManagement>
|
||||
<url>https://github.com/kemitix/mon/issues</url>
|
||||
|
@ -38,9 +38,9 @@
|
|||
<assertj.version>3.19.0</assertj.version>
|
||||
<lombok.version>1.18.18</lombok.version>
|
||||
<tiles-maven-plugin.version>2.19</tiles-maven-plugin.version>
|
||||
<kemitix-maven-tiles.version>2.4.1</kemitix-maven-tiles.version>
|
||||
<kemitix-maven-tiles.version>3.0.1</kemitix-maven-tiles.version>
|
||||
<digraph-dependency.basePackage>net.kemitix.mon</digraph-dependency.basePackage>
|
||||
<kemitix-checkstyle.version>5.0.0</kemitix-checkstyle.version>
|
||||
<kemitix-checkstyle.version>5.5.0</kemitix-checkstyle.version>
|
||||
<pitest-maven-plugin.version>1.6.4</pitest-maven-plugin.version>
|
||||
<pitest-junit5-plugin.version>0.12</pitest-junit5-plugin.version>
|
||||
<spotbugs.version>4.1.2</spotbugs.version>
|
||||
|
@ -105,7 +105,14 @@
|
|||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<tile>net.kemitix.tiles:all:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:maven-plugins:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:compiler-jdk-lts:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:pmd:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:testing:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:spotbugs:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:coverage:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:pitest:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.tiles:pmd-strict:${kemitix-maven-tiles.version}</tile>
|
||||
<tile>net.kemitix.checkstyle:tile:${kemitix-checkstyle.version}</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
|
|
|
@ -48,5 +48,5 @@ public interface Functor<T, F extends Functor<?, ?>> {
|
|||
*
|
||||
* @return a Functor containing the result of the function {@code f} applied to the value
|
||||
*/
|
||||
public abstract <R> F map(Function<T, R> f);
|
||||
<R> F map(Function<T, R> f);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.function.Function;
|
|||
* @param <T> the type of the alias
|
||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||
*/
|
||||
@SuppressWarnings("abstractclassname")
|
||||
@SuppressWarnings({"abstractclassname", "PMD.AbstractClassWithoutAbstractMethod"})
|
||||
public abstract class TypeAlias<T> {
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,6 @@ public interface Wrapper<T> {
|
|||
*
|
||||
* @return the value
|
||||
*/
|
||||
public abstract T value();
|
||||
T value();
|
||||
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public interface After<T, R> extends
|
|||
* @return a partially applied Function that will take an argument and return the result of applying it to the
|
||||
* function parameter
|
||||
*/
|
||||
public static <T, R> Function<T, R> decorate(
|
||||
static <T, R> Function<T, R> decorate(
|
||||
final Function<T, R> function,
|
||||
final BiConsumer<T, R> after
|
||||
) {
|
||||
|
@ -68,7 +68,7 @@ public interface After<T, R> extends
|
|||
*
|
||||
* @return a curried function that will pass the argument and the result of the function to the supplied bi-consumer
|
||||
*/
|
||||
public static <T, R> After<T, R> create() {
|
||||
static <T, R> After<T, R> create() {
|
||||
return function -> after -> argument -> {
|
||||
final R result = function.apply(argument);
|
||||
after.accept(argument, result);
|
||||
|
|
|
@ -54,7 +54,7 @@ public interface Around<T, R> extends
|
|||
*
|
||||
* @return a partially applied Function that will take an argument, and the result of applying it to function
|
||||
*/
|
||||
public static <T, R> Function<T, R> decorate(
|
||||
static <T, R> Function<T, R> decorate(
|
||||
final Function<T, R> function,
|
||||
final BiConsumer<Executable<R>, T> around
|
||||
) {
|
||||
|
@ -71,7 +71,7 @@ public interface Around<T, R> extends
|
|||
* @return a curried function that will execute the around function, passing an executable and the invocations
|
||||
* argument. The around function must {@code execute()} the executable and may capture the result.
|
||||
*/
|
||||
public static <T, R> Around<T, R> create() {
|
||||
static <T, R> Around<T, R> create() {
|
||||
return function -> around -> argument -> {
|
||||
final AtomicReference<R> result = new AtomicReference<>();
|
||||
final Executable<R> callback = () -> {
|
||||
|
@ -89,13 +89,13 @@ public interface Around<T, R> extends
|
|||
* @param <R> the return type of the function
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public static interface Executable<R> {
|
||||
interface Executable<R> {
|
||||
|
||||
/**
|
||||
* Executes the function.
|
||||
*
|
||||
* @return the result of applying the function
|
||||
*/
|
||||
public abstract R execute();
|
||||
R execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public interface Before<T, R> extends
|
|||
* @return a partially applied Function that will take an argument and return the result of applying it to the
|
||||
* function parameter
|
||||
*/
|
||||
public static <T, R> Function<T, R> decorate(
|
||||
static <T, R> Function<T, R> decorate(
|
||||
final Consumer<T> before,
|
||||
final Function<T, R> function
|
||||
) {
|
||||
|
@ -69,7 +69,7 @@ public interface Before<T, R> extends
|
|||
*
|
||||
* @return a curried function that will pass the argument to before applying the supplied function
|
||||
*/
|
||||
public static <T, R> Before<T, R> create() {
|
||||
static <T, R> Before<T, R> create() {
|
||||
return before -> function -> argument -> {
|
||||
before.accept(argument);
|
||||
return function.apply(argument);
|
||||
|
|
|
@ -43,7 +43,7 @@ public interface Either<L, R> {
|
|||
* @param <R> the type of the right value
|
||||
* @return a Either holding the left value
|
||||
*/
|
||||
public static <L, R> Either<L, R> left(final L l) {
|
||||
static <L, R> Either<L, R> left(final L l) {
|
||||
return new Left<>(l);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ public interface Either<L, R> {
|
|||
* @param <R> the type of the right value
|
||||
* @return a Either holding the right value
|
||||
*/
|
||||
public static <L, R> Either<L, R> right(final R r) {
|
||||
static <L, R> Either<L, R> right(final R r) {
|
||||
return new Right<>(r);
|
||||
}
|
||||
|
||||
|
@ -64,14 +64,14 @@ public interface Either<L, R> {
|
|||
*
|
||||
* @return true if this Either is a left
|
||||
*/
|
||||
public abstract boolean isLeft();
|
||||
boolean isLeft();
|
||||
|
||||
/**
|
||||
* Checks if the Either holds a right value.
|
||||
*
|
||||
* @return true if this Either is a right
|
||||
*/
|
||||
public abstract boolean isRight();
|
||||
boolean isRight();
|
||||
|
||||
/**
|
||||
* Matches the Either, invoking the correct Consumer.
|
||||
|
@ -79,7 +79,7 @@ public interface Either<L, R> {
|
|||
* @param onLeft the Consumer to invoke when the Either is a left
|
||||
* @param onRight the Consumer to invoke when the Either is a right
|
||||
*/
|
||||
public abstract void match(Consumer<L> onLeft, Consumer<R> onRight);
|
||||
void match(Consumer<L> onLeft, Consumer<R> onRight);
|
||||
|
||||
/**
|
||||
* Map the function across the left value.
|
||||
|
@ -88,7 +88,7 @@ public interface Either<L, R> {
|
|||
* @param <T> the type to change the left value to
|
||||
* @return a new Either
|
||||
*/
|
||||
public abstract <T> Either<T, R> mapLeft(Function<L, T> f);
|
||||
<T> Either<T, R> mapLeft(Function<L, T> f);
|
||||
|
||||
/**
|
||||
* Map the function across the right value.
|
||||
|
@ -97,7 +97,7 @@ public interface Either<L, R> {
|
|||
* @param <T> the type to change the right value to
|
||||
* @return a new Either
|
||||
*/
|
||||
public abstract <T> Either<L, T> mapRight(Function<R, T> f);
|
||||
<T> Either<L, T> mapRight(Function<R, T> f);
|
||||
|
||||
/**
|
||||
* FlatMap the function across the left value.
|
||||
|
@ -106,7 +106,7 @@ public interface Either<L, R> {
|
|||
* @param <T> the type to change the left value to
|
||||
* @return a new Either if is a Left, else this
|
||||
*/
|
||||
public abstract <T> Either<T, R> flatMapLeft(Function<L, Either<T, R>> f);
|
||||
<T> Either<T, R> flatMapLeft(Function<L, Either<T, R>> f);
|
||||
|
||||
/**
|
||||
* FlatMap the function across the right value.
|
||||
|
@ -115,7 +115,7 @@ public interface Either<L, R> {
|
|||
* @param <T> the type to change the right value to
|
||||
* @return a new Either if is a Right, else this
|
||||
*/
|
||||
public abstract <T> Either<L, T> flatMapRight(Function<R, Either<L, T>> f);
|
||||
<T> Either<L, T> flatMapRight(Function<R, Either<L, T>> f);
|
||||
|
||||
/**
|
||||
* Returns an Optional containing the left value, if is a left, otherwise
|
||||
|
@ -123,7 +123,7 @@ public interface Either<L, R> {
|
|||
*
|
||||
* @return An Optional containing any left value
|
||||
*/
|
||||
public abstract Optional<L> getLeft();
|
||||
Optional<L> getLeft();
|
||||
|
||||
/**
|
||||
* Returns an Optional containing the right value, if is a right, otherwise
|
||||
|
@ -131,5 +131,5 @@ public interface Either<L, R> {
|
|||
*
|
||||
* @return An Optional containing any right value
|
||||
*/
|
||||
public abstract Optional<R> getRight();
|
||||
Optional<R> getRight();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public interface Lazy<T> extends Functor<T, Lazy<?>> {
|
|||
* @param <R> the type of the value
|
||||
* @return a Lazy wrapper of the Supplier
|
||||
*/
|
||||
public static <R> Lazy<R> of(final Supplier<R> supplier) {
|
||||
static <R> Lazy<R> of(final Supplier<R> supplier) {
|
||||
return new LazySupplier<>(supplier);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ public interface Lazy<T> extends Functor<T, Lazy<?>> {
|
|||
*
|
||||
* @return true if the value has been evaluated.
|
||||
*/
|
||||
public abstract boolean isEvaluated();
|
||||
boolean isEvaluated();
|
||||
|
||||
/**
|
||||
* The value, evaluating it if necessary.
|
||||
|
@ -60,8 +60,8 @@ public interface Lazy<T> extends Functor<T, Lazy<?>> {
|
|||
*
|
||||
* @return the evaluated value
|
||||
*/
|
||||
public abstract T value();
|
||||
T value();
|
||||
|
||||
@Override
|
||||
public abstract <R> Lazy<R> map(Function<T, R> f);
|
||||
<R> Lazy<R> map(Function<T, R> f);
|
||||
}
|
||||
|
|
|
@ -35,10 +35,10 @@ import java.util.function.Supplier;
|
|||
*/
|
||||
class LazySupplier<T> implements Lazy<T> {
|
||||
|
||||
private final Supplier<T> supplier;
|
||||
private transient final Supplier<T> supplier;
|
||||
private final AtomicBoolean evaluated = new AtomicBoolean(false);
|
||||
private final AtomicReference<T> value = new AtomicReference<>();
|
||||
private final Object lock = new Object();
|
||||
private transient final AtomicReference<T> value = new AtomicReference<>();
|
||||
private transient final Object lock = new Object();
|
||||
|
||||
/**
|
||||
* Creates a new Lazy wrapper for the Supplier.
|
||||
|
|
|
@ -50,7 +50,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param <T> the type of the value
|
||||
* @return a Maybe of the value
|
||||
*/
|
||||
public static <T> Maybe<T> just(@NonNull final T value) {
|
||||
static <T> Maybe<T> just(@NonNull final T value) {
|
||||
return new Just<>(value);
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @return an empty Maybe
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Maybe<T> nothing() {
|
||||
static <T> Maybe<T> nothing() {
|
||||
return (Maybe<T>) Nothing.INSTANCE;
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param <T> the type of the value
|
||||
* @return a Maybe, either a Just, or Nothing if value is null
|
||||
*/
|
||||
public static <T> Maybe<T> maybe(final T value) {
|
||||
static <T> Maybe<T> maybe(final T value) {
|
||||
if (value == null) {
|
||||
return nothing();
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param <T> the type of the stream
|
||||
* @return a Maybe containing the first item in the stream
|
||||
*/
|
||||
public static <T> Maybe<T> findFirst(Stream<T> stream) {
|
||||
static <T> Maybe<T> findFirst(Stream<T> stream) {
|
||||
return stream.findFirst()
|
||||
.map(Maybe::just)
|
||||
.orElseGet(Maybe::nothing);
|
||||
|
@ -99,14 +99,14 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
*
|
||||
* @return true if the Maybe is a Just
|
||||
*/
|
||||
public abstract boolean isJust();
|
||||
boolean isJust();
|
||||
|
||||
/**
|
||||
* Checks if the Maybe is Nothing.
|
||||
*
|
||||
* @return true if the Maybe is Nothing
|
||||
*/
|
||||
public abstract boolean isNothing();
|
||||
boolean isNothing();
|
||||
|
||||
/**
|
||||
* Monad binder maps the Maybe into another Maybe using the binder method f.
|
||||
|
@ -115,10 +115,10 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param <R> the type of the value in the final maybe
|
||||
* @return a Maybe with the mapped value
|
||||
*/
|
||||
public abstract <R> Maybe<R> flatMap(Function<T, Maybe<R>> f);
|
||||
<R> Maybe<R> flatMap(Function<T, Maybe<R>> f);
|
||||
|
||||
@Override
|
||||
public abstract <R> Maybe<R> map(Function<T, R> f);
|
||||
<R> Maybe<R> map(Function<T, R> f);
|
||||
|
||||
/**
|
||||
* Provide a value to use when Maybe is Nothing.
|
||||
|
@ -126,7 +126,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param supplier supplier for an alternate value
|
||||
* @return a Maybe
|
||||
*/
|
||||
public abstract T orElseGet(Supplier<T> supplier);
|
||||
T orElseGet(Supplier<T> supplier);
|
||||
|
||||
/**
|
||||
* A value to use when Maybe is Nothing.
|
||||
|
@ -134,14 +134,14 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param otherValue an alternate value
|
||||
* @return the value of the Maybe if a Just, otherwise the otherValue
|
||||
*/
|
||||
public abstract T orElse(T otherValue);
|
||||
T orElse(T otherValue);
|
||||
|
||||
/**
|
||||
* Convert the Maybe to an {@link Optional}.
|
||||
*
|
||||
* @return an Optional containing a value for a Just, or empty for a Nothing
|
||||
*/
|
||||
public abstract Optional<T> toOptional();
|
||||
Optional<T> toOptional();
|
||||
|
||||
/**
|
||||
* Throw the exception if the Maybe is a Nothing.
|
||||
|
@ -151,14 +151,14 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @return the value of the Maybe if a Just
|
||||
* @throws X if the Maybe is nothing
|
||||
*/
|
||||
public abstract <X extends Throwable> T orElseThrow(Supplier<? extends X> e) throws X;
|
||||
<X extends Throwable> T orElseThrow(Supplier<? extends X> e) throws X;
|
||||
|
||||
/**
|
||||
* Converts the Maybe into either a single value stream or an empty stream.
|
||||
*
|
||||
* @return a Stream containing the value or nothing.
|
||||
*/
|
||||
public abstract Stream<T> stream();
|
||||
Stream<T> stream();
|
||||
|
||||
/**
|
||||
* Filter a Maybe by the predicate, replacing with Nothing when it fails.
|
||||
|
@ -166,7 +166,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param predicate the test
|
||||
* @return the Maybe, or Nothing if the test returns false
|
||||
*/
|
||||
public abstract Maybe<T> filter(Predicate<T> predicate);
|
||||
Maybe<T> filter(Predicate<T> predicate);
|
||||
|
||||
/**
|
||||
* Provide the value within the Maybe, if it exists, to the Consumer, and returns this Maybe.
|
||||
|
@ -174,14 +174,14 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param consumer the Consumer to the value if present
|
||||
* @return this Maybe
|
||||
*/
|
||||
public abstract Maybe<T> peek(Consumer<T> consumer);
|
||||
Maybe<T> peek(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Run the runnable if the Maybe is a Nothing, otherwise do nothing.
|
||||
*
|
||||
* @param runnable the runnable to call if this is a Nothing
|
||||
*/
|
||||
public abstract void ifNothing(Runnable runnable);
|
||||
void ifNothing(Runnable runnable);
|
||||
|
||||
/**
|
||||
* Matches the Maybe, either just or nothing, and performs either the Consumer, for Just, or Runnable for nothing.
|
||||
|
@ -191,7 +191,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
* @param justMatcher the Consumer to pass the value of a Just to
|
||||
* @param nothingMatcher the Runnable to call if the Maybe is a Nothing
|
||||
*/
|
||||
public abstract void match(Consumer<T> justMatcher, Runnable nothingMatcher);
|
||||
void match(Consumer<T> justMatcher, Runnable nothingMatcher);
|
||||
|
||||
/**
|
||||
* Matches the Maybe, either just or nothing, and performs either the Function, for Just, or Supplier for nothing.
|
||||
|
@ -204,7 +204,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
*
|
||||
* @return the matched result, from either the justMatcher or the nothingMatcher
|
||||
*/
|
||||
public abstract <R> R matchValue(Function<T, R> justMatcher, Supplier<R> nothingMatcher);
|
||||
<R> R matchValue(Function<T, R> justMatcher, Supplier<R> nothingMatcher);
|
||||
|
||||
/**
|
||||
* Maps the Maybe into another Maybe only when it is nothing.
|
||||
|
@ -213,5 +213,5 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
*
|
||||
* @return the original Maybe if not nothing, or the alternative
|
||||
*/
|
||||
public abstract Maybe<T> or(Supplier<Maybe<T>> alternative);
|
||||
Maybe<T> or(Supplier<Maybe<T>> alternative);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ final class Nothing<T> implements Maybe<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "PMD.AvoidDuplicateLiterals"})
|
||||
public <R> Maybe<R> flatMap(final Function<T, Maybe<R>> f) {
|
||||
return (Maybe<R>) INSTANCE;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ package net.kemitix.mon.result;
|
|||
*/
|
||||
public final class CheckedErrorResultException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 6388860431020999870L;
|
||||
|
||||
private CheckedErrorResultException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import java.util.function.Predicate;
|
|||
* @param <T> the type of the value in the Result if it has been a success
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings("methodcount")
|
||||
@SuppressWarnings({"methodcount", "PMD.CyclomaticComplexity"})
|
||||
class Err<T> implements Result<T> {
|
||||
|
||||
private final Throwable error;
|
||||
|
|
|
@ -30,6 +30,8 @@ package net.kemitix.mon.result;
|
|||
*/
|
||||
public final class ErrorResultException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -949688489831104844L;
|
||||
|
||||
private ErrorResultException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import java.util.function.*;
|
|||
* @param <T> the type of the result when a success
|
||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||
*/
|
||||
@SuppressWarnings("methodcount")
|
||||
@SuppressWarnings({"methodcount", "PMD.TooManyMethods"})
|
||||
public interface Result<T> extends Functor<T, Result<?>> {
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type of the Maybe and the Result
|
||||
* @return a Result containing the value of the Maybe when it is a Just, or the error when it is Nothing
|
||||
*/
|
||||
public static <T> Result<T> fromMaybe(final Maybe<T> maybe, final Supplier<Throwable> error) {
|
||||
static <T> Result<T> fromMaybe(final Maybe<T> maybe, final Supplier<Throwable> error) {
|
||||
return maybe.map(Result::ok)
|
||||
.orElseGet(() -> Result.error(error.get()));
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type had the result been a success
|
||||
* @return an error Result
|
||||
*/
|
||||
public default <T> Result<T> err(final Throwable error) {
|
||||
default <T> Result<T> err(final Throwable error) {
|
||||
return new Err<>(error);
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type had the result been a success
|
||||
* @return an error Result
|
||||
*/
|
||||
public static <T> Result<T> error(final Throwable error) {
|
||||
static <T> Result<T> error(final Throwable error) {
|
||||
return new Err<>(error);
|
||||
}
|
||||
|
||||
|
@ -78,11 +78,11 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type of the value
|
||||
* @return a Result
|
||||
*/
|
||||
@SuppressWarnings("illegalcatch")
|
||||
public default <T> Result<T> result(final Callable<T> callable) {
|
||||
@SuppressWarnings({"illegalcatch", "PMD.AvoidCatchingThrowable", "PMD.AvoidDuplicateLiterals"})
|
||||
default <T> Result<T> result(final Callable<T> callable) {
|
||||
try {
|
||||
return Result.ok(callable.call());
|
||||
} catch (final Exception e) {
|
||||
} catch (final Throwable e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
@ -94,11 +94,11 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type of the value
|
||||
* @return a Result
|
||||
*/
|
||||
@SuppressWarnings("illegalcatch")
|
||||
public static <T> Result<T> of(final Callable<T> callable) {
|
||||
@SuppressWarnings({"illegalcatch", "PMD.AvoidCatchingThrowable"})
|
||||
static <T> Result<T> of(final Callable<T> callable) {
|
||||
try {
|
||||
return Result.ok(callable.call());
|
||||
} catch (final Exception e) {
|
||||
} catch (final Throwable e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type of the value
|
||||
* @return a successful Result
|
||||
*/
|
||||
public default <T> Result<T> success(final T value) {
|
||||
default <T> Result<T> success(final T value) {
|
||||
return new Success<>(value);
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type of the value
|
||||
* @return a successful Result
|
||||
*/
|
||||
public static <T> Result<T> ok(final T value) {
|
||||
static <T> Result<T> ok(final T value) {
|
||||
return new Success<>(value);
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <T> the type of the Maybe and the Result
|
||||
* @return a Result containing the value of the Maybe when it is a Just, or the error when it is Nothing
|
||||
*/
|
||||
public static <T> Maybe<T> toMaybe(final Result<T> result) {
|
||||
static <T> Maybe<T> toMaybe(final Result<T> result) {
|
||||
try {
|
||||
return Maybe.just(result.orElseThrow());
|
||||
} catch (final CheckedErrorResultException throwable) {
|
||||
|
@ -148,7 +148,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @return the value if a success
|
||||
* @throws CheckedErrorResultException if the result is an error
|
||||
*/
|
||||
public abstract T orElseThrow() throws CheckedErrorResultException;
|
||||
T orElseThrow() throws CheckedErrorResultException;
|
||||
|
||||
/**
|
||||
* Extracts the successful value from the result, or throws the error Throwable.
|
||||
|
@ -159,14 +159,14 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @return the value if a success
|
||||
* @throws E if the result is an error
|
||||
*/
|
||||
public abstract <E extends Exception> T orElseThrow(Class<E> type) throws E;
|
||||
<E extends Exception> T orElseThrow(Class<E> type) throws E;
|
||||
|
||||
/**
|
||||
* Extracts the successful value from the result, or throws the error in a {@link UnexpectedErrorResultException}.
|
||||
*
|
||||
* @return the value if a success
|
||||
*/
|
||||
public abstract T orElseThrowUnchecked();
|
||||
T orElseThrowUnchecked();
|
||||
|
||||
/**
|
||||
* Swaps the inner Result of a Maybe, so that a Result is on the outside.
|
||||
|
@ -177,7 +177,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* original Maybe. If the original Maybe is Nothing, the Result will contain Nothing. If the original Result was an
|
||||
* error, then the Result will also be an error.
|
||||
*/
|
||||
public static <T> Result<Maybe<T>> swap(final Maybe<Result<T>> maybeResult) {
|
||||
static <T> Result<Maybe<T>> swap(final Maybe<Result<T>> maybeResult) {
|
||||
return maybeResult.orElseGet(() -> Result.ok(null))
|
||||
.flatMap(value -> Result.ok(Maybe.maybe(value)));
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <R> the type of the value withing the Result of the mapping function
|
||||
* @return a Result
|
||||
*/
|
||||
public abstract <R> Result<R> flatMap(Function<T, Result<R>> f);
|
||||
<R> Result<R> flatMap(Function<T, Result<R>> f);
|
||||
|
||||
/**
|
||||
* Applies the function to the contents of a Maybe within the Result.
|
||||
|
@ -200,7 +200,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <R> the type of the updated Result
|
||||
* @return a new Maybe within a Result
|
||||
*/
|
||||
public static <T, R> Result<Maybe<R>> flatMapMaybe(
|
||||
static <T, R> Result<Maybe<R>> flatMapMaybe(
|
||||
final Result<Maybe<T>> maybeResult,
|
||||
final Function<Maybe<T>, Result<Maybe<R>>> f
|
||||
) {
|
||||
|
@ -212,17 +212,17 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
*
|
||||
* @return true if the Result is an error.
|
||||
*/
|
||||
public abstract boolean isError();
|
||||
boolean isError();
|
||||
|
||||
/**
|
||||
* Checks if the Result is a success.
|
||||
*
|
||||
* @return true if the Result is a success.
|
||||
*/
|
||||
public abstract boolean isOkay();
|
||||
boolean isOkay();
|
||||
|
||||
@Override
|
||||
public abstract <R> Result<R> map(Function<T, R> f);
|
||||
<R> Result<R> map(Function<T, R> f);
|
||||
|
||||
/**
|
||||
* Matches the Result, either success or error, and supplies the appropriate Consumer with the value or error.
|
||||
|
@ -230,7 +230,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param onSuccess the Consumer to pass the value of a successful Result to
|
||||
* @param onError the Consumer to pass the error from an error Result to
|
||||
*/
|
||||
public abstract void match(Consumer<T> onSuccess, Consumer<Throwable> onError);
|
||||
void match(Consumer<T> onSuccess, Consumer<Throwable> onError);
|
||||
|
||||
/**
|
||||
* Wraps the value within the Result in a Maybe, either a Just if the predicate is true, or Nothing.
|
||||
|
@ -238,7 +238,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param predicate the test to decide
|
||||
* @return a Result containing a Maybe that may or may not contain a value
|
||||
*/
|
||||
public abstract Result<Maybe<T>> maybe(Predicate<T> predicate);
|
||||
Result<Maybe<T>> maybe(Predicate<T> predicate);
|
||||
|
||||
/**
|
||||
* Provide the value within the Result, if it is a success, to the Consumer, and returns this Result.
|
||||
|
@ -246,7 +246,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param consumer the Consumer to the value if a success
|
||||
* @return this Result
|
||||
*/
|
||||
public abstract Result<T> peek(Consumer<T> consumer);
|
||||
Result<T> peek(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Provide a way to attempt to recover from an error state.
|
||||
|
@ -254,7 +254,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param f the function to recover from the error
|
||||
* @return a new Result, either a Success, or if recovery is not possible an other Err.
|
||||
*/
|
||||
public abstract Result<T> recover(Function<Throwable, Result<T>> f);
|
||||
Result<T> recover(Function<Throwable, Result<T>> f);
|
||||
|
||||
/**
|
||||
* A handler for error states.
|
||||
|
@ -264,7 +264,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
*
|
||||
* @param errorConsumer the consumer to handle the error
|
||||
*/
|
||||
public abstract void onError(Consumer<Throwable> errorConsumer);
|
||||
void onError(Consumer<Throwable> errorConsumer);
|
||||
|
||||
/**
|
||||
* Maps a Success Result to another Result using a Callable that is able to throw a checked exception.
|
||||
|
@ -284,7 +284,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param <R> the type of the final Result
|
||||
* @return a new Result
|
||||
*/
|
||||
public abstract <R> Result<R> andThen(Function<T, Callable<R>> f);
|
||||
<R> Result<R> andThen(Function<T, Callable<R>> f);
|
||||
|
||||
/**
|
||||
* Perform the continuation with the current Result value then return the current Result, assuming there was no
|
||||
|
@ -304,7 +304,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param f the function to map the Success value into the result continuation
|
||||
* @return the Result or a new error Result
|
||||
*/
|
||||
public abstract Result<T> thenWith(Function<T, WithResultContinuation<T>> f);
|
||||
Result<T> thenWith(Function<T, WithResultContinuation<T>> f);
|
||||
|
||||
/**
|
||||
* Reduce two Results of the same type into one using the reducing function provided.
|
||||
|
@ -316,5 +316,5 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @param operator the function to combine the values the Results
|
||||
* @return a Result containing the combination of the two Results
|
||||
*/
|
||||
public abstract Result<T> reduce(Result<T> identify, BinaryOperator<T> operator);
|
||||
Result<T> reduce(Result<T> identify, BinaryOperator<T> operator);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import java.util.function.Predicate;
|
|||
* @param <T> the type of the value in the Result
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings("methodcount")
|
||||
@SuppressWarnings({"methodcount", "PMD.CyclomaticComplexity"})
|
||||
class Success<T> implements Result<T> {
|
||||
|
||||
private final T value;
|
||||
|
@ -53,8 +53,13 @@ class Success<T> implements Result<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"illegalcatch", "PMD.AvoidCatchingThrowable"})
|
||||
public <R> Result<R> map(final Function<T, R> f) {
|
||||
return success(f.apply(value));
|
||||
try {
|
||||
return success(f.apply(this.value));
|
||||
} catch (Throwable e) {
|
||||
return err(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,6 +31,8 @@ package net.kemitix.mon.result;
|
|||
*/
|
||||
public final class UnexpectedErrorResultException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 959355287011172256L;
|
||||
|
||||
private UnexpectedErrorResultException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
|
|
@ -35,10 +35,18 @@ public interface WithResultContinuation<T> {
|
|||
*
|
||||
* @throws Exception to replace the current Result with an error
|
||||
*/
|
||||
public abstract void run() throws Exception;
|
||||
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
|
||||
void run() throws Exception;
|
||||
|
||||
@SuppressWarnings({"illegalcatch", "javadocmethod"})
|
||||
public default Result<T> call(final Result<T> currentResult) {
|
||||
/**
|
||||
* Internal. Called when the result of the previous {@link Result} is a
|
||||
* {@link Success}.
|
||||
*
|
||||
* @param currentResult the previous result.
|
||||
* @return the previous result if no exceptions thrown, or an {@link Err}
|
||||
*/
|
||||
@SuppressWarnings({"illegalcatch", "javadocmethod", "PMD.AvoidCatchingThrowable"})
|
||||
default Result<T> call(final Result<T> currentResult) {
|
||||
try {
|
||||
run();
|
||||
} catch (Throwable e) {
|
||||
|
|
|
@ -41,8 +41,8 @@ import java.util.function.Function;
|
|||
@EqualsAndHashCode
|
||||
class GeneralisedTree<T> implements Tree<T>, TreeMapper<T> {
|
||||
|
||||
private final T item;
|
||||
private final List<Tree<T>> subTrees;
|
||||
private transient final T item;
|
||||
private transient final List<Tree<T>> subTrees;
|
||||
|
||||
/**
|
||||
* Creates a new tree.
|
||||
|
|
|
@ -43,9 +43,9 @@ import java.util.stream.Collectors;
|
|||
@SuppressWarnings("methodcount")
|
||||
class MutableTree<T> implements Tree<T>, TreeMapper<T> {
|
||||
|
||||
private final List<MutableTree<T>> mySubTrees = new ArrayList<>();
|
||||
private transient final List<MutableTree<T>> mySubTrees = new ArrayList<>();
|
||||
|
||||
private T item;
|
||||
private transient T item;
|
||||
|
||||
/**
|
||||
* Create a new {@link MutableTree}.
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.function.Function;
|
|||
*/
|
||||
class MutableTreeBuilder<T> implements TreeBuilder<T> {
|
||||
|
||||
private final MutableTree<T> root;
|
||||
private transient final MutableTree<T> root;
|
||||
|
||||
/**
|
||||
* Create empty tree builder.
|
||||
|
|
|
@ -47,7 +47,7 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
|||
*
|
||||
* @return a empty generalised tree
|
||||
*/
|
||||
public static <R> Tree<R> leaf(final R item) {
|
||||
static <R> Tree<R> leaf(final R item) {
|
||||
return new GeneralisedTree<>(item, Collections.emptyList());
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
|||
* @param <R> the type of the item
|
||||
* @return a leaf node of a generalised tree
|
||||
*/
|
||||
public static <R> Tree<R> of(final R item, final Collection<Tree<R>> subtrees) {
|
||||
static <R> Tree<R> of(final R item, final Collection<Tree<R>> subtrees) {
|
||||
return new GeneralisedTree<>(item, subtrees);
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
|||
*/
|
||||
@SuppressFBWarnings(value = "UP_UNUSED_PARAMETER",
|
||||
justification = "Use the type parameter to fingerprint the return type")
|
||||
public static <B> TreeBuilder<B> builder(final Class<B> type) {
|
||||
static <B> TreeBuilder<B> builder(final Class<B> type) {
|
||||
return new MutableTreeBuilder<>();
|
||||
}
|
||||
|
||||
|
@ -85,26 +85,26 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
|||
*
|
||||
* @return a TreeBuilder
|
||||
*/
|
||||
public static <B> TreeBuilder<B> builder(final Tree<B> tree) {
|
||||
static <B> TreeBuilder<B> builder(final Tree<B> tree) {
|
||||
return new MutableTreeBuilder<>(MutableTree.of(tree));
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract <R> Tree<R> map(Function<T, R> f);
|
||||
<R> Tree<R> map(Function<T, R> f);
|
||||
|
||||
/**
|
||||
* Return the item within the node of the tree, if present.
|
||||
*
|
||||
* @return a Maybe containing the item
|
||||
*/
|
||||
public abstract Maybe<T> item();
|
||||
Maybe<T> item();
|
||||
|
||||
/**
|
||||
* Count the number of item in the tree, including subtrees.
|
||||
*
|
||||
* @return the sum of the subtrees, plus 1 if there is an item in this node
|
||||
*/
|
||||
public default int count() {
|
||||
default int count() {
|
||||
return item().matchValue(x -> 1, () -> 0)
|
||||
+ subTrees().stream().mapToInt(Tree::count).sum();
|
||||
}
|
||||
|
@ -114,5 +114,5 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
|||
*
|
||||
* @return a list of Trees
|
||||
*/
|
||||
public abstract List<Tree<T>> subTrees();
|
||||
List<Tree<T>> subTrees();
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public interface TreeBuilder<T> {
|
|||
*
|
||||
* @return a {@link Tree}
|
||||
*/
|
||||
public abstract Tree<T> build();
|
||||
Tree<T> build();
|
||||
|
||||
/**
|
||||
* Set the current {@link Tree}'s item.
|
||||
|
@ -48,7 +48,7 @@ public interface TreeBuilder<T> {
|
|||
*
|
||||
* @return the TreeBuilder
|
||||
*/
|
||||
public abstract TreeBuilder<T> item(T item);
|
||||
TreeBuilder<T> item(T item);
|
||||
|
||||
/**
|
||||
* Adds the subtree to the current tree.
|
||||
|
@ -57,7 +57,7 @@ public interface TreeBuilder<T> {
|
|||
*
|
||||
* @return the TreeBuilder
|
||||
*/
|
||||
public abstract TreeBuilder<T> add(Tree<T> subtree);
|
||||
TreeBuilder<T> add(Tree<T> subtree);
|
||||
|
||||
/**
|
||||
* Add the Child item as a subTree.
|
||||
|
@ -65,7 +65,7 @@ public interface TreeBuilder<T> {
|
|||
* @param childItem the item to add as a subtree
|
||||
* @return the TreeBuilder
|
||||
*/
|
||||
public abstract TreeBuilder<T> addChild(T childItem);
|
||||
TreeBuilder<T> addChild(T childItem);
|
||||
|
||||
/**
|
||||
* Add all the child items as subTrees.
|
||||
|
@ -73,7 +73,7 @@ public interface TreeBuilder<T> {
|
|||
* @param children the items to add as a subtree
|
||||
* @return the TreeBuilder
|
||||
*/
|
||||
public default TreeBuilder<T> addChildren(List<T> children) {
|
||||
default TreeBuilder<T> addChildren(List<T> children) {
|
||||
children.forEach(this::addChild);
|
||||
return this;
|
||||
}
|
||||
|
@ -84,5 +84,5 @@ public interface TreeBuilder<T> {
|
|||
* @param childItem the item of search the subtrees for
|
||||
* @return a Maybe containing the TreeBuilder for the subtree, or Nothing if there child item is not found
|
||||
*/
|
||||
public abstract Maybe<TreeBuilder<T>> select(T childItem);
|
||||
Maybe<TreeBuilder<T>> select(T childItem);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ interface TreeMapper<T> {
|
|||
*
|
||||
* @return a List of mapped sub-trees
|
||||
*/
|
||||
public default <R> List<Tree<R>> mapTrees(
|
||||
default <R> List<Tree<R>> mapTrees(
|
||||
final Function<T, R> f,
|
||||
final List<Tree<T>> trees
|
||||
) {
|
||||
|
|
|
@ -144,7 +144,7 @@ class ResultTest implements WithAssertions {
|
|||
}
|
||||
|
||||
@Test
|
||||
void okay_whenMap_isOkay() {
|
||||
void okay_whenMapToOkay_isOkay() {
|
||||
//given
|
||||
final Result<Integer> okResult = Result.ok(1);
|
||||
//when
|
||||
|
@ -157,6 +157,22 @@ class ResultTest implements WithAssertions {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void okay_whenMapToError_isError() {
|
||||
//given
|
||||
final Result<Integer> okResult = Result.ok(1);
|
||||
//when
|
||||
final Result<String> result = okResult.map(value -> {
|
||||
throw new RuntimeException("map error");
|
||||
});
|
||||
//then
|
||||
assertThat(result.isError()).isTrue();
|
||||
result.match(
|
||||
success -> fail("not an success"),
|
||||
error -> assertThat(error).hasMessage("map error")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void error_whenMap_isError() {
|
||||
//given
|
||||
|
|
Loading…
Reference in a new issue