bear.task.TaskDef.java Source code

Java tutorial

Introduction

Here is the source code for bear.task.TaskDef.java

Source

/*
 * Copyright (C) 2013 Andrey Chaschev.
 *
 * 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 bear.task;

import bear.core.Role;
import bear.core.SessionContext;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Sets;

import java.util.*;

/**
 * @author Andrey Chaschev chaschev@gmail.com
 */

public class TaskDef<I, O extends TaskResult<?>> {
    String name;
    public String description;

    private boolean setupTask;

    Set<Role> roles = new HashSet<Role>();

    List<TaskDef<Object, TaskResult<?>>> beforeTasks = new ArrayList<TaskDef<Object, TaskResult<?>>>();
    List<TaskDef<Object, TaskResult<?>>> afterTasks = new ArrayList<TaskDef<Object, TaskResult<?>>>();
    List<TaskDef<Object, TaskResult<?>>> dependsOnTasks = new ArrayList<TaskDef<Object, TaskResult<?>>>();

    private final MultitaskSupplier multitaskSupplier;

    TaskDef<Object, TaskResult<?>> rollback;

    private final SingleTaskSupplier<I, O> singleTaskSupplier;

    public TaskDef(TaskCallable<I, O> callable) {
        this(Tasks.<I, O>newSingleSupplier(callable));

        if (callable instanceof NamedCallable<?, ?>) {
            NamedCallable<I, O> namedCallable = (NamedCallable<I, O>) callable;
            setName(namedCallable.name);

        }
    }

    public TaskDef(String name, TaskCallable<I, O> callable) {
        this(Tasks.<I, O>newSingleSupplier(callable));
        this.name = name;
    }

    public TaskDef(SingleTaskSupplier<I, O> singleTaskSupplier) {
        this(null, singleTaskSupplier);

        if (singleTaskSupplier instanceof NamedSupplier<?, ?>) {
            NamedSupplier<?, ?> taskSupplier = (NamedSupplier<?, ?>) singleTaskSupplier;
            this.name = taskSupplier.name;
        }
    }

    public TaskDef(String name, SingleTaskSupplier<I, O> singleTaskSupplier) {
        this(null, singleTaskSupplier, null);
        this.name = name;
    }

    public TaskDef(String name, MultitaskSupplier multitaskSupplier) {
        this(name, null, multitaskSupplier);
    }

    public TaskDef(String name, SingleTaskSupplier<I, O> singleTaskSupplier, MultitaskSupplier multitaskSupplier) {
        this.name = name;
        this.singleTaskSupplier = singleTaskSupplier;
        this.multitaskSupplier = multitaskSupplier;
    }

    private StringBuilder classNameToTaskName(String simpleName) {
        int wordStart = 0;
        StringBuilder sb = new StringBuilder(simpleName.length() + 10);
        for (int i = 1; i < simpleName.length(); i++) {
            if (Character.isUpperCase(simpleName.charAt(i))) {
                sb.append(simpleName.substring(wordStart, i));
                sb.append(' ');
                wordStart = i;
            }
        }

        sb.append(simpleName.substring(wordStart));
        return sb;
    }

    private Task<I, O> createNewSession(SessionContext $, final Task parent) {
        Preconditions.checkArgument(!isMultitask(), "task is not multi");

        Task task = singleTaskSupplier.createNewSession($, parent, this);

        task.wire($);

        return task;
    }

    public TaskResult<?> runRollback(SessionRunner sessionRunner) {
        if (rollback != null) {
            return sessionRunner.run(rollback);
        }
        return TaskResult.OK;
    }

    private List<Task> createNewSessions(SessionContext $, final Task parent) {
        Preconditions.checkArgument(isMultitask(), "task is multi");

        List<TaskDef<Object, TaskResult<?>>> defs = multitaskSupplier.getTaskDefs();
        List<Task> tasks = new ArrayList<Task>();

        for (TaskDef<Object, TaskResult<?>> def : defs) {
            Task task = (Task) def.createNewSession($, parent).wire($);

            tasks.add(task);
        }

        return tasks;
    }

    public TaskDef<I, O> setName(String name) {
        this.name = name;
        return this;
    }

    public static interface TaskSupplier {

    }

    public List<Task<Object, TaskResult<?>>> createNewSessionsAsList(SessionContext $, final Task parent) {
        if (isMultitask()) {
            return (List) createNewSessions($, parent);
        } else {
            return (List) Collections.singletonList(createNewSession($, parent));
        }
    }

    public SingleTaskSupplier<I, O> singleTaskSupplier() {
        Preconditions.checkArgument(!isMultitask(), "task is multi");

        return new SingleTaskSupplier<I, O>() {
            @Override
            public Task<I, O> createNewSession(SessionContext $, Task<Object, TaskResult<?>> parent,
                    TaskDef<I, O> def) {
                return TaskDef.this.createNewSession($, parent);
            }
        };
    }

    public MultitaskSupplier multitaskSupplier() {
        Preconditions.checkArgument(isMultitask(), "task is not multi");

        return multitaskSupplier;
    }

    public boolean hasRole(Set<Role> roles) {
        return !Sets.intersection(this.roles, roles).isEmpty();
    }

    public TaskDef depends(Task<Object, TaskResult<?>>... tasks) {
        Collections.addAll((List) dependsOnTasks, tasks);

        return this;
    }

    public TaskDef<I, O> before(String name, TaskCallable<Object, TaskResult<?>> callable) {
        beforeTasks.add(new TaskDef<Object, TaskResult<?>>(name, callable));
        return this;
    }

    public TaskDef<I, O> before(TaskCallable<Object, TaskResult<?>> callable) {
        beforeTasks.add(new TaskDef<Object, TaskResult<?>>(callable));
        return this;
    }

    public TaskDef<I, O> addBeforeTask(TaskDef<Object, TaskResult<?>> task) {
        beforeTasks.add(task);
        return this;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("TaskDef{");
        sb.append("name='").append(name).append('\'');
        sb.append(", description='").append(description).append('\'');
        sb.append(", roles=").append(roles);
        sb.append('}');
        return sb.toString();
    }

    public TaskDef desc(String description) {
        this.description = description;
        return this;
    }

    public final DependencyResult checkDependencies() {
        return checkDependencies(true);
    }

    public final DependencyResult checkDependencies(boolean throwException) {
        return checkDeps(throwException);
    }

    protected DependencyResult checkDeps(boolean throwException) {
        return DependencyResult.OK;
    }

    public boolean isSetupTask() {
        return setupTask;
    }

    public TaskDef setSetupTask(boolean setupTask) {
        this.setupTask = setupTask;
        return this;
    }

    public static final TaskDef EMPTY = new TaskDef<Object, TaskResult<?>>("EMPTY", SingleTaskSupplier.NOP);

    public static final TaskDef ROOT = new TaskDef<Object, TaskResult<?>>("ROOT", SingleTaskSupplier.NOP);

    public Set<Role> getRoles() {
        return roles;
    }

    public String getName() {
        return name == null ? getClass().getSimpleName() + "@" + hashCode() : name;
    }

    public boolean isNamed() {
        return name != null;
    }

    public String getDisplayName() {
        String name = this.name == null ? defaultName() : this.name;
        return name + (roles.isEmpty() ? "" : " with roles: " + roles);
    }

    public boolean isMultitask() {
        return multitaskSupplier != null;
    }

    //    static AtomicInteger createdLists = new AtomicInteger();

    //the purpose is to lazy-initialize this factory
    //memoize is required because task is single, sub-taskdefs are created in a single thread...
    protected final Supplier<List<TaskDef<Object, TaskResult<?>>>> multiDefsSupplier = Suppliers
            .memoize(new Supplier<List<TaskDef<Object, TaskResult<?>>>>() {
                @Override
                public List<TaskDef<Object, TaskResult<?>>> get() {
                    final TaskDef<I, O> enclosingTaskDef = TaskDef.this;

                    MultitaskSupplier multitaskSupplier = multitaskSupplier();
                    List<TaskDef<Object, TaskResult<?>>> taskDefs = new ArrayList<TaskDef<Object, TaskResult<?>>>(
                            multitaskSupplier.size());

                    //attached to a task def, value memoized in a session
                    //            final DynamicVariable<List<Task<Object, TaskResult>>> taskListInASession = Variables.dynamic(new Fun<SessionContext, List<Task<Object, TaskResult>>>() {
                    //                @Override
                    //                public List<Task<Object, TaskResult>> apply(SessionContext $) {
                    //                    // LoggerFactory.getLogger("log").info("created tasks: {}, $: {}, @{}", tasks, $.getName(), System.identityHashCode(list));
                    //
                    //                    return enclosingTaskDef.multitaskSupplier().createNewSessions($, $.getCurrentTask());
                    //                }
                    //            })  .setName(enclosingTaskDef.getName())
                    //                .memoizeIn(SessionContext.class);

                    // "for this task def"
                    // "in this session"
                    // multitask is created once

                    //            for (int i = 0; i < multitaskSupplier.size(); i++) {
                    //                final int finalI = i;
                    //
                    //                final TaskDef<Object, TaskResult> taskDef = new TaskDef<Object, TaskResult>(new SingleTaskSupplier<Object, TaskResult>() {
                    //                    @Override
                    //                    public Task<Object, TaskResult> createNewSession(SessionContext $, Task<Object, TaskResult> parent, TaskDef<Object, TaskResult> def) {
                    //                        Task.wrongThreadCheck($);
                    //
                    //                        List<Task<Object, TaskResult>> tasks = $.var(taskListInASession);
                    //
                    //                        return tasks.get(finalI);
                    //                    }
                    //                });
                    //
                    //
                    //
                    //                taskDefs.add(taskDef);
                    //            }

                    return taskDefs;
                }
            });

    public List<TaskDef<Object, TaskResult<?>>> asList() {
        Preconditions.checkArgument(isMultitask(), "task is not multi");

        return (List) Collections.unmodifiableList(multitaskSupplier.getTaskDefs());
    }

    public TaskDef<I, O> onRollback(TaskDef<Object, TaskResult<?>> rollback) {
        this.rollback = rollback;
        return this;
    }

    private String defaultName() {
        return classNameToTaskName(getClass().getSimpleName()).toString();
    }

    public TaskDef<Object, TaskResult<?>> getRollback() {
        return rollback;
    }
}