package com.hammurapi.common.concurrent;

import java.util.concurrent.Callable;

/**
 * Callable which callInternal() method is invoked only once. 
 * @author Pavel Vlasov
 *
 * @param <T>
 */
public abstract class OneOffCallable<T> implements Callable<T> {

	private boolean hasRun;
	private Exception exception;
	private T result;

	public synchronized T call() throws Exception {
		if (!hasRun) {
			try {
				result = callInternal();
			} catch (Exception e) {
				exception = e;
			} finally {
				hasRun = true;				
			}
		}
		
		if (exception!=null) {
			throw exception;
		}
		return result;			
	}

	/**
	 * This method is invoked once by the call() method.
	 * @return
	 */
	protected abstract T callInternal() throws Exception;

}
