package org.appwork.controlling;
public class StateLocker implements StateEventListener {
private StateMachine[] stateMachines;
private int counter;
private State waitState;
private State[] exceptions;
private State interruptState = null;
private StateMachine interruptStatemachine;
/**
* @param machines
*/
public StateLocker(StateMachine... machines) {
stateMachines = machines.clone();
counter = 0;
}
/**
* @param stoppedState
* @throws InterruptedException
* @throws StateExceptionException
*/
public void lockUntilAllHavePassed(final State state, final State... exceptions) throws InterruptedException, StateExceptionException {
waitState = state;
this.exceptions = exceptions;
if (stateMachines == null || stateMachines.length == 0) return;
try {
for (StateMachine st : stateMachines) {
for (State e : exceptions) {
if (st.hasPassed(e)) throw new StateExceptionException(st, e);
}
if (st.hasPassed(state)) {
increaseCounter();
} else {
st.addListener(this);
}
}
main: while (counter < stateMachines.length) {
synchronized (this) {
this.wait(2000);
}
if (interruptState != null) { throw new StateExceptionException(interruptStatemachine, interruptState); }
for (StateMachine st : stateMachines) {
if (!st.hasPassed(state)) {
continue main;
}
}
break;
}
} finally {
for (StateMachine st : stateMachines) {
st.removeListener(this);
}
}
}
/**
*
*/
private synchronized int increaseCounter() {
return ++counter;
}
public void onStateChange(StateEvent event) {
if (event.getNewState() == waitState) {
if (increaseCounter() == stateMachines.length) {
synchronized (this) {
this.notify();
}
event.getStateMachine().removeListener(this);
}
} else {
for (State s : exceptions) {
if (event.getNewState() == s) {
this.interruptState = s;
this.interruptStatemachine = event.getStateMachine();
synchronized (this) {
this.notify();
}
return;
}
}
}
}
public void onStateUpdate(StateEvent event) {
}
}