package org.oddjob.scheduling.state;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.oddjob.Stateful;
import org.oddjob.framework.JobDestroyedException;
import org.oddjob.state.ParentState;
import org.oddjob.state.StateEvent;
import org.oddjob.state.StateListener;
import org.oddjob.state.StateOperator;
/**
* A {@link Stateful} that adapts a {@link ParentState}s to
* {@link TimerState}s. Required because {@link StateOperator}s provide
* {@code ParentState}s but timers need to reflect the child states as a
* {@code TimerState}.
*
* @author rob
*
*/
public class TimerStateAdapter implements Stateful {
private final Stateful adapting;
private final Map<StateListener, StateListener> adaptedListeners
= new ConcurrentHashMap<StateListener, StateListener>();
/**
* Create a new instance.
*
* @param adapting The {@link Stateful} that provides
* {@link ParentState}s.
*/
public TimerStateAdapter(Stateful adapting) {
this.adapting = adapting;
}
/**
* Convert the event that is assumed to contain a {@link ParentState}
* into an equivalent event that contains a {@link TimerState}.
*
* @param event The original event.
* @return The new event.
*/
protected StateEvent convert(StateEvent event) {
ParentState parentState = (ParentState) event.getState();
TimerState timerState;
switch (parentState) {
case ACTIVE:
timerState = TimerState.ACTIVE;
break;
case COMPLETE:
timerState = TimerState.COMPLETE;
break;
case EXCEPTION:
timerState = TimerState.EXCEPTION;
break;
case INCOMPLETE:
timerState = TimerState.INCOMPLETE;
break;
case READY:
timerState = TimerState.STARTABLE;
break;
case STARTED:
timerState = TimerState.STARTED;
break;
case EXECUTING:
case DESTROYED:
default:
throw new IllegalStateException(parentState.toString());
}
return new StateEvent(event.getSource(), timerState,
event.getTime(), event.getException());
}
@Override
public StateEvent lastStateEvent() {
return convert(adapting.lastStateEvent());
}
@Override
public void addStateListener(final StateListener listener)
throws JobDestroyedException {
StateListener adaptedListener = new StateListener() {
@Override
public void jobStateChange(StateEvent event) {
listener.jobStateChange(convert(event));
}
};
adaptedListeners.put(listener, adaptedListener);
adapting.addStateListener(adaptedListener);
}
@Override
public void removeStateListener(StateListener listener) {
StateListener adaptedListener = adaptedListeners.remove(listener);
if (adaptedListener == null) {
return;
}
adapting.removeStateListener(adaptedListener);
}
}