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>
|
<version>2.3.0</version>
|
||||||
|
|
||||||
<name>Mon</name>
|
<name>Mon</name>
|
||||||
<description>TypeAlias, Result and Maybe for Java</description>
|
<description>Wrapper, TypeAlias, Result, Lazy, Maybe and combinators for Java</description>
|
||||||
|
|
||||||
<issueManagement>
|
<issueManagement>
|
||||||
<url>https://github.com/kemitix/mon/issues</url>
|
<url>https://github.com/kemitix/mon/issues</url>
|
||||||
|
@ -38,9 +38,9 @@
|
||||||
<assertj.version>3.19.0</assertj.version>
|
<assertj.version>3.19.0</assertj.version>
|
||||||
<lombok.version>1.18.18</lombok.version>
|
<lombok.version>1.18.18</lombok.version>
|
||||||
<tiles-maven-plugin.version>2.19</tiles-maven-plugin.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>
|
<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-maven-plugin.version>1.6.4</pitest-maven-plugin.version>
|
||||||
<pitest-junit5-plugin.version>0.12</pitest-junit5-plugin.version>
|
<pitest-junit5-plugin.version>0.12</pitest-junit5-plugin.version>
|
||||||
<spotbugs.version>4.1.2</spotbugs.version>
|
<spotbugs.version>4.1.2</spotbugs.version>
|
||||||
|
@ -105,7 +105,14 @@
|
||||||
<extensions>true</extensions>
|
<extensions>true</extensions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<tiles>
|
<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>
|
<tile>net.kemitix.checkstyle:tile:${kemitix-checkstyle.version}</tile>
|
||||||
</tiles>
|
</tiles>
|
||||||
</configuration>
|
</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
|
* @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
|
* @param <T> the type of the alias
|
||||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("abstractclassname")
|
@SuppressWarnings({"abstractclassname", "PMD.AbstractClassWithoutAbstractMethod"})
|
||||||
public abstract class TypeAlias<T> {
|
public abstract class TypeAlias<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,6 +37,6 @@ public interface Wrapper<T> {
|
||||||
*
|
*
|
||||||
* @return the value
|
* @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
|
* @return a partially applied Function that will take an argument and return the result of applying it to the
|
||||||
* function parameter
|
* function parameter
|
||||||
*/
|
*/
|
||||||
public static <T, R> Function<T, R> decorate(
|
static <T, R> Function<T, R> decorate(
|
||||||
final Function<T, R> function,
|
final Function<T, R> function,
|
||||||
final BiConsumer<T, R> after
|
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
|
* @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 -> {
|
return function -> after -> argument -> {
|
||||||
final R result = function.apply(argument);
|
final R result = function.apply(argument);
|
||||||
after.accept(argument, result);
|
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
|
* @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 Function<T, R> function,
|
||||||
final BiConsumer<Executable<R>, T> around
|
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
|
* @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.
|
* 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 -> {
|
return function -> around -> argument -> {
|
||||||
final AtomicReference<R> result = new AtomicReference<>();
|
final AtomicReference<R> result = new AtomicReference<>();
|
||||||
final Executable<R> callback = () -> {
|
final Executable<R> callback = () -> {
|
||||||
|
@ -89,13 +89,13 @@ public interface Around<T, R> extends
|
||||||
* @param <R> the return type of the function
|
* @param <R> the return type of the function
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public static interface Executable<R> {
|
interface Executable<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the function.
|
* Executes the function.
|
||||||
*
|
*
|
||||||
* @return the result of applying 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
|
* @return a partially applied Function that will take an argument and return the result of applying it to the
|
||||||
* function parameter
|
* function parameter
|
||||||
*/
|
*/
|
||||||
public static <T, R> Function<T, R> decorate(
|
static <T, R> Function<T, R> decorate(
|
||||||
final Consumer<T> before,
|
final Consumer<T> before,
|
||||||
final Function<T, R> function
|
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
|
* @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 -> {
|
return before -> function -> argument -> {
|
||||||
before.accept(argument);
|
before.accept(argument);
|
||||||
return function.apply(argument);
|
return function.apply(argument);
|
||||||
|
|
|
@ -43,7 +43,7 @@ public interface Either<L, R> {
|
||||||
* @param <R> the type of the right value
|
* @param <R> the type of the right value
|
||||||
* @return a Either holding the left 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);
|
return new Left<>(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ public interface Either<L, R> {
|
||||||
* @param <R> the type of the right value
|
* @param <R> the type of the right value
|
||||||
* @return a Either holding 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);
|
return new Right<>(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,14 +64,14 @@ public interface Either<L, R> {
|
||||||
*
|
*
|
||||||
* @return true if this Either is a left
|
* @return true if this Either is a left
|
||||||
*/
|
*/
|
||||||
public abstract boolean isLeft();
|
boolean isLeft();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the Either holds a right value.
|
* Checks if the Either holds a right value.
|
||||||
*
|
*
|
||||||
* @return true if this Either is a right
|
* @return true if this Either is a right
|
||||||
*/
|
*/
|
||||||
public abstract boolean isRight();
|
boolean isRight();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches the Either, invoking the correct Consumer.
|
* 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 onLeft the Consumer to invoke when the Either is a left
|
||||||
* @param onRight the Consumer to invoke when the Either is a right
|
* @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.
|
* 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
|
* @param <T> the type to change the left value to
|
||||||
* @return a new Either
|
* @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.
|
* 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
|
* @param <T> the type to change the right value to
|
||||||
* @return a new Either
|
* @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.
|
* 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
|
* @param <T> the type to change the left value to
|
||||||
* @return a new Either if is a Left, else this
|
* @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.
|
* 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
|
* @param <T> the type to change the right value to
|
||||||
* @return a new Either if is a Right, else this
|
* @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
|
* 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
|
* @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
|
* 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
|
* @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
|
* @param <R> the type of the value
|
||||||
* @return a Lazy wrapper of the Supplier
|
* @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);
|
return new LazySupplier<>(supplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public interface Lazy<T> extends Functor<T, Lazy<?>> {
|
||||||
*
|
*
|
||||||
* @return true if the value has been evaluated.
|
* @return true if the value has been evaluated.
|
||||||
*/
|
*/
|
||||||
public abstract boolean isEvaluated();
|
boolean isEvaluated();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value, evaluating it if necessary.
|
* The value, evaluating it if necessary.
|
||||||
|
@ -60,8 +60,8 @@ public interface Lazy<T> extends Functor<T, Lazy<?>> {
|
||||||
*
|
*
|
||||||
* @return the evaluated value
|
* @return the evaluated value
|
||||||
*/
|
*/
|
||||||
public abstract T value();
|
T value();
|
||||||
|
|
||||||
@Override
|
@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> {
|
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 AtomicBoolean evaluated = new AtomicBoolean(false);
|
||||||
private final AtomicReference<T> value = new AtomicReference<>();
|
private transient final AtomicReference<T> value = new AtomicReference<>();
|
||||||
private final Object lock = new Object();
|
private transient final Object lock = new Object();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Lazy wrapper for the Supplier.
|
* 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
|
* @param <T> the type of the value
|
||||||
* @return a Maybe 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);
|
return new Just<>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
||||||
* @return an empty Maybe
|
* @return an empty Maybe
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> Maybe<T> nothing() {
|
static <T> Maybe<T> nothing() {
|
||||||
return (Maybe<T>) Nothing.INSTANCE;
|
return (Maybe<T>) Nothing.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
||||||
* @param <T> the type of the value
|
* @param <T> the type of the value
|
||||||
* @return a Maybe, either a Just, or Nothing if value is null
|
* @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) {
|
if (value == null) {
|
||||||
return nothing();
|
return nothing();
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
||||||
* @param <T> the type of the stream
|
* @param <T> the type of the stream
|
||||||
* @return a Maybe containing the first item in 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()
|
return stream.findFirst()
|
||||||
.map(Maybe::just)
|
.map(Maybe::just)
|
||||||
.orElseGet(Maybe::nothing);
|
.orElseGet(Maybe::nothing);
|
||||||
|
@ -99,14 +99,14 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
||||||
*
|
*
|
||||||
* @return true if the Maybe is a Just
|
* @return true if the Maybe is a Just
|
||||||
*/
|
*/
|
||||||
public abstract boolean isJust();
|
boolean isJust();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the Maybe is Nothing.
|
* Checks if the Maybe is Nothing.
|
||||||
*
|
*
|
||||||
* @return true 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.
|
* 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
|
* @param <R> the type of the value in the final maybe
|
||||||
* @return a Maybe with the mapped value
|
* @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
|
@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.
|
* 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
|
* @param supplier supplier for an alternate value
|
||||||
* @return a Maybe
|
* @return a Maybe
|
||||||
*/
|
*/
|
||||||
public abstract T orElseGet(Supplier<T> supplier);
|
T orElseGet(Supplier<T> supplier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A value to use when Maybe is Nothing.
|
* 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
|
* @param otherValue an alternate value
|
||||||
* @return the value of the Maybe if a Just, otherwise the otherValue
|
* @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}.
|
* Convert the Maybe to an {@link Optional}.
|
||||||
*
|
*
|
||||||
* @return an Optional containing a value for a Just, or empty for a Nothing
|
* @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.
|
* 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
|
* @return the value of the Maybe if a Just
|
||||||
* @throws X if the Maybe is nothing
|
* @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.
|
* Converts the Maybe into either a single value stream or an empty stream.
|
||||||
*
|
*
|
||||||
* @return a Stream containing the value or nothing.
|
* @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.
|
* 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
|
* @param predicate the test
|
||||||
* @return the Maybe, or Nothing if the test returns false
|
* @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.
|
* 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
|
* @param consumer the Consumer to the value if present
|
||||||
* @return this Maybe
|
* @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.
|
* Run the runnable if the Maybe is a Nothing, otherwise do nothing.
|
||||||
*
|
*
|
||||||
* @param runnable the runnable to call if this is a 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.
|
* 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 justMatcher the Consumer to pass the value of a Just to
|
||||||
* @param nothingMatcher the Runnable to call if the Maybe is a Nothing
|
* @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.
|
* 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
|
* @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.
|
* 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
|
* @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
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings({"unchecked", "PMD.AvoidDuplicateLiterals"})
|
||||||
public <R> Maybe<R> flatMap(final Function<T, Maybe<R>> f) {
|
public <R> Maybe<R> flatMap(final Function<T, Maybe<R>> f) {
|
||||||
return (Maybe<R>) INSTANCE;
|
return (Maybe<R>) INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ package net.kemitix.mon.result;
|
||||||
*/
|
*/
|
||||||
public final class CheckedErrorResultException extends Exception {
|
public final class CheckedErrorResultException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 6388860431020999870L;
|
||||||
|
|
||||||
private CheckedErrorResultException(final Throwable cause) {
|
private CheckedErrorResultException(final Throwable cause) {
|
||||||
super(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
|
* @param <T> the type of the value in the Result if it has been a success
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@SuppressWarnings("methodcount")
|
@SuppressWarnings({"methodcount", "PMD.CyclomaticComplexity"})
|
||||||
class Err<T> implements Result<T> {
|
class Err<T> implements Result<T> {
|
||||||
|
|
||||||
private final Throwable error;
|
private final Throwable error;
|
||||||
|
|
|
@ -30,6 +30,8 @@ package net.kemitix.mon.result;
|
||||||
*/
|
*/
|
||||||
public final class ErrorResultException extends RuntimeException {
|
public final class ErrorResultException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -949688489831104844L;
|
||||||
|
|
||||||
private ErrorResultException(final Throwable cause) {
|
private ErrorResultException(final Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import java.util.function.*;
|
||||||
* @param <T> the type of the result when a success
|
* @param <T> the type of the result when a success
|
||||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("methodcount")
|
@SuppressWarnings({"methodcount", "PMD.TooManyMethods"})
|
||||||
public interface Result<T> extends Functor<T, Result<?>> {
|
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
|
* @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
|
* @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)
|
return maybe.map(Result::ok)
|
||||||
.orElseGet(() -> Result.error(error.get()));
|
.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
|
* @param <T> the type had the result been a success
|
||||||
* @return an error Result
|
* @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);
|
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
|
* @param <T> the type had the result been a success
|
||||||
* @return an error Result
|
* @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);
|
return new Err<>(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,11 +78,11 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
||||||
* @param <T> the type of the value
|
* @param <T> the type of the value
|
||||||
* @return a Result
|
* @return a Result
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("illegalcatch")
|
@SuppressWarnings({"illegalcatch", "PMD.AvoidCatchingThrowable", "PMD.AvoidDuplicateLiterals"})
|
||||||
public default <T> Result<T> result(final Callable<T> callable) {
|
default <T> Result<T> result(final Callable<T> callable) {
|
||||||
try {
|
try {
|
||||||
return Result.ok(callable.call());
|
return Result.ok(callable.call());
|
||||||
} catch (final Exception e) {
|
} catch (final Throwable e) {
|
||||||
return Result.error(e);
|
return Result.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,11 +94,11 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
||||||
* @param <T> the type of the value
|
* @param <T> the type of the value
|
||||||
* @return a Result
|
* @return a Result
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("illegalcatch")
|
@SuppressWarnings({"illegalcatch", "PMD.AvoidCatchingThrowable"})
|
||||||
public static <T> Result<T> of(final Callable<T> callable) {
|
static <T> Result<T> of(final Callable<T> callable) {
|
||||||
try {
|
try {
|
||||||
return Result.ok(callable.call());
|
return Result.ok(callable.call());
|
||||||
} catch (final Exception e) {
|
} catch (final Throwable e) {
|
||||||
return Result.error(e);
|
return Result.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
||||||
* @param <T> the type of the value
|
* @param <T> the type of the value
|
||||||
* @return a successful Result
|
* @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);
|
return new Success<>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
||||||
* @param <T> the type of the value
|
* @param <T> the type of the value
|
||||||
* @return a successful Result
|
* @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);
|
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
|
* @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
|
* @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 {
|
try {
|
||||||
return Maybe.just(result.orElseThrow());
|
return Maybe.just(result.orElseThrow());
|
||||||
} catch (final CheckedErrorResultException throwable) {
|
} catch (final CheckedErrorResultException throwable) {
|
||||||
|
@ -148,7 +148,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
||||||
* @return the value if a success
|
* @return the value if a success
|
||||||
* @throws CheckedErrorResultException if the result is an error
|
* @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.
|
* 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
|
* @return the value if a success
|
||||||
* @throws E if the result is an error
|
* @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}.
|
* Extracts the successful value from the result, or throws the error in a {@link UnexpectedErrorResultException}.
|
||||||
*
|
*
|
||||||
* @return the value if a success
|
* @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.
|
* 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
|
* 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.
|
* 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))
|
return maybeResult.orElseGet(() -> Result.ok(null))
|
||||||
.flatMap(value -> Result.ok(Maybe.maybe(value)));
|
.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
|
* @param <R> the type of the value withing the Result of the mapping function
|
||||||
* @return a Result
|
* @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.
|
* 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
|
* @param <R> the type of the updated Result
|
||||||
* @return a new Maybe within a 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 Result<Maybe<T>> maybeResult,
|
||||||
final Function<Maybe<T>, Result<Maybe<R>>> f
|
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.
|
* @return true if the Result is an error.
|
||||||
*/
|
*/
|
||||||
public abstract boolean isError();
|
boolean isError();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the Result is a success.
|
* Checks if the Result is a success.
|
||||||
*
|
*
|
||||||
* @return true if the Result is a success.
|
* @return true if the Result is a success.
|
||||||
*/
|
*/
|
||||||
public abstract boolean isOkay();
|
boolean isOkay();
|
||||||
|
|
||||||
@Override
|
@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.
|
* 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 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
|
* @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.
|
* 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
|
* @param predicate the test to decide
|
||||||
* @return a Result containing a Maybe that may or may not contain a value
|
* @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.
|
* 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
|
* @param consumer the Consumer to the value if a success
|
||||||
* @return this Result
|
* @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.
|
* 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
|
* @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.
|
* @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.
|
* 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
|
* @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.
|
* 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
|
* @param <R> the type of the final Result
|
||||||
* @return a new 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
|
* 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
|
* @param f the function to map the Success value into the result continuation
|
||||||
* @return the Result or a new error Result
|
* @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.
|
* 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
|
* @param operator the function to combine the values the Results
|
||||||
* @return a Result containing the combination of the two 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
|
* @param <T> the type of the value in the Result
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@SuppressWarnings("methodcount")
|
@SuppressWarnings({"methodcount", "PMD.CyclomaticComplexity"})
|
||||||
class Success<T> implements Result<T> {
|
class Success<T> implements Result<T> {
|
||||||
|
|
||||||
private final T value;
|
private final T value;
|
||||||
|
@ -53,8 +53,13 @@ class Success<T> implements Result<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings({"illegalcatch", "PMD.AvoidCatchingThrowable"})
|
||||||
public <R> Result<R> map(final Function<T, R> f) {
|
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
|
@Override
|
||||||
|
|
|
@ -31,6 +31,8 @@ package net.kemitix.mon.result;
|
||||||
*/
|
*/
|
||||||
public final class UnexpectedErrorResultException extends RuntimeException {
|
public final class UnexpectedErrorResultException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 959355287011172256L;
|
||||||
|
|
||||||
private UnexpectedErrorResultException(final Throwable cause) {
|
private UnexpectedErrorResultException(final Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,18 @@ public interface WithResultContinuation<T> {
|
||||||
*
|
*
|
||||||
* @throws Exception to replace the current Result with an error
|
* @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 {
|
try {
|
||||||
run();
|
run();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
@ -41,8 +41,8 @@ import java.util.function.Function;
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
class GeneralisedTree<T> implements Tree<T>, TreeMapper<T> {
|
class GeneralisedTree<T> implements Tree<T>, TreeMapper<T> {
|
||||||
|
|
||||||
private final T item;
|
private transient final T item;
|
||||||
private final List<Tree<T>> subTrees;
|
private transient final List<Tree<T>> subTrees;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new tree.
|
* Creates a new tree.
|
||||||
|
|
|
@ -43,9 +43,9 @@ import java.util.stream.Collectors;
|
||||||
@SuppressWarnings("methodcount")
|
@SuppressWarnings("methodcount")
|
||||||
class MutableTree<T> implements Tree<T>, TreeMapper<T> {
|
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}.
|
* Create a new {@link MutableTree}.
|
||||||
|
|
|
@ -35,7 +35,7 @@ import java.util.function.Function;
|
||||||
*/
|
*/
|
||||||
class MutableTreeBuilder<T> implements TreeBuilder<T> {
|
class MutableTreeBuilder<T> implements TreeBuilder<T> {
|
||||||
|
|
||||||
private final MutableTree<T> root;
|
private transient final MutableTree<T> root;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create empty tree builder.
|
* Create empty tree builder.
|
||||||
|
|
|
@ -47,7 +47,7 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
||||||
*
|
*
|
||||||
* @return a empty generalised 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());
|
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
|
* @param <R> the type of the item
|
||||||
* @return a leaf node of a generalised tree
|
* @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);
|
return new GeneralisedTree<>(item, subtrees);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
||||||
*/
|
*/
|
||||||
@SuppressFBWarnings(value = "UP_UNUSED_PARAMETER",
|
@SuppressFBWarnings(value = "UP_UNUSED_PARAMETER",
|
||||||
justification = "Use the type parameter to fingerprint the return type")
|
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<>();
|
return new MutableTreeBuilder<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,26 +85,26 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
||||||
*
|
*
|
||||||
* @return a TreeBuilder
|
* @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));
|
return new MutableTreeBuilder<>(MutableTree.of(tree));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 the item within the node of the tree, if present.
|
||||||
*
|
*
|
||||||
* @return a Maybe containing the item
|
* @return a Maybe containing the item
|
||||||
*/
|
*/
|
||||||
public abstract Maybe<T> item();
|
Maybe<T> item();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the number of item in the tree, including subtrees.
|
* 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
|
* @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)
|
return item().matchValue(x -> 1, () -> 0)
|
||||||
+ subTrees().stream().mapToInt(Tree::count).sum();
|
+ subTrees().stream().mapToInt(Tree::count).sum();
|
||||||
}
|
}
|
||||||
|
@ -114,5 +114,5 @@ public interface Tree<T> extends Functor<T, Tree<?>> {
|
||||||
*
|
*
|
||||||
* @return a list of Trees
|
* @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}
|
* @return a {@link Tree}
|
||||||
*/
|
*/
|
||||||
public abstract Tree<T> build();
|
Tree<T> build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current {@link Tree}'s item.
|
* Set the current {@link Tree}'s item.
|
||||||
|
@ -48,7 +48,7 @@ public interface TreeBuilder<T> {
|
||||||
*
|
*
|
||||||
* @return the TreeBuilder
|
* @return the TreeBuilder
|
||||||
*/
|
*/
|
||||||
public abstract TreeBuilder<T> item(T item);
|
TreeBuilder<T> item(T item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the subtree to the current tree.
|
* Adds the subtree to the current tree.
|
||||||
|
@ -57,7 +57,7 @@ public interface TreeBuilder<T> {
|
||||||
*
|
*
|
||||||
* @return the TreeBuilder
|
* @return the TreeBuilder
|
||||||
*/
|
*/
|
||||||
public abstract TreeBuilder<T> add(Tree<T> subtree);
|
TreeBuilder<T> add(Tree<T> subtree);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the Child item as a 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
|
* @param childItem the item to add as a subtree
|
||||||
* @return the TreeBuilder
|
* @return the TreeBuilder
|
||||||
*/
|
*/
|
||||||
public abstract TreeBuilder<T> addChild(T childItem);
|
TreeBuilder<T> addChild(T childItem);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all the child items as subTrees.
|
* Add all the child items as subTrees.
|
||||||
|
@ -73,7 +73,7 @@ public interface TreeBuilder<T> {
|
||||||
* @param children the items to add as a subtree
|
* @param children the items to add as a subtree
|
||||||
* @return the TreeBuilder
|
* @return the TreeBuilder
|
||||||
*/
|
*/
|
||||||
public default TreeBuilder<T> addChildren(List<T> children) {
|
default TreeBuilder<T> addChildren(List<T> children) {
|
||||||
children.forEach(this::addChild);
|
children.forEach(this::addChild);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -84,5 +84,5 @@ public interface TreeBuilder<T> {
|
||||||
* @param childItem the item of search the subtrees for
|
* @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
|
* @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
|
* @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 Function<T, R> f,
|
||||||
final List<Tree<T>> trees
|
final List<Tree<T>> trees
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -144,7 +144,7 @@ class ResultTest implements WithAssertions {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void okay_whenMap_isOkay() {
|
void okay_whenMapToOkay_isOkay() {
|
||||||
//given
|
//given
|
||||||
final Result<Integer> okResult = Result.ok(1);
|
final Result<Integer> okResult = Result.ok(1);
|
||||||
//when
|
//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
|
@Test
|
||||||
void error_whenMap_isError() {
|
void error_whenMap_isError() {
|
||||||
//given
|
//given
|
||||||
|
|
Loading…
Reference in a new issue