/*
* Created by Andrey Cherkashin (acherkashin)
* http://acherkashin.me
*
* License
* Copyright (c) 2015 Andrey Cherkashin
* The project released under the MIT license: http://opensource.org/licenses/MIT
*/
package ragefist.core;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Logger;
/**
*
* @author acherkashin
*/
public abstract class ProcessorTask
{
public static interface IProcessorTaskDelegate
{
public void whenTaskIsFinished(ProcessorTask task);
}
private static int _nextId = 0;
private Processor _processor;
private final int _id;
private WeakReference<IProcessorTaskDelegate> _delegate;
private boolean _isAsync = false;
private Object _data;
private boolean _result;
private String _error;
private boolean _isFinished = false;
private Object _attachment = null;
private ProcessorTask _nextTask = null;
private Processor _nextTaskProcessor = null;
private ProcessorTask _parentTask = null;
private long _startTime;
private long _finishTime;
// ---------------------------------------------------------------------- //
// PUBLIC
// ---------------------------------------------------------------------- //
public ProcessorTask() {
_id = ++_nextId;
if (_nextId == Integer.MAX_VALUE) {
_nextId = 1;
}
}
public long getExecutionTime() {
return _finishTime - _startTime;
}
// ---------------------------------------------------------------------- //
// NEXT TASK
// A next task will be execute when this task is finished, whatever result
// it is
// ---------------------------------------------------------------------- //
public final void setNextTask(ProcessorTask task) {
_nextTask = task;
_nextTaskProcessor = null;
}
public final void setNextTask(ProcessorTask task, Processor processor) {
_nextTask = task;
_nextTaskProcessor = processor;
}
public final ProcessorTask getNextTask() {
return _nextTask;
}
public final Processor getNextTaskProcessor() {
return _nextTaskProcessor;
}
// ---------------------------------------------------------------------- //
// PARENT TASK
// For accessing previous task's results
// ---------------------------------------------------------------------- //
public final void setParentTask(ProcessorTask task) {
_parentTask = task;
}
public final ProcessorTask getParentTask() {
return _parentTask;
}
// ---------------------------------------------------------------------- //
// ATTACHMENTS
// For storing and accessing custom attachment
// ---------------------------------------------------------------------- //
public final void setAttachment(Object object) {
_attachment = object;
}
public final Object getAttachment() {
return _attachment;
}
// ---------------------------------------------------------------------- //
// DELEGATE
// The object that will be notified when the task is finished (whatever
// result it is)
// ---------------------------------------------------------------------- //
public final void setDelegate(IProcessorTaskDelegate delegate) {
_delegate = new WeakReference<>(delegate);
}
public final IProcessorTaskDelegate getDelegate() {
return _delegate != null ? _delegate.get() : null;
}
// ---------------------------------------------------------------------- //
// GETTERS
// ---------------------------------------------------------------------- //
public final int getId() { return _id; }
public final boolean getResult() { return _result; }
public final Object getData() { return _data; }
public final String getError() { return _error; }
public final boolean isAsync() { return _isAsync; }
public final boolean isFinished() { return _isFinished; }
// ---------------------------------------------------------------------- //
// SETTERS
// ---------------------------------------------------------------------- //
public final void setAsync(boolean isAsync) {
_isAsync = isAsync;
}
// ---------------------------------------------------------------------- //
// EXECUTION
// ---------------------------------------------------------------------- //
public final void execute(Processor processor) {
_startTime = System.currentTimeMillis();
_processor = processor;
boolean result = _executeImpl(_processor);
if (_isAsync == false) {
if (result) {
this.complete();
} else {
this.fail();
}
}
}
// ---------------------------------------------------------------------- //
// COMPLETION
// ---------------------------------------------------------------------- //
public final void finishWithResults(ProcessorTask task) {
_result = task._result;
_data = task._data;
_error = task._error;
_finish();
}
public final void complete() {
completeWithData(null);
}
public final void completeWithData(Object data) {
_result = true;
_data = data;
_finish();
}
public final void fail() {
failWithErrorAndData(null, null);
}
public final void failWithError(String error) {
failWithErrorAndData(error, null);
}
public final void failWithErrorAndData(String error, Object data) {
_result = false;
_error = error;
_data = data;
_finish();
}
private void _finish() {
if (_isFinished) {
Logger.getLogger(ProcessorTask.class.getName()).warning("Attempt to finish a task twice. " + Arrays.toString(Thread.currentThread().getStackTrace()));
return;
}
_isFinished = true;
_finishTime = System.currentTimeMillis();
if (this.getDelegate() != null) {
this.getDelegate().whenTaskIsFinished(this);
}
if (this.getNextTask() != null) {
_nextTask.setParentTask(this);
if (_nextTaskProcessor != null) {
_nextTaskProcessor.addTask(_nextTask);
} else {
_processor.addTask(_nextTask);
}
}
}
// ---------------------------------------------------------------------- //
// ABSTRACT
// ---------------------------------------------------------------------- //
protected abstract boolean _executeImpl(Processor processor);
}