package org.oddjob.jobs.tasks; import java.util.Date; import java.util.concurrent.Callable; import org.oddjob.Stateful; import org.oddjob.framework.JobDestroyedException; import org.oddjob.state.State; import org.oddjob.state.StateConditions; import org.oddjob.state.StateEvent; import org.oddjob.state.StateHandler; import org.oddjob.state.StateListener; /** * A {@link TaskView} that is based on a job that is performing the task. * * @author rob * */ abstract public class JobTaskView implements TaskView { private final StateHandler<TaskState> stateHandler = new StateHandler<TaskState>(this, TaskState.PENDING); private volatile Object response; private final StateListener listener = new StateListener() { public void jobStateChange(final StateEvent event) { final State state = event.getState(); final Date time = event.getTime(); // Called before the event is fired so the response will // be known by clients waiting for the complete event. if (StateConditions.DONE.test(state)) { response = onDone(); } if (StateConditions.FINISHED.test(state)) { event.getSource().removeStateListener(this); } stateHandler.callLocked(new Callable<Void>() { @Override public Void call() throws Exception { TaskState newState; Throwable exception = null; if (state.isDestroyed()) { newState = TaskState.EXCEPTION; exception = new TaskException("Job Executing Task has been destroyed."); } else if (state.isStoppable()) { newState = TaskState.INPROGRESS; } else if (state.isIncomplete()) { newState = TaskState.INCOMPLETE; } else if (state.isComplete()) { newState = TaskState.COMPLETE; } else if (state.isException()) { newState = TaskState.EXCEPTION; exception = event.getException(); } else if (state.isReady()) { newState = TaskState.PENDING; } else { throw new IllegalStateException("Unconvertable state " + state); } if (newState == stateHandler.lastStateEvent().getState()) { return null; } if (newState == TaskState.EXCEPTION) { stateHandler.setStateException( TaskState.EXCEPTION, exception, time); } else { stateHandler.setState(newState, time); } stateHandler.fireEvent(); return null; } }); } }; public JobTaskView(Stateful job) { job.addStateListener(listener); } protected abstract Object onDone(); @Override public StateEvent lastStateEvent() { return stateHandler.lastStateEvent(); } @Override public void addStateListener(StateListener listener) throws JobDestroyedException { stateHandler.addStateListener(listener); } @Override public void removeStateListener(StateListener listener) { stateHandler.removeStateListener(listener); } @Override public Object getTaskResponse() { return response; } }