diff --git a/README.md b/README.md
index 1a03777..9e232f3 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,19 @@
Mon
===
-TypeAlias for Java
+TypeAlias, Maybe and Result for Java
-[![GitHub release](https://img.shields.io/github/release/kemitix/mon.svg)]()
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/d57096b0639d496aba9a7e43e7cf5b4c)](https://www.codacy.com/app/kemitix/mon?utm_source=github.com&utm_medium=referral&utm_content=kemitix/mon&utm_campaign=Badge_Grade)
-[![Build Status](https://travis-ci.org/kemitix/mon.svg?branch=master)](https://travis-ci.org/kemitix/mon)
-[![Coverage Status](https://coveralls.io/repos/github/kemitix/mon/badge.svg?branch=master)](https://coveralls.io/github/kemitix/mon?branch=master)
-[![codecov](https://codecov.io/gh/kemitix/mon/branch/master/graph/badge.svg)](https://codecov.io/gh/kemitix/mon)
+[![Sonatype Nexus (Releases)](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/#search|ga|1|g%3A"net.kemitix"%20AND%20a%3A"mon")
+
+[![SonarQube Coverage](https://img.shields.io/sonar/https/sonarcloud.io/net.kemitix%3Amon/coverage.svg?style=for-the-badge)](https://sonarcloud.io/dashboard?id=net.kemitix%3Amon)
+[![SonarQube Tech Debt](https://img.shields.io/sonar/https/sonarcloud.io/net.kemitix%3Amon/tech_debt.svg?style=for-the-badge)](https://sonarcloud.io/dashboard?id=net.kemitix%3Amon)
+
+[![Jenkins](https://img.shields.io/jenkins/s/https/jenkins.kemitix.net/job/GitLab/job/kemitix%252Fmon.svg?style=for-the-badge)](https://jenkins.kemitix.net/job/GitLab/job/kemitix%252Fmon/)
+[![Jenkins tests](https://img.shields.io/jenkins/t/https/jenkins.kemitix.net/job/GitLab/job/kemitix%252Fmon.svg?style=for-the-badge)](https://jenkins.kemitix.net/job/GitLab/job/kemitix%252Fmon/)
+[![Jenkins coverage](https://img.shields.io/jenkins/c/https/jenkins.kemitix.net/job/GitLab/job/kemitix%252Fmon.svg?style=for-the-badge)](https://jenkins.kemitix.net/job/GitLab/job/kemitix%252Fmon/)
+
+[![Codacy grade](https://img.shields.io/codacy/grade/d57096b0639d496aba9a7e43e7cf5b4c.svg?style=for-the-badge)](https://app.codacy.com/project/kemitix/mon/dashboard)
## Maven
@@ -15,7 +21,7 @@ TypeAlias for Java
net.kemitix
mon
- 0.4.0
+ 0.6.0
```
@@ -23,6 +29,8 @@ TypeAlias for Java
### TypeAlias
+More of a type-wrapper really. It's as close as I could get to a Haskell type alias in Java.
+
```java
class Goal extends TypeAlias {
private Goal(final String goal) {
@@ -35,43 +43,147 @@ class Goal extends TypeAlias {
```
```java
-Goal goal = Goal.of("goal");
-
-void foo(final Goal goal) {
- System.out.println("The goal is " + goal.getValue());
+class Example {}
+ Goal goal = Goal.of("goal");
+ void foo(final Goal goal) {
+ System.out.println("The goal is " + goal.getValue());
+ }
}
```
-### Maybe (Just & Nothing)
+### Maybe
+
+A non-final substitute for Optional with `peek()` and `stream()` methods.
```java
-assertThat(Maybe.maybe(null)).isEqualTo(Maybe.nothing());
-assertThat(Maybe.maybe(1)).isEqualTo(Maybe.just(1));
-assertThat(Maybe.nothing()
- .orElseGet(() -> 1)).isEqualTo(1);
-assertThat(Maybe.just(1)
- .orElseGet(() -> 2)).isEqualTo(1);
-assertThat(Maybe.nothing()
- .orElse(1)).isEqualTo(1);
-assertThat(Maybe.just(1)
- .orElse(2)).isEqualTo(1);
-assertThat(Maybe.just(1)
- .filter(v -> v > 2)).isEqualTo(Maybe.nothing());
-assertThat(Maybe.just(3)
- .filter(v -> v > 2)).isEqualTo(Maybe.just(3));
-assertThat(Maybe.just(1)
- .toOptional()).isEqualTo(Optional.of(1));
-assertThat(Maybe.nothing()
- .toOptional()).isEqualTo(Optional.empty());
-assertThat(Maybe.fromOptional(Optional.of(1))).isEqualTo(Maybe.just(1));
-assertThat(Maybe.fromOptional(Optional.empty())).isEqualTo(Maybe.nothing());
-final AtomicInteger reference = new AtomicInteger(0);
-assertThat(Maybe.just(1).peek(reference::set)).isEqualTo(Maybe.just(1));
-assertThat(reference).hasValue(1);
-assertThat(Maybe.nothing().peek(v -> reference.incrementAndGet())).isEqualTo(Maybe.nothing());
-assertThat(reference).hasValue(1);
-assertThatCode(() -> Maybe.just(1).orElseThrow(IllegalStateException::new))
- .doesNotThrowAnyException();
-assertThatThrownBy(() -> Maybe.nothing().orElseThrow(IllegalStateException::new))
- .isInstanceOf(IllegalStateException.class);
+class Test {
+ @Test
+ public void maybeTests() {
+ assertThat(Maybe.maybe(null)).isEqualTo(Maybe.nothing());
+ assertThat(Maybe.maybe(1)).isEqualTo(Maybe.just(1));
+ assertThat(Maybe.nothing().orElseGet(() -> 1)).isEqualTo(1);
+ assertThat(Maybe.just(1).orElseGet(() -> 2)).isEqualTo(1);
+ assertThat(Maybe.nothing().orElse(1)).isEqualTo(1);
+ assertThat(Maybe.just(1).orElse(2)).isEqualTo(1);
+ assertThat(Maybe.just(1).filter(v -> v > 2)).isEqualTo(Maybe.nothing());
+ assertThat(Maybe.just(3).filter(v -> v > 2)).isEqualTo(Maybe.just(3));
+ assertThat(Maybe.just(1).toOptional()).isEqualTo(Optional.of(1));
+ assertThat(Maybe.nothing().toOptional()).isEqualTo(Optional.empty());
+ assertThat(Maybe.fromOptional(Optional.of(1))).isEqualTo(Maybe.just(1));
+ assertThat(Maybe.fromOptional(Optional.empty())).isEqualTo(Maybe.nothing());
+ final AtomicInteger reference = new AtomicInteger(0);
+ assertThat(Maybe.just(1).peek(reference::set)).isEqualTo(Maybe.just(1));
+ assertThat(reference).hasValue(1);
+ assertThat(Maybe.nothing().peek(v -> reference.incrementAndGet())).isEqualTo(Maybe.nothing());
+ assertThat(reference).hasValue(1);
+ assertThatCode(() -> Maybe.just(1).orElseThrow(IllegalStateException::new)).doesNotThrowAnyException();
+ assertThatThrownBy(() -> Maybe.nothing().orElseThrow(IllegalStateException::new)).isInstanceOf(IllegalStateException.class);
+ assertThat(Maybe.just(1).stream()).containsExactly(1);
+ assertThat(Maybe.nothing().stream()).isEmpty();
+ }
+}
+```
+
+### Result
+
+A container for method return values that may raise an Exception. Useful for when a checked exceptions can't be added
+to the method signature.
+
+```java
+package net.kemitix.mon;
+
+import net.kemitix.mon.result.Result;
+
+import java.io.IOException;
+
+class ResultExample implements Runnable {
+
+ public static void main(String[] args) {
+ new ResultExample().run();
+ }
+
+ @Override
+ public void run() {
+ System.out.println("run");
+ final Result goodResult = goodMethod();
+ if (goodResult.isOkay()) {
+ doGoodThings();
+ }
+ if (goodResult.isError()) {
+ notCalled(0);
+ }
+
+ goodResult.flatMap(number -> convertToString(number))
+ .flatMap(str -> stringLength(str))
+ .match(
+ success -> System.out.format("Length is %s%n", success),
+ error -> System.out.println("Count not determine length")
+ );
+
+ final Result badResult = badMethod();
+ badResult.match(
+ success -> notCalled(success),
+ error -> handleError(error)
+ );
+ }
+
+ private Result goodMethod() {
+ System.out.println("goodMethod");
+ return Result.ok(1);
+ }
+
+ private void doGoodThings() {
+ System.out.println("doGoodThings");
+ }
+
+ private void notCalled(final Integer success) {
+ System.out.println("notCalled");
+ }
+
+ private Result convertToString(final Integer number) {
+ System.out.println("convertToString");
+ return Result.ok(String.valueOf(number));
+ }
+
+ private Result stringLength(final String value) {
+ System.out.println("stringLength");
+ if (value == null) {
+ return Result.error(new NullPointerException("value is null"));
+ }
+ return Result.ok(value.length());
+ }
+
+ // doesn't need to declare "throws IOException"
+ private Result badMethod() {
+ System.out.println("badMethod");
+ return Result.error(new IOException("error"));
+ }
+
+ private void handleError(final Throwable error) {
+ System.out.println("handleError");
+ throw new RuntimeException("Handled exception", error);
+ }
+
+}
+```
+Will output:
+```text
+run
+goodMethod
+doGoodThings
+convertToString
+stringLength
+Length is 1
+badMethod
+handleError
+Exception in thread "main" java.lang.RuntimeException: Handled exception
+ at net.kemitix.mon.ResultExample.handleError(ResultExample.java:72)
+ at net.kemitix.mon.ResultExample.lambda$run$5(ResultExample.java:34)
+ at net.kemitix.mon.result.Err.match(Err.java:56)
+ at net.kemitix.mon.ResultExample.run(ResultExample.java:32)
+ at net.kemitix.mon.ResultExample.main(ResultExample.java:10)
+Caused by: java.io.IOException: error
+ at net.kemitix.mon.ResultExample.badMethod(ResultExample.java:67)
+ at net.kemitix.mon.ResultExample.run(ResultExample.java:31)
+ ... 1 more
```