commit
d3dad6c670
13 changed files with 522 additions and 55 deletions
|
@ -1,6 +1,12 @@
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
0.4.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* Restore public access for `TypeAlias.getValue()`
|
||||||
|
* Add `Maybe`, `Just`, `Nothing`
|
||||||
|
|
||||||
0.3.0
|
0.3.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
36
README.md
36
README.md
|
@ -15,7 +15,7 @@ TypeAlias for Java
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kemitix</groupId>
|
<groupId>net.kemitix</groupId>
|
||||||
<artifactId>mon</artifactId>
|
<artifactId>mon</artifactId>
|
||||||
<version>0.3.0</version>
|
<version>0.4.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -41,3 +41,37 @@ void foo(final Goal goal) {
|
||||||
System.out.println("The goal is " + goal.getValue());
|
System.out.println("The goal is " + goal.getValue());
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Maybe (Just & Nothing)
|
||||||
|
|
||||||
|
```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);
|
||||||
|
```
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -10,7 +10,7 @@
|
||||||
<version>3.2.4</version>
|
<version>3.2.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>mon</artifactId>
|
<artifactId>mon</artifactId>
|
||||||
<version>0.3.0</version>
|
<version>0.4.0</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<junit.version>4.12</junit.version>
|
<junit.version>4.12</junit.version>
|
||||||
|
|
|
@ -34,18 +34,19 @@ import java.util.function.Function;
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param <T> the type of the Functor
|
* @param <T> the type of the Functor
|
||||||
|
* @param <F> the type of the mapped Functor
|
||||||
*
|
*
|
||||||
* @author Tomasz Nurkiewicz (?@?.?)
|
* @author Tomasz Nurkiewicz (?@?.?)
|
||||||
*/
|
*/
|
||||||
public interface Functor<T> {
|
public interface Functor<T, F extends Functor<?, ?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the function to the value within the Functor, returning the result within a Functor.
|
* Applies the function to the value within the Functor, returning the result within a Functor.
|
||||||
*
|
*
|
||||||
* @param f the function to apply
|
* @param f the function to apply
|
||||||
* @param <R> the type of the result of the function
|
* @param <R> the type of the content of the mapped 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
|
||||||
*/
|
*/
|
||||||
<R> Functor<R> map(Function<T, R> f);
|
<R> F map(Function<T, R> f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import java.util.function.Function;
|
||||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
class Identity<T> implements Functor<T> {
|
class Identity<T> implements Functor<T, Identity<?>> {
|
||||||
|
|
||||||
private final T value;
|
private final T value;
|
||||||
|
|
||||||
|
|
94
src/main/java/net/kemitix/mon/Just.java
Normal file
94
src/main/java/net/kemitix/mon/Just.java
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Maybe where a value is present.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the content
|
||||||
|
*
|
||||||
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
public final class Just<T> implements Maybe<T> {
|
||||||
|
|
||||||
|
private final T value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> Maybe<?> map(final Function<T, R> f) {
|
||||||
|
return new Just<>(f.apply(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object other) {
|
||||||
|
return other instanceof Just && Objects.equals(this.value, ((Just) other).value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T orElseGet(final Supplier<T> supplier) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T orElse(final T otherValue) {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Maybe<T> filter(final Predicate<T> predicate) {
|
||||||
|
if (predicate.test(value)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return Maybe.nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<T> toOptional() {
|
||||||
|
return Optional.of(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Maybe<T> peek(final Consumer<T> consumer) {
|
||||||
|
consumer.accept(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void orElseThrow(final Supplier<Exception> e) {
|
||||||
|
// do not throw
|
||||||
|
}
|
||||||
|
}
|
145
src/main/java/net/kemitix/mon/Maybe.java
Normal file
145
src/main/java/net/kemitix/mon/Maybe.java
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A value that may or may not be present.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the content of the Just
|
||||||
|
*
|
||||||
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
|
*/
|
||||||
|
public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Maybe for the value that is present.
|
||||||
|
*
|
||||||
|
* @param value the value, not null
|
||||||
|
* @param <T> the type of the value
|
||||||
|
*
|
||||||
|
* @return a Maybe of the value
|
||||||
|
*/
|
||||||
|
static <T> Maybe<T> just(@NonNull final T value) {
|
||||||
|
return new Just<>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Maybe for a lack of a value.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the missing value
|
||||||
|
*
|
||||||
|
* @return an empty Maybe
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static <T> Maybe<T> nothing() {
|
||||||
|
return (Maybe<T>) Nothing.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Maybe for the value that may or may not be present.
|
||||||
|
*
|
||||||
|
* @param value the value, may be null
|
||||||
|
* @param <T> the type of the value
|
||||||
|
*
|
||||||
|
* @return a Maybe, either a Just, or Nothing if value is null
|
||||||
|
*/
|
||||||
|
static <T> Maybe<T> maybe(final T value) {
|
||||||
|
if (value == null) {
|
||||||
|
return nothing();
|
||||||
|
}
|
||||||
|
return just(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Maybe from an {@link Optional}.
|
||||||
|
*
|
||||||
|
* @param optional the Optional
|
||||||
|
* @param <T> the type of the Optional
|
||||||
|
*
|
||||||
|
* @return a Maybe
|
||||||
|
*/
|
||||||
|
static <T> Maybe<T> fromOptional(final Optional<T> optional) {
|
||||||
|
return optional.map(Maybe::maybe)
|
||||||
|
.orElse(nothing());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a value to use when Maybe is Nothing.
|
||||||
|
*
|
||||||
|
* @param supplier supplier for an alternate value
|
||||||
|
*
|
||||||
|
* @return a Maybe
|
||||||
|
*/
|
||||||
|
T orElseGet(Supplier<T> supplier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A value to use when Maybe is Nothing.
|
||||||
|
*
|
||||||
|
* @param otherValue an alternate value
|
||||||
|
*
|
||||||
|
* @return a Maybe
|
||||||
|
*/
|
||||||
|
T orElse(T otherValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter a Maybe by the predicate, replacing with Nothing when it fails.
|
||||||
|
*
|
||||||
|
* @param predicate the test
|
||||||
|
*
|
||||||
|
* @return the Maybe, or Nothing if the test returns false
|
||||||
|
*/
|
||||||
|
Maybe<T> filter(Predicate<T> predicate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the Maybe to an {@link Optional}.
|
||||||
|
*
|
||||||
|
* @return an Optional containing a value for a Just, or empty for a Nothing
|
||||||
|
*/
|
||||||
|
Optional<T> toOptional();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide the value within the Maybe, if it exists, to the Supplier, and returns the Maybe.
|
||||||
|
*
|
||||||
|
* @param consumer the Consumer to the value if present
|
||||||
|
*
|
||||||
|
* @return the Maybe
|
||||||
|
*/
|
||||||
|
Maybe<T> peek(Consumer<T> consumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw the exception if the Maybe is a Nothing.
|
||||||
|
*
|
||||||
|
* @param e the exception to throw
|
||||||
|
*
|
||||||
|
* @throws Exception if the Maybe is a Nothing
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("illegalthrows")
|
||||||
|
void orElseThrow(Supplier<Exception> e) throws Exception;
|
||||||
|
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ import java.util.function.Supplier;
|
||||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
public class Mon<T> implements Functor<T> {
|
public class Mon<T> implements Functor<T, Mon<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value.
|
* The value.
|
||||||
|
|
75
src/main/java/net/kemitix/mon/Nothing.java
Normal file
75
src/main/java/net/kemitix/mon/Nothing.java
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Maybe where no value is present.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the missing content
|
||||||
|
*
|
||||||
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
|
*/
|
||||||
|
public final class Nothing<T> implements Maybe<T> {
|
||||||
|
|
||||||
|
protected static final Maybe<?> INSTANCE = new Nothing<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> Maybe<?> map(final Function<T, R> f) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T orElseGet(final Supplier<T> supplier) {
|
||||||
|
return supplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T orElse(final T otherValue) {
|
||||||
|
return otherValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Maybe<T> filter(final Predicate<T> predicate) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<T> toOptional() {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Maybe<T> peek(final Consumer<T> consumer) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void orElseThrow(final Supplier<Exception> e) throws Exception {
|
||||||
|
throw e.get();
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,9 @@ import java.util.function.Function;
|
||||||
/**
|
/**
|
||||||
* Type Alias for other types.
|
* Type Alias for other types.
|
||||||
*
|
*
|
||||||
|
* <p>{@link #toString()}, {@link #equals(Object)} and {@link #hashCode()} are all transparent, returning the value
|
||||||
|
* for the type being aliased.</p>
|
||||||
|
*
|
||||||
* @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)
|
||||||
|
@ -38,20 +41,13 @@ public abstract class TypeAlias<T> {
|
||||||
*/
|
*/
|
||||||
private final T value;
|
private final T value;
|
||||||
|
|
||||||
private final Class<? super T> type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param value the value
|
* @param value the value
|
||||||
* @param type the type of the value
|
|
||||||
*/
|
*/
|
||||||
protected TypeAlias(
|
protected TypeAlias(final T value) {
|
||||||
final T value,
|
|
||||||
final Class<? super T> type
|
|
||||||
) {
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.type = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,14 +68,13 @@ public abstract class TypeAlias<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final boolean equals(final Object o) {
|
public final boolean equals(final Object o) {
|
||||||
if (o instanceof TypeAlias) {
|
if (o instanceof TypeAlias) {
|
||||||
if (((TypeAlias) o).type.equals(type)) {
|
final TypeAlias other = (TypeAlias) o;
|
||||||
return ((TypeAlias<T>) o).map(getValue()::equals);
|
final Object otherValue = other.getValue();
|
||||||
} else {
|
final Class<?> otherValueClass = otherValue.getClass();
|
||||||
return false;
|
return otherValueClass.equals(getValue().getClass())
|
||||||
}
|
&& otherValue.equals(getValue());
|
||||||
}
|
}
|
||||||
return map(o::equals);
|
return map(o::equals);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +89,7 @@ public abstract class TypeAlias<T> {
|
||||||
*
|
*
|
||||||
* @return the value
|
* @return the value
|
||||||
*/
|
*/
|
||||||
private T getValue() {
|
public T getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,15 +10,6 @@ import org.junit.Test;
|
||||||
*/
|
*/
|
||||||
public class IdentityTest implements WithAssertions {
|
public class IdentityTest implements WithAssertions {
|
||||||
|
|
||||||
@Test
|
|
||||||
public void functorLawMapIdEqualsId() {
|
|
||||||
//given
|
|
||||||
final String id = "id";
|
|
||||||
//when
|
|
||||||
|
|
||||||
//then
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void canMapIdentityFromStringToInteger() {
|
public void canMapIdentityFromStringToInteger() {
|
||||||
//given
|
//given
|
||||||
|
|
114
src/test/java/net/kemitix/mon/MaybeTest.java
Normal file
114
src/test/java/net/kemitix/mon/MaybeTest.java
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
package net.kemitix.mon;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import static net.kemitix.mon.Maybe.just;
|
||||||
|
import static net.kemitix.mon.Maybe.maybe;
|
||||||
|
import static net.kemitix.mon.Maybe.nothing;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
public class MaybeTest {
|
||||||
|
|
||||||
|
private static <T> Predicate<T> eq(final T value) {
|
||||||
|
return v -> Objects.equals(value, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void justMustBeNonNull() {
|
||||||
|
assertThatNullPointerException().isThrownBy(() -> just(null))
|
||||||
|
.withMessage("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nothingReusesTheSameInstance() {
|
||||||
|
assertThat(nothing()).isSameAs(nothing());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void equality() {
|
||||||
|
assertThat(just(1)).isEqualTo(just(1));
|
||||||
|
assertThat(just(1)).isNotEqualTo(just(2));
|
||||||
|
assertThat(just(1)).isNotEqualTo(nothing());
|
||||||
|
assertThat(nothing()).isEqualTo(nothing());
|
||||||
|
assertThat(just(1).equals("1")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void maybeAllowsNull() {
|
||||||
|
assertThat(just(1)).isEqualTo(maybe(1));
|
||||||
|
assertThat(nothing()).isEqualTo(maybe(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void map() {
|
||||||
|
assertThat(just(1).map(v -> v + 1)).isEqualTo(just(2));
|
||||||
|
assertThat(nothing().map(v -> v)).isEqualTo(nothing());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHashCode() {
|
||||||
|
assertThat(just(1).hashCode()).isEqualTo(Objects.hashCode(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void orElseGet() {
|
||||||
|
assertThat(just(1).orElseGet(() -> -1)).isEqualTo(1);
|
||||||
|
assertThat(nothing().orElseGet(() -> -1)).isEqualTo(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void orElse() {
|
||||||
|
assertThat(just(1).orElse(-1)).isEqualTo(1);
|
||||||
|
assertThat(nothing().orElse(-1)).isEqualTo(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void filter() {
|
||||||
|
assertThat(just(1).filter(eq(1))).isEqualTo(just(1));
|
||||||
|
assertThat(just(1).filter(eq(0))).isEqualTo(nothing());
|
||||||
|
assertThat(nothing().filter(eq(1))).isEqualTo(nothing());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toOptional() {
|
||||||
|
assertThat(just(1).toOptional()).isEqualTo(Optional.of(1));
|
||||||
|
assertThat(nothing()
|
||||||
|
.toOptional()).isEqualTo(Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fromOptional() {
|
||||||
|
assertThat(Maybe.fromOptional(Optional.of(1))).isEqualTo(just(1));
|
||||||
|
assertThat(Maybe.fromOptional(Optional.empty())).isEqualTo(nothing());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void peek() {
|
||||||
|
final AtomicInteger ref = new AtomicInteger(0);
|
||||||
|
assertThat(just(1).peek(x -> ref.incrementAndGet())).isEqualTo(just(1));
|
||||||
|
assertThat(ref.get()).isEqualTo(1);
|
||||||
|
|
||||||
|
assertThat(nothing().peek(x -> ref.incrementAndGet())).isEqualTo(nothing());
|
||||||
|
assertThat(ref.get()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void justOrThrow() {
|
||||||
|
assertThatCode(() -> just(1).orElseThrow(IllegalStateException::new)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nothingOrThrow() {
|
||||||
|
assertThatThrownBy(() -> nothing().orElseThrow(IllegalStateException::new)).isInstanceOf(
|
||||||
|
IllegalStateException.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,29 @@
|
||||||
package net.kemitix.mon;
|
package net.kemitix.mon;
|
||||||
|
|
||||||
|
import org.assertj.core.util.Strings;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.function.Function;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
public class TypeAliasTest {
|
public class TypeAliasTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldCreateATypeAliasAndGetTheValue() throws Exception {
|
public void shouldCreateATypeAliasAndGetTheValue() {
|
||||||
//given
|
//given
|
||||||
final String value = "value";
|
final String value = "value";
|
||||||
//when
|
//when
|
||||||
final TypeAlias<String> typeAlias = givenTypeAlias(value);
|
final TypeAlias<String> typeAlias = givenTypeAlias(value);
|
||||||
//then
|
//then
|
||||||
assertThat(typeAlias.<Boolean>map(value::equals)).isTrue();
|
assertThat(typeAlias.getValue()).isSameAs(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeAlias<String> givenTypeAlias(final String value) {
|
||||||
|
return new TypeAlias<String>(value) {
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -25,38 +32,34 @@ public class TypeAliasTest {
|
||||||
final Iterable<String> iterable = Collections.emptyList();
|
final Iterable<String> iterable = Collections.emptyList();
|
||||||
//when
|
//when
|
||||||
final TypeAlias<Iterable<String>> typeAlias =
|
final TypeAlias<Iterable<String>> typeAlias =
|
||||||
new TypeAlias<Iterable<String>>(iterable, Iterable.class) {
|
new TypeAlias<Iterable<String>>(iterable) {
|
||||||
};
|
};
|
||||||
//then
|
//then
|
||||||
assertThat(typeAlias.<Boolean>map(iterable::equals)).isTrue();
|
assertThat(typeAlias.getValue()).isSameAs(iterable);
|
||||||
}
|
|
||||||
|
|
||||||
private TypeAlias<String> givenTypeAlias(final String value) {
|
|
||||||
return new TypeAlias<String>(value, String.class) {
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldCreateAnAliasedTypeAndGetTheValue() throws Exception {
|
public void shouldCreateATypeAliasSubclassAndGetTheValue() {
|
||||||
//given
|
//given
|
||||||
final String value = "value";
|
final String value = "value";
|
||||||
//when
|
//when
|
||||||
final AnAlias anAlias = AnAlias.of(value);
|
final AnAlias anAlias = AnAlias.of(value);
|
||||||
//then
|
//then
|
||||||
assertThat(anAlias.<Boolean>map(value::equals)).isTrue();
|
assertThat(anAlias.getValue()).isSameAs(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldNotBeEqualWhenValueTypesAreDifferent() {
|
public void shouldNotBeEqualWhenValueTypesAreDifferent() {
|
||||||
//given
|
//given
|
||||||
final TypeAlias<String> stringTypeAlias = givenTypeAlias("1");
|
final TypeAlias<String> stringTypeAlias = givenTypeAlias("1");
|
||||||
final TypeAlias<Integer> integerTypeAlias = new TypeAlias<Integer>(1, Integer.class){};
|
final TypeAlias<Integer> integerTypeAlias = new TypeAlias<Integer>(1) {
|
||||||
|
};
|
||||||
//then
|
//then
|
||||||
assertThat(stringTypeAlias).isNotEqualTo(integerTypeAlias);
|
assertThat(stringTypeAlias).isNotEqualTo(integerTypeAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldBeEqualWhenValuesAreTheSame() throws Exception {
|
public void shouldBeEqualWhenValuesAreTheSame() {
|
||||||
//given
|
//given
|
||||||
final String value = "value";
|
final String value = "value";
|
||||||
final AnAlias anAlias1 = AnAlias.of(value);
|
final AnAlias anAlias1 = AnAlias.of(value);
|
||||||
|
@ -66,7 +69,16 @@ public class TypeAliasTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldBeEqualToUnAliasedValue() throws Exception {
|
public void shouldNotBeEqualWhenValuesAreNotTheSame() {
|
||||||
|
//given
|
||||||
|
final AnAlias valueA = AnAlias.of("value a");
|
||||||
|
final AnAlias valueB = AnAlias.of("value b");
|
||||||
|
//then
|
||||||
|
assertThat(valueA).isNotEqualTo(valueB);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldBeEqualToRawValue() {
|
||||||
//given
|
//given
|
||||||
final String value = "value";
|
final String value = "value";
|
||||||
final AnAlias anAlias = AnAlias.of(value);
|
final AnAlias anAlias = AnAlias.of(value);
|
||||||
|
@ -75,7 +87,7 @@ public class TypeAliasTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldHaveHashCodeOfValue() throws Exception {
|
public void shouldHaveHashCodeOfValue() {
|
||||||
//given
|
//given
|
||||||
final String value = "value";
|
final String value = "value";
|
||||||
final AnAlias anAlias = AnAlias.of(value);
|
final AnAlias anAlias = AnAlias.of(value);
|
||||||
|
@ -84,24 +96,24 @@ public class TypeAliasTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldHaveSameToStringAsAliasedType() throws Exception {
|
public void shouldHaveSameToStringAsAliasedType() {
|
||||||
//given
|
//given
|
||||||
final String value = "value";
|
final List<Integer> value = Arrays.asList(1, 2, 3);
|
||||||
//when
|
//when
|
||||||
final AnAlias anAlias = AnAlias.of(value);
|
final TypeAlias<List<Integer>> anAlias = new TypeAlias<List<Integer>>(value) {
|
||||||
|
};
|
||||||
//then
|
//then
|
||||||
assertThat(anAlias.toString()).isEqualTo(value);
|
assertThat(anAlias.toString()).isEqualTo(value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldMapTypeAlias() {
|
public void shouldMapTypeAlias() {
|
||||||
//given
|
//given
|
||||||
final AnAlias anAlias = AnAlias.of("text");
|
final AnAlias anAlias = AnAlias.of("text");
|
||||||
final Function<String, String> function = v -> v;
|
|
||||||
//when
|
//when
|
||||||
final String value = anAlias.map(function);
|
final String value = anAlias.map(Strings::quote);
|
||||||
//then
|
//then
|
||||||
assertThat(value).isEqualTo("text");
|
assertThat(value).isEqualTo("'text'");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AnAlias extends TypeAlias<String> {
|
private static class AnAlias extends TypeAlias<String> {
|
||||||
|
@ -112,7 +124,7 @@ public class TypeAliasTest {
|
||||||
* @param value the value
|
* @param value the value
|
||||||
*/
|
*/
|
||||||
protected AnAlias(final String value) {
|
protected AnAlias(final String value) {
|
||||||
super(value, String.class);
|
super(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static AnAlias of(final String value) {
|
protected static AnAlias of(final String value) {
|
||||||
|
|
Loading…
Reference in a new issue