package er.extensions.concurrency; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; import com.webobjects.foundation.NSKeyValueCoding; import er.extensions.foundation.IERXStatus; /** * A FutureTask that implements {@link IERXStatus}, {@link IERXPercentComplete} and * {@link NSKeyValueCoding}. Additional methods are provided in this FutureTask for checking * if those interfaces are implemented in the wrapped task and if so the values are passed thru * from the task. * * Usage: * <blockquote><pre> // If null, then submit the callable task ERXFutureTask _future = new ERXFutureTask(callable); ERXExecutorService.executorService().execute(_future); </pre></blockquote> * * @author kieran * @param <V> the result type returned by this ERXFutureTask's get method */ public class ERXFutureTask<V> extends FutureTask<V> implements IERXExecutionStateTransition, IERXStatus, IERXPercentComplete, NSKeyValueCoding { private final Object _task; public ERXFutureTask(Callable<V> callable) { super(callable); _task = callable; } public ERXFutureTask(Runnable runnable, V result) { super(runnable, result); _task = runnable; } public Object task() { return _task; } /* (non-Javadoc) * @see er.extensions.foundation.IERXStatus#status() */ public String status() { return (hasStatus() && _task != null) ? ((IERXStatus) _task).status() : null; } /* (non-Javadoc) * @see er.extensions.concurrency.IERXPercentComplete#percentComplete() */ public Double percentComplete() { return (hasPercentComplete() && _task != null) ? ((IERXPercentComplete) _task).percentComplete() : null; } public void takeValueForKey(Object value, String key) { NSKeyValueCoding.DefaultImplementation.takeValueForKey(this, value, key); } public Object valueForKey(String key) { return NSKeyValueCoding.DefaultImplementation.valueForKey(this, key); } private Boolean _hasStatus; /** * @return whether the wrapped task implements the {@link IERXStatus} interface */ public boolean hasStatus() { if (_hasStatus == null) { _hasStatus = Boolean.valueOf(_task instanceof IERXStatus); } // ~ if (_hasStatus == null) return _hasStatus.booleanValue(); } private Boolean _isStoppable; /** * @return whether the wrapped task implements the {@link IERXStoppable} interface */ public boolean isStoppable() { if (_isStoppable == null) { _isStoppable = Boolean.valueOf(_task instanceof IERXStoppable); } return _isStoppable.booleanValue(); } private Boolean _hasPercentComplete; /** * @return whether the wrapped task implements the {@link IERXPercentComplete} interface */ public boolean hasPercentComplete() { if (_hasPercentComplete == null) { _hasPercentComplete = Boolean.valueOf(_task instanceof IERXPercentComplete); } return _hasPercentComplete; } public void afterExecute() { if (_task instanceof IERXExecutionStateTransition) { ((IERXExecutionStateTransition) _task).afterExecute(); } } public void beforeExecute() { if (_task instanceof IERXExecutionStateTransition) { ((IERXExecutionStateTransition) _task).beforeExecute(); } } @Override public String toString() { return _task == null ? super.toString() : _task.toString(); } }