org.rapidpm.frp.model.Result Maven / Gradle / Ivy
Show all versions of rapidpm-functional-reactive Show documentation
/**
* Copyright © 2017 Sven Ruppert ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rapidpm.frp.model;
import org.rapidpm.frp.functions.CheckedFunction;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
* Copyright (C) 2017 RapidPM - Sven Ruppert
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Created by Sven Ruppert - RapidPM - Team on 16.03.17.
*/
public interface Result {
void ifPresentOrElse(Consumer super T> action, Runnable emptyAction);
void ifPresentOrElse(Consumer success, Consumer failure);
void ifPresentOrElseAsync(Consumer super T> action, Runnable emptyAction);
void ifPresentOrElseAsync(Consumer success, Consumer failure);
static Result failure(String errorMessage) {
Objects.requireNonNull(errorMessage);
return new Result.Failure<>(errorMessage);
}
static Result success(T value) {
return new Result.Success<>(value);
}
static Result ofNullable(T value) {
return ofNullable(value, "Object was null");
}
static Result ofNullable(T value, String failedMessage) {
return (Objects.nonNull(value))
? success(value)
: failure(failedMessage);
}
T get();
T getOrElse(Supplier supplier);
Boolean isPresent();
Boolean isAbsent();
Result ifPresent(Consumer consumer);
Result ifAbsent(Runnable action);
Result ifFailed(Consumer failed);
default Stream stream() {
if (!isPresent()) {
return Stream.empty();
} else {
return Stream.of(get());
}
}
default Result or(Supplier extends Result extends T>> supplier) {
Objects.requireNonNull(supplier);
if (isPresent()) {
return this;
} else {
@SuppressWarnings("unchecked")
Result r = (Result) supplier.get();
return Objects.requireNonNull(r);
}
}
default Optional toOptional() {
return Optional.ofNullable(get());
}
static Result fromOptional(Optional optional) {
Objects.requireNonNull(optional);
return optional
.map(Result::success)
.orElseGet(() -> failure("Optional hold a null value"));
}
default Result thenCombine(V value, BiFunction> func) {
return func.apply(get(), value);
}
default CompletableFuture> thenCombineAsync(V value, BiFunction> func) {
return CompletableFuture.supplyAsync(() -> func.apply(get(), value));
}
default Result map(Function super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
return isPresent()
? ((CheckedFunction) mapper::apply).apply(get())
: this.asFailure();
}
default Result flatMap(Function super T, Result> mapper) {
Objects.requireNonNull(mapper);
return this.isPresent()
? mapper.apply(get())
: this.asFailure();
}
default Result asFailure() {
return (isAbsent())
? ofNullable(null)
: failure("converted to Failure orig was " + this);
}
abstract class AbstractResult implements Result {
protected final T value;
public AbstractResult(T value) {
this.value = value;
}
@Override
public Result ifPresent(Consumer consumer) {
Objects.requireNonNull(consumer);
if (value != null) consumer.accept(value);
return (this instanceof Failure)
? this
: ofNullable(value);
}
@Override
public Result ifAbsent(Runnable action) {
Objects.requireNonNull(action);
if (value == null) action.run();
return (this instanceof Failure)
? this
: ofNullable(value);
}
public Boolean isPresent() {
return (value != null) ? Boolean.TRUE : Boolean.FALSE;
}
public Boolean isAbsent() {
return (value == null) ? Boolean.TRUE : Boolean.FALSE;
}
@Override
public T get() {
return Objects.requireNonNull(value);
}
@Override
public T getOrElse(Supplier supplier) {
Objects.requireNonNull(supplier);
return (value != null) ? value : Objects.requireNonNull(supplier.get());
}
}
class Success extends AbstractResult {
public Success(T value) {
super(value);
}
@Override
public void ifPresentOrElse(Consumer super T> action, Runnable emptyAction) {
action.accept(value);
}
@Override
public void ifPresentOrElse(final Consumer success, final Consumer failure) {
// TODO check if usefull -> Objects.requireNonNull(value);
success.accept(value);
}
@Override
public void ifPresentOrElseAsync(Consumer super T> action, Runnable emptyAction) {
CompletableFuture.runAsync(() -> action.accept(value));
}
@Override
public void ifPresentOrElseAsync(Consumer success, Consumer failure) {
CompletableFuture.runAsync(() -> success.accept(value));
}
public Result ifFailed(Consumer failed) {
Objects.requireNonNull(failed);
//nothing do do , I am a Success
return ofNullable(value);
}
}
class Failure extends AbstractResult {
private final String errorMessage;
public Failure(final String errorMessage) {
super(null);
this.errorMessage = errorMessage;
}
@Override
public void ifPresentOrElse(Consumer super T> action, Runnable emptyAction) {
emptyAction.run();
}
@Override
public void ifPresentOrElse(final Consumer success, final Consumer failure) {
failure.accept(errorMessage);
}
@Override
public void ifPresentOrElseAsync(Consumer super T> action, Runnable emptyAction) {
CompletableFuture.runAsync(emptyAction);
}
@Override
public void ifPresentOrElseAsync(Consumer success, Consumer failure) {
CompletableFuture.runAsync(() -> failure.accept(errorMessage));
}
public Result ifFailed(Consumer failed) {
Objects.requireNonNull(failed);
failed.accept(errorMessage);
// I am a Failure - hold errorMessage, value already null;
return this;
}
}
}