package jp.hasc.hasctool.core.runtime;

import java.util.concurrent.Callable;

/**
 * TaskManagerで起動できるTaskのためのスーパークラスです。
 * スレッドのようなものです。
 * @author iwasaki
 */
public abstract class AbstractTask extends AbstractRuntimeBean implements Callable<Object> {
	/** logger for this class */
	private final static org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
			.getLog(AbstractTask.class);
	
	private boolean called_ = false;

	public TaskManager getTaskManager() {
		return getRuntimeContext().getTaskManager();
	}
	
	@Override
	public Object call() {
		synchronized (this) {
			if (called_) {
				throw new IllegalStateException();
			}
			called_=true;
		}
		try {
			AbstractTask.this.run();
		} catch (InterruptedException ex) {
			LOG.warn("Task interrupted: "+AbstractTask.this.toString());
			LOG.warn("InterruptedException",ex);
		} catch (Throwable ex) {
			LOG.warn("Unhandled Exception",ex);
			getRuntimeContext().onCatchUnhandledException(ex);
		}
		return null;
	}
	
	/**
	 * 現在のスレッドで直接実行します。
	 */
	public void runDirect() throws InterruptedException {
		synchronized (this) {
			if (called_) {
				throw new IllegalStateException();
			}
			called_=true;
		}
		getTaskManager().runDirect(this);
	}

	protected boolean isShutdown() {
		return getTaskManager().getExecutorService().isShutdown();
	}
	
	protected abstract void run() throws InterruptedException;

	@Override
	public void setup(RuntimeContext context) {
		super.setup(context);
		getTaskManager().register(this);
	}
	
	/**
	 * RuntimeContext#startTasks()呼び出し後に、setupしたTaskを開始します。
	 */
	public void start() {
		getTaskManager().start(this);
	}
}
