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

functionalj.task.Tasks Maven / Gradle / Ivy

// ============================================================================
// Copyright (c) 2017-2019 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.task;

import static nullablej.nullable.Nullable.nullable;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiPredicate;
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.Func3;
import functionalj.function.Func4;
import functionalj.function.Func5;
import functionalj.function.Func6;
import functionalj.function.FuncUnit1;
import functionalj.list.FuncList;
import functionalj.promise.DeferAction;
import functionalj.promise.DeferActionBuilder;
import functionalj.promise.Promise;
import functionalj.promise.RaceResult;
import functionalj.result.Result;
import lombok.val;

public class Tasks {
    
    public static class TaskValue implements Task {
        private final DATA value;
        public TaskValue(DATA value) {
            this.value = value;
        }
        @Override
        public DeferAction createAction() {
            return DeferAction.ofValue(value);
        }
        public String toString() {
            return "Task(" + value + ")";
        }
    }
    
    public static class TaskSupplier extends DeferActionBuilder implements Task {
        public TaskSupplier(Func0 supplier) {
            super(supplier);
        }
        @Override
        public DeferAction createAction() {
            return build();
        }
        public String toString() {
            return "Task(()->" + supplier() + ")";
        }
    }
    
    public static class TaskResult implements Task {
        private final Result result;
        public TaskResult(Result result) {
            this.result = result;
        }
        @Override
        public DeferAction createAction() {
            val action = DeferAction.of((Class)null);
            action.start();
            if (result.isValue())
                 action.complete(result.getValue());
            else action.fail    (result.getException());
            return action;
        }
        public String toString() {
            return "Task(" + result + ")";
        }
    }
    
    public static class TaskPromise implements Task {
        private final Promise promise;
        public TaskPromise(Promise promise) {
            this.promise = promise;
        }
        @Override
        public DeferAction createAction() {
            val action = DeferAction.of((Class)null, ()->{
                if (promise != null)
                    promise.start();
            });
            if (promise != null) {
                promise
                .eavesdrop(result -> {
                    val pendingAction = action.start();
                    if (result.isValue())
                         pendingAction.complete(result.getValue());
                    else pendingAction.fail    (result.getException());
                });
            }
            return action;
        }
        public String toString() {
            return "Task(" + promise + ")";
        }
    }
    
    public static class IOInstance implements Task {
        private final String toString;
        private final Supplier> createAction;
        public IOInstance(String toString, Supplier> createAction) {
            this.toString     = (toString != null) ? toString : "Task@" + hashCode();
            this.createAction = Objects.requireNonNull(createAction);
        }
        @Override
        public DeferAction createAction() {
            return createAction.get();
        }
        public String toString() {
            return toString;
        }
    }
    
    public static class TaskPeek implements Task {
        private final Task                source;
        private final FuncUnit1 peeker;
        public TaskPeek(Task source, FuncUnit1 peeker) {
            this.source = source;
            this.peeker = peeker;
        }
        @Override
        public DeferAction createAction() {
            return source.createAction().peek(peeker);
        }
        public String toString() {
            return source + ".peek(" + peeker + ")";
        }
    }
    
    public static class TaskMap implements Task {
        private final Task                            source;
        private final Func1 mapper;
        public TaskMap(Task source, Func1 mapper) {
            this.source = source;
            this.mapper = mapper;
        }
        @Override
        public DeferAction createAction() {
            DeferAction map = source
                    .createAction()
                    .map(mapper);
            return map;
        }
        public String toString() {
            return source + ".map(" + mapper + ")";
        }
    }
    public static class TaskChain implements Task {
        private final Task                                source;
        private final Func1> mapper;
        public TaskChain(Task source, Func1> mapper) {
            this.source = source;
            this.mapper = mapper;
        }
        @SuppressWarnings("unchecked")
        @Override
        public DeferAction createAction() {
            val ioDefer   = source.createAction().map(mapper);
            val ioPromise = ioDefer.getPromise();
            val action    = (DeferAction)DeferAction.createNew(()->ioPromise.start());
            ioPromise
            .subscribe(io -> {
                val pendindAction = action.start();
                io
                .createAction()
                .start()
                .eavesdrop(result -> {
                    if (result.isValue())
                         pendindAction.complete(result.getValue());
                    else pendindAction.fail    (result.getException());
                });
            });
            return action;
        }
        public String toString() {
            return source + ".chain(" + mapper + ")";
        }
    }
    public static class TaskFilter implements Task {
        private final Task                source;
        private final Predicate predicate;
        public TaskFilter(Task source, Predicate predicate) {
            this.source    = source;
            this.predicate = predicate;
        }
        @Override
        public DeferAction createAction() {
            return source.createAction().filter(predicate);
        }
        public String toString() {
            return source + ".filter(" + predicate + ")";
        }
    }
    public static class TaskCached implements Task {
        private final Task          source;
        private final DeferAction action;
        public TaskCached(Task source) {
            this.source = source;
            this.action = source.createAction();
        }
        @Override
        public DeferAction createAction() {
            return action;
        }
        public String toString() {
            return source + ".cached()";
        }
    }
    
    public static class TaskCachedFor implements Task {
        private final Task                           source;
        private final Supplier                  contextSupplier;
        private final BiPredicate      staleChecker;
        private final AtomicReference           contxtRef;
        private final AtomicReference> actionRef;
        public TaskCachedFor(Task source, Supplier contextSupplier, BiPredicate staleChecker) {
            this.source          = source;
            this.contextSupplier = contextSupplier;
            this.staleChecker    = staleChecker;
            this.actionRef       = new AtomicReference<>(null);
            this.contxtRef       = new AtomicReference<>(contextSupplier.get());
        }
        @Override
        public DeferAction createAction() {
            val act = actionRef.get();
            val ctx = contxtRef.get();
            val newRef = contextSupplier.get();
            if (staleChecker.test(ctx, newRef) || (act == null)) {
                actionRef.compareAndSet(act, source.createAction());
                contxtRef.set(newRef);
                return actionRef.get();
            }
            
            return act;
        }
        public String toString() {
            return source + ".cachedFor(" + contextSupplier + "," + staleChecker + ")";
        }
    }
    
    // merge, race, loop, branch
    
    public static class TaskMerge2 implements Task {
        private final Task input1;
        private final Task input2;
        private final Func2  merger;
        public TaskMerge2(Task input1, Task input2, Func2 merger) {
            this.input1 = input1;
            this.input2 = input2;
            this.merger = merger;
        }
        @Override
        public DeferAction createAction() {
            val action1 = input1.createAction();
            val action2 = input2.createAction();
            val action  = DeferAction.from(action1, action2, merger);
            return action;
        }
        @Override
        public String toString() {
            return merger + "(" + input1 + ", " + input2 + ")";
        }
    }
    
    public static class TaskMerge3 implements Task {
        private final Task input1;
        private final Task input2;
        private final Task input3;
        private final Func3 merger;
        public TaskMerge3(Task input1, Task input2, Task input3, Func3 merger) {
            this.input1 = input1;
            this.input2 = input2;
            this.input3 = input3;
            this.merger = merger;
        }
        @Override
        public DeferAction createAction() {
            val action1 = input1.createAction();
            val action2 = input2.createAction();
            val action3 = input3.createAction();
            val action  = DeferAction.from(action1, action2, action3, merger);
            return action;
        }
        @Override
        public String toString() {
            return merger + "(" + input1 + ", " + input2 + ", " + input3 + ")";
        }
    }
    
    public static class TaskMerge4 implements Task {
        private final Task input1;
        private final Task input2;
        private final Task input3;
        private final Task input4;
        private final Func4 merger;
        public TaskMerge4(Task input1, Task input2, Task input3, Task input4, Func4 merger) {
            this.input1 = input1;
            this.input2 = input2;
            this.input3 = input3;
            this.input4 = input4;
            this.merger = merger;
        }
        @Override
        public DeferAction createAction() {
            val action1 = input1.createAction();
            val action2 = input2.createAction();
            val action3 = input3.createAction();
            val action4 = input4.createAction();
            val action  = DeferAction.from(action1, action2, action3, action4, merger);
            return action;
        }
        @Override
        public String toString() {
            return merger + "(" + input1 + ", " + input2 + ", " + input3 + ", " + input4 + ")";
        }
    }
    
    public static class TaskMerge5 implements Task {
        private final Task input1;
        private final Task input2;
        private final Task input3;
        private final Task input4;
        private final Task input5;
        private final Func5 merger;
        public TaskMerge5(Task input1, Task input2, Task input3, Task input4, Task input5, Func5 merger) {
            this.input1 = input1;
            this.input2 = input2;
            this.input3 = input3;
            this.input4 = input4;
            this.input5 = input5;
            this.merger = merger;
        }
        @Override
        public DeferAction createAction() {
            val action1 = input1.createAction();
            val action2 = input2.createAction();
            val action3 = input3.createAction();
            val action4 = input4.createAction();
            val action5 = input5.createAction();
            val action  = DeferAction.from(action1, action2, action3, action4, action5, merger);
            return action;
        }
        @Override
        public String toString() {
            return merger + "(" + input1 + ", " + input2 + ", " + input3 + ", " + input4 + ", " + input5 + ")";
        }
    }
    
    public static class TaskMerge6 implements Task {
        private final Task input1;
        private final Task input2;
        private final Task input3;
        private final Task input4;
        private final Task input5;
        private final Task input6;
        private final Func6 merger;
        public TaskMerge6(Task input1, Task input2, Task input3, Task input4, Task input5, Task input6, Func6 merger) {
            this.input1 = input1;
            this.input2 = input2;
            this.input3 = input3;
            this.input4 = input4;
            this.input5 = input5;
            this.input6 = input6;
            this.merger = merger;
        }
        @Override
        public DeferAction createAction() {
            val action1 = input1.createAction();
            val action2 = input2.createAction();
            val action3 = input3.createAction();
            val action4 = input4.createAction();
            val action5 = input5.createAction();
            val action6 = input6.createAction();
            val action  = DeferAction.from(action1, action2, action3, action4, action5, action6, merger);
            return action;
        }
        @Override
        public String toString() {
            return merger + "(" + input1 + ", " + input2 + ", " + input3 + ", " + input4 + ", " + input5 + ", " + input6 + ")";
        }
    }
    
    public static class TaskRace implements Task {
        private final FuncList> list;
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public TaskRace(List> list) {
            this.list = (FuncList)nullable(list).map(FuncList::from).orElse(FuncList.empty());
        }
        @Override
        public DeferAction createAction() {
            val actions    = list.map(io -> io.createAction());
            val raceResult = RaceResult.from(actions);
            val promise    = raceResult.getResultPromise();
            val action     = DeferAction.of((Class)null, ()->{
                if (promise != null)
                    promise.start();
            });
            if (promise != null) {
                promise
                .eavesdrop(result -> {
                    val pendingAction = action.start();
                    if (result.isValue())
                         pendingAction.complete(result.getValue());
                    else pendingAction.fail    (result.getException());
                });
            }
            return action;
        }
        @Override
        public String toString() {
            return "Race(" + list.joinToString(",") + ")";
        }
        
    }
    
    public static class TaskDoUntil implements Task {
        private final Task                body;
        private final Predicate> breakCheck;
        public TaskDoUntil(Task body, Predicate> breakCheck) {
            this.body       = body;
            this.breakCheck = breakCheck;
        }
        @Override
        public DeferAction createAction() {
            val actionRef = new AtomicReference>();
            val action = DeferAction.of((Class)null, ()->{
                doBody(actionRef);
            });
            actionRef.set(action);
            return action;
        }
        private void doBody(AtomicReference> actionRef) {
            val bodyAction = body.createAction();
            // Ummm not sure if subscribe is good here
            bodyAction.onComplete(result -> {
                val isToBreak = breakCheck.test(result);
                if (isToBreak) {
                    val action = actionRef.get().start();
                    if (result.isValue())
                         action.complete(result.value());
                    else action.fail    (result.exception());
                } else {
                    doBody(actionRef);
                }
            });
            bodyAction.start();
        }
        @Override
        public String toString() {
            return "DoUntil(do: " + body + ", util: " + breakCheck + ")";
        }
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy