All Downloads are FREE. Search and download functionalities are using the official Maven repository.

functionalj.promise.DeferValue Maven / Gradle / Ivy

There is a newer version: 1.0.17
Show newest version
// ============================================================================
// Copyright (c) 2017-2021 Nawapunth Manusitthipol (NawaMan - http://nawaman.net).
// ----------------------------------------------------------------------------
// MIT License
// 
// 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 functionalj.promise;

import static functionalj.function.Func.itself;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import functionalj.function.Func0;
import functionalj.function.Func1;
import functionalj.function.Func2;
import functionalj.function.FuncUnit1;
import functionalj.function.FuncUnit2;
import functionalj.list.FuncList;
import functionalj.result.Result;
import functionalj.result.ResultStatus;
import functionalj.result.ValidationException;
import functionalj.tuple.Tuple2;
import functionalj.validator.Validator;
import lombok.NonNull;
import lombok.val;

/**
 * This special class of promise can have its value assigned later.
 * Once assigned, the value is set.
 **/
@SuppressWarnings({"unchecked", "rawtypes"})
public class DeferValue extends Promise {
    
    public static  DeferValue of(Class clazz) {
        return new DeferValue();
    }
    
    public static  DeferValue ofValue(DATA data) {
        val deferValue = new DeferValue();
        deferValue.assign(data);
        return deferValue;
    }
    
    public static  DeferValue ofFailure(@NonNull Exception cause) {
        val deferValue = new DeferValue();
        deferValue.fail(cause);
        return deferValue;
    }
    
    public static  DeferValue ofResult(Result result) {
        val deferValue = new DeferValue();
        deferValue.complete(result);
        return deferValue;
    }
    
    public static  DeferValue deferValueOf(Class clazz) {
        return new DeferValue();
    }
    
    public static  DeferValue deferValue() {
        return new DeferValue();
    }
    
    public static DeferValue deferString() {
        return new DeferValue();
    }
    
    public static DeferValue deferInt() {
        return new DeferValue();
    }
    
    public static DeferValue deferLong() {
        return new DeferValue();
    }
    
    public static DeferValue deferDouble() {
        return new DeferValue();
    }
    
    public static  DeferValue of(String name, Class clazz) {
        return new DeferValue().named(name);
    }
    
    public static  DeferValue deferValue(String name, Class clazz) {
        return new DeferValue().named(name);
    }
    
    public static  DeferValue deferValue(String name) {
        return new DeferValue().named(name);
    }
    
    public static DeferValue deferString(String name) {
        return new DeferValue().named(name);
    }
    
    public static DeferValue deferInt(String name) {
        return new DeferValue().named(name);
    }
    
    public static DeferValue deferLong(String name) {
        return new DeferValue().named(name);
    }
    
    public static DeferValue deferDouble(String name) {
        return new DeferValue().named(name);
    }
    
    
    public DeferValue() {
        super((OnStart)()->{});
        start();
    }
    
    DeferValue(Promise parent) {
        super(parent);
    }
    
    DeferValue parent() {
        return (DeferValue)super.parent();
    }
    
    public NamedDeferValue named(String name) {
        return new NamedDeferValue(this, name);
    }
    
    @Override
    public Promise getPromise() {
        return map(itself());
    }
    
    public Func0 asSupplier() {
        return ()->get();
    }
    
    public String toString() {
        return "Later#" + id;
    }
    
    private boolean complete(boolean shouldThrowException, 
            Predicate> parentAction,
            BooleanSupplier             superAction) {
        val parent = parent();
        if (parent != null) {
            return parentAction.test(parent);
        } else {
            if (!isComplete()) {
                synchronized (this) {
                    if (!isComplete()) {
                        return superAction.getAsBoolean();
                    }
                }
            }
            return handleAlreadyCompleted(shouldThrowException);
        }
    }
    private boolean handleAlreadyCompleted(boolean shouldThrowException) {
        if (shouldThrowException) {
            throw new RuntimeException();
        } else {
            return false;
        }
    }
    
    boolean abort(boolean shouldThrowException) {
        return complete(shouldThrowException,
                parent -> parent.abort(),
                ()     -> super.abort());
    }
    boolean abort(String message, boolean shouldThrowException) {
        return complete(shouldThrowException,
                parent -> parent.abort(message),
                ()     -> super.abort(message));
    }
    boolean abort(Exception cause, boolean shouldThrowException) {
        return complete(shouldThrowException,
                parent -> parent.abort(cause),
                ()     -> super.abort(cause));
    }
    boolean abort(String message, Exception cause, boolean shouldThrowException) {
        return complete(shouldThrowException,
                parent -> parent.abort(message, cause),
                ()     -> super.abort(message, cause));
    }
    
    boolean assign(DATA data, boolean shouldThrowException) {
        return complete(shouldThrowException,
                parent -> parent.assign(data),
                ()     -> super.makeComplete(data));
    }
    
    boolean fail(Exception exception, boolean shouldThrowException) {
        return complete(shouldThrowException,
                parent -> parent.fail(exception),
                ()     -> super.makeFail(exception));
    }
    boolean complete(Result result, boolean shouldThrowException) {
        return complete(shouldThrowException,
                parent -> makeDone(parent, result),
                ()     -> makeDone(this, result));
    }
    
    //== Complete ==
    
    public boolean abort() {
        return abort(false);
    }
    public boolean abort(String message) {
        return abort(message, false);
    }
    public boolean abort(Exception cause) {
        return abort(cause, false);
    }
    public boolean abort(String message, Exception cause) {
        return abort(message, cause, false);
    }
    
    public boolean assign(DATA data) {
        return assign(data, false);
    }
    public boolean fail(Exception exception) {
        return fail(exception, false);
    }
    public boolean complete(Result result) {
        return complete(result, false);
    }
    
    //== When not complete ==
    
    public boolean abortOrThrow() {
        return abort(true);
    }
    public boolean abortOrThrow(String message) {
        return abort(message, true);
    }
    public boolean abortOrThrow(Exception cause) {
        return abort(cause, true);
    }
    public boolean abortOrThrow(String message, Exception cause) {
        return abort(message, cause, true);
    }
    
    public boolean assignOrThrow(DATA data) {
        return assign(data, true);
    }
    public boolean failOrThrow(Exception exception) {
        return fail(exception, true);
    }
    public boolean completeOrThrow(Result result) {
        return complete(result, true);
    }
    
    // TODO - Do the same here to Ref
    
    //== Functional ==
    
    public final DeferValue filter(Predicate predicate) {
        return DeferValueHelper.mapResult(this, result -> result.filter((Predicate)predicate));
    }
    
    //== Validation ==
    
    public DeferValue validateNotNull() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validateNotNull());
    }
    public DeferValue validateNotNull(String message) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validateNotNull(message));
    }
    public DeferValue validateUnavailable() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validateUnavailable());
    }
    public DeferValue validateNotReady() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validateNotReady());
    }
    public DeferValue validateResultCancelled() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validateResultCancelled());
    }
    public DeferValue validateResultNotExist() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validateResultNotExist());
    }
    public DeferValue validateNoMoreResult() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validateNoMoreResult());
    }
    
    public DeferValue validate(String stringFormat, Predicate validChecker) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validate(stringFormat, (Predicate)validChecker));
    }
    
    public  DeferValue validate(String stringFormat, Func1 mapper, Predicate validChecker) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validate(stringFormat, (Func1)mapper, (Predicate)validChecker));
    }
    public DeferValue validate(Validator validator) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validate((Validator)validator));
    }
    
    public DeferValue>> validate(Validator ... validators) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validate((Validator[])validators));
    }
    
    public DeferValue>> validate(List> validators) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.validate((List)validators));
    }
    
    public DeferValue ensureNotNull() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ensureNotNull());
    }
    
    // Alias of whenNotPresentUse
    public DeferValue otherwise(DATA elseValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.otherwise(elseValue));
    }
    
    // Alias of whenNotPresentGet
    public DeferValue otherwiseGet(Supplier elseSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.otherwiseGet(elseSupplier));
    }
    
    public DeferValue printException() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.printException());
    }
    
    public DeferValue printException(PrintStream printStream) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.printException(printStream));
    }
    
    public DeferValue printException(PrintWriter printWriter) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.printException(printWriter));
    }
    
    //== Peek ==
    
    public  DeferValue peek(Class clzz, Consumer theConsumer) {
        return DeferValueHelper.mapResult(this, result -> result.peek(clzz, (Consumer)theConsumer));
    }
    public DeferValue peek(Predicate selector, Consumer theConsumer) {
        return DeferValueHelper.mapResult(this, result -> result.peek((Predicate)selector, (Consumer)theConsumer));
    }
    public  DeferValue peek(Function mapper, Consumer theConsumer) {
        return DeferValueHelper.mapResult(this, result -> result.peek((Function)mapper, (Consumer)theConsumer));
    }
    
    public  DeferValue peek(Function mapper, Predicate selector, Consumer theConsumer) {
        return DeferValueHelper.mapResult(this, result -> result.peek((Function)mapper, (Predicate) selector, (Consumer)theConsumer));
    }
    
    //== If+When ==
    
    public DeferValue useData(FuncUnit2 processor) {
        return DeferValueHelper.mapResult(this, result -> result.useData((FuncUnit2)processor));
    }
    
    public DeferValue whenComplete(FuncUnit2 processor) {
        return DeferValueHelper.mapResult(this, result -> result.useData((FuncUnit2)processor));
    }
    
    public DeferValue whenComplete(FuncUnit1> processor) {
        return DeferValueHelper.mapResult(this, result -> {
            processor.accept((Result)result);
            return null;
        });
    }
    
    //== Status ==
    
    public DeferValue ifStatusRun(ResultStatus status, Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifStatusRun(status, runnable));
    }
    
    public DeferValue ifStatusAccept(ResultStatus status, Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifStatusAccept(status, (Consumer)consumer));
    }
    
    public DeferValue whenStatusUse(ResultStatus status, DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenStatusUse(status, fallbackValue));
    }
    public DeferValue whenStatusGet(ResultStatus status, Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenStatusGet(status, fallbackSupplier));
    }
    public DeferValue whenStatusApply(ResultStatus status, BiFunction recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenStatusApply(status, (BiFunction)recoverFunction));
    }
    
    //== Present ==
    
    public DeferValue ifPresent(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifPresent(runnable));
    }
    
    public DeferValue ifPresent(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifPresent((Consumer)consumer));
    }
    
    //== Absent ==
    
    public DeferValue ifAbsent(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifAbsent(runnable));
    }
    
    public DeferValue ifAbsent(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifAbsent((Consumer)consumer));
    }
    
    public DeferValue ifAbsent(BiConsumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifAbsent((BiConsumer)consumer));
    }
    
    public DeferValue whenAbsentUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> 
            (Result)result.whenAbsentUse(fallbackValue));
    }
    
    public DeferValue whenAbsentGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenAbsentGet(fallbackSupplier));
    }
    
    public DeferValue whenAbsentApply(BiFunction recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> result.whenAbsentApply((Func2)recoverFunction));
    }
    
    //== Null ==
    
    public DeferValue ifNull(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifNull(runnable));
    }
    
    public DeferValue whenNullUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNullUse(fallbackValue));
    }
    public DeferValue whenNullGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNullGet(fallbackSupplier));
    }
    
    //== Value ==
    
    public DeferValue ifValue(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifValue(runnable));
    }
    
    public DeferValue ifValue(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifValue((Consumer)consumer));
    }
    
    //== NotValue ==
    
    public DeferValue ifNotValue(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifNotValue(runnable));
    }
    
    public DeferValue ifNotValue(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifNotValue((Consumer)consumer));
    }
    
    public DeferValue ifNotValue(BiConsumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifNotValue((BiConsumer)consumer));
    }
    
    public DeferValue whenNotValueUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotValueUse(fallbackValue));
    }
    public DeferValue whenNotValueGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotValueGet(fallbackSupplier));
    }
    public DeferValue whenNotValueApply(BiFunction recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> result.whenNotValueApply((Func2)recoverFunction));
    }
    
    //== Valid ==
    
    public DeferValue ifValid(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifValid((Consumer)consumer));
    }
    
    //== Invalid ==
    
    public DeferValue ifInvalid(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifInvalid(runnable));
    }
    
    public DeferValue ifInvalid(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifInvalid((Consumer)consumer));
    }
    
    public DeferValue whenInvalidUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenInvalidUse(fallbackValue));
    }
    public DeferValue whenInvalidGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> result.whenInvalidGet((Supplier)fallbackSupplier));
    }
    public DeferValue whenInvalidApply(Function recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> result.whenInvalidApply((Func1)recoverFunction));
    }
    
    //== NotExist ==
    
    public DeferValue ifNotExist(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifNotExist(runnable));
    }
    
    public DeferValue ifNotExist(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifNotExist((Consumer)consumer));
    }
    
    public DeferValue whenNotExistUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotExistUse(fallbackValue));
    }
    public DeferValue whenNotExistGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotExistGet(fallbackSupplier));
    }
    public DeferValue whenNotExistApply(Function recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotExistApply(recoverFunction));
    }
    
    //== Exception ==
    
    public DeferValue ifException(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifException(runnable));
    }
    
    public DeferValue ifException(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifException(consumer));
    }
    
    public DeferValue ifExceptionThenPrint() {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifExceptionThenPrint());
    }
    public DeferValue ifExceptionThenPrint(PrintStream printStream) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifExceptionThenPrint(printStream));
    }
    public DeferValue ifExceptionThenPrint(PrintWriter printWriter) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifExceptionThenPrint(printWriter));
    }
    
    public DeferValue whenExceptionUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenExceptionUse(fallbackValue));
    }
    public DeferValue whenExceptionGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenExceptionGet(fallbackSupplier));
    }
    public DeferValue whenExceptionApply(Function recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenExceptionApply(recoverFunction));
    }
    
    public DeferValue recover(Class problemClass, DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.recover(problemClass, fallbackValue));
    }
    public DeferValue recover(Class problemClass, Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.recover(problemClass, fallbackSupplier));
    }
    public DeferValue recover(Class problemClass, Func1 recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.recover(problemClass, recoverFunction));
    }
    
    //== Cancelled ==
    
    public DeferValue ifCancelled(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifCancelled(runnable));
    }
    
    public DeferValue whenCancelledUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenCancelledUse(fallbackValue));
    }
    public DeferValue whenCancelledGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenCancelledGet(fallbackSupplier));
    }
    public DeferValue whenCancelledApply(Function recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenCancelledApply(recoverFunction));
    }
    
    //== Ready ==
    
    public DeferValue ifReady(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifReady(runnable));
    }
    
    public DeferValue ifReady(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifReady((Consumer)consumer));
    }
    
    public DeferValue ifReady(BiConsumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifReady((BiConsumer)consumer));
    }
    
    public DeferValue whenReadyUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenReadyUse(fallbackValue));
    }
    public DeferValue whenReadyGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenReadyGet(fallbackSupplier));
    }
    public DeferValue whenNotReadyApply(BiFunction recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> result.whenNotReadyApply((Func2)recoverFunction));
    }
    
    //== Not Ready ==
    
    public DeferValue ifNotReady(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifNotReady(runnable));
    }
    public DeferValue ifNotReady(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> result.ifNotReady((Consumer)consumer));
    }
    
    public DeferValue whenNotReadyUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotReadyUse(fallbackValue));
    }
    public DeferValue whenNotReadyGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotReadyGet(fallbackSupplier));
    }
    public DeferValue whenNotReadyApply(Function recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNotReadyApply(recoverFunction));
    }
    
    //== No More Result ==
    
    public DeferValue ifNoMore(Runnable runnable) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifNoMore(runnable));
    }
    public DeferValue ifNoMore(Consumer consumer) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.ifNoMore(consumer));
    }
    
    public DeferValue whenNoMoreUse(DATA fallbackValue) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNoMoreUse(fallbackValue));
    }
    public DeferValue whenNoMoreGet(Supplier fallbackSupplier) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNoMoreGet(fallbackSupplier));
    }
    public DeferValue whenNoMoreApply(Function recoverFunction) {
        return DeferValueHelper.mapResult(this, result -> (Result)result.whenNoMoreApply(recoverFunction));
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy