package org.schmivits.airball.dataproxy.data;
import java.util.Map;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public abstract class RpcStates extends ConcurrentProcess {
public interface ThreadState {
void onEnter() throws Exception;
void onCleanup();
}
private static final long TRY_AGAIN_INTERVAL = 1000L;
private final Map<String, ThreadState> mStates;
private final String mInitialState;
protected RpcStates(Context context, ProcessNode parent, String title, String initialState) {
super(context, parent, title);
mStates = buildStates();
mInitialState = initialState;
}
@Override
public final void doRun() {
while (isRunning()) {
try {
enter(mInitialState);
} catch (InterruptedException e) {
return;
} catch (RuntimeException e) {
setStatus(e.toString());
}
try {
Thread.sleep(TRY_AGAIN_INTERVAL);
} catch (InterruptedException e) {
return;
}
}
}
protected abstract Map<String, ThreadState> buildStates();
protected void enter(String name) throws InterruptedException {
try {
reportEnter(name);
mStates.get(name).onEnter();
} catch (Exception e) {
handleException(name, e);
} finally {
mStates.get(name).onCleanup();
reportExit(name);
}
}
private void reportEnter(String name) {
setStatus("-> entering " + name);
}
private void reportExit(String name) {
setStatus("<- exiting " + name);
}
private void handleException(String name, Exception e) throws InterruptedException {
if (e instanceof InterruptedException) {
setStatus(name + " interrupted");
throw (InterruptedException) e;
} else if (e instanceof RuntimeException) {
setStatus(name + " exception " + e.toString());
throw (RuntimeException) e;
} else {
setStatus(name + " exception " + e.toString());
throw new RuntimeException(e);
}
}
}