package tc.oc.commons.core.scheduler; import java.util.Objects; import javax.annotation.Nullable; import java.time.Duration; import java.time.Instant; import tc.oc.commons.core.util.TimeUtils; import static com.google.common.base.Preconditions.checkNotNull; /** * Represents a task to be managed by a {@link Scheduler}. * * A task can be instantiated but not be running. This allows tasks to be * queued before certain events occur. * * This is *only* to be constructed by a {@link Scheduler}. Constructing this * without the help of the scheduler will most likely cause bugs. */ public interface Task { /** * Get the scheduler for this task. * @return the scheduler. */ Scheduler getScheduler(); /** * Get the parameters that will tell the scheduler how to run this task. * @return the task parameters. */ Parameters getParameters(); /** * Get the runnable for this task. Do not attempt to directly interrupt this, * instead use {@link #cancel()}. * @return the runnable for this task. */ Runnable getRunnable(); /** * Get whether this task is currently running. * @return whether the task is running. */ boolean isRunning(); /** * Get whether this task is queued to run. * @return whether the task is queued. */ boolean isQueued(); /** * Get whether this task is registered, queued, or running. * @return whether the task is pending. */ boolean isPending(); /** * Cancel this task from ever running again. * If the task was never started, it will be cancelled * instantly when it is started. */ void cancel(); /** * Parameters for running a task. */ class Parameters { private final Instant creation; private @Nullable Duration delay; private @Nullable Duration interval; private Parameters(Instant creation, @Nullable Duration delay, @Nullable Duration interval) { this.creation = creation; this.delay = delay; this.interval = interval; } @Override public String toString() { return getClass().getSimpleName() + "{delay=" + delay() + ", interval=" + interval() + "}"; } public @Nullable Duration delay() { return delay; } public @Nullable Duration interval() { return interval; } public boolean isRepeating() { return interval() != null; } public Instant creation() { return creation; } public Instant start() { return delay == null ? creation : creation.plus(delay); } public static Parameters fromDuration(@Nullable Duration delay, @Nullable Duration interval) { return new Parameters(Instant.now(), delay, interval); } public static Parameters fromInstant(@Nullable Instant start, @Nullable Duration interval) { final Instant now = Instant.now(); final Duration delay = start != null && start.isAfter(now) ? Duration.between(now, start) : null; return new Parameters(now, delay, interval); } public static Parameters fromInstant(@Nullable Instant start) { return fromInstant(start, null); } public static Parameters fromTicks(@Nullable Long delay, @Nullable Long interval) { return fromDuration(delay == null ? null : TimeUtils.fromTicks(delay), interval == null ? null : TimeUtils.fromTicks(interval)); } public static Parameters after(Duration delay) { return fromDuration(checkNotNull(delay), null); } public static Parameters every(Duration interval) { return fromDuration(null, checkNotNull(interval)); } @Override public boolean equals(Object obj) { if(!(obj instanceof Parameters)) return false; if(obj == this) return true; final Parameters parameters = (Parameters) obj; return Objects.equals(start(), parameters.start()) && Objects.equals(interval(), parameters.interval()); } @Override public int hashCode() { return Objects.hash(start(), interval()); } } }