package org.ovirt.engine.ui.uicompat;
import java.util.ArrayList;
import java.util.List;
public class ReversibleFlow {
List<IEnlistmentNotification> notifications;
int prepareIndex;
int commitIndex;
int rollbackIndex;
Object context;
public static final EventDefinition completeEventDefinition;
private Event<EventArgs> completeEvent;
public Event<EventArgs> getCompleteEvent() {
return completeEvent;
}
static {
completeEventDefinition = new EventDefinition("Complete", ReversibleFlow.class); //$NON-NLS-1$
}
public ReversibleFlow() {
completeEvent = new Event<>(completeEventDefinition);
notifications = new ArrayList<>();
}
public void enlist(IEnlistmentNotification notification) {
// Add notifier to the list.
notifications.add(notification);
}
/**
* Note, the current implementation is not thread safe (good enough for UI)
*/
public void run() {
// Begin processing notifications.
if (notifications.size() > 0) {
prepareIndex = 0;
rollbackIndex = notifications.size();
prepare();
}
}
public void run(Object context) {
this.context = context;
run();
}
private void prepare() {
PreparingEnlistment enlistment = new PreparingEnlistment(context);
enlistment.getPreparedEvent().addListener((ev, sender, args) -> preparedHandler());
enlistment.getRollbackEvent().addListener((ev, sender, args) -> rollbackHandler());
enlistment.getDoneEvent().addListener((ev, sender, args) -> doneOnPrepareHandler());
IEnlistmentNotification notification = notifications.get(prepareIndex);
notification.prepare(enlistment);
}
private void commit() {
Enlistment enlistment = new Enlistment(context);
enlistment.getDoneEvent().addListener((ev, sender, args) -> doneOnCommitHandler());
IEnlistmentNotification notification = notifications.get(commitIndex);
notification.commit(enlistment);
}
private void rollback() {
Enlistment enlistment = new Enlistment(context);
enlistment.getDoneEvent().addListener((ev, sender, args) -> doneOnRollbackHandler());
IEnlistmentNotification notification = notifications.get(rollbackIndex);
notification.rollback(enlistment);
}
private void preparedHandler() {
if (prepareIndex == notifications.size() - 1) {
// Move to the next (commit) stage.
commitIndex = 0;
commit();
} else {
// Process next notification.
prepareIndex++;
prepare();
}
}
private void rollbackHandler() {
if (rollbackIndex == 0) {
complete();
} else {
// Process next notification.
rollbackIndex--;
rollback();
}
}
private void doneOnPrepareHandler() {
complete();
}
private void doneOnRollbackHandler() {
rollbackHandler();
}
private void doneOnCommitHandler() {
if (commitIndex == notifications.size() - 1) {
complete();
} else {
// Process next notification.
commitIndex++;
commit();
}
}
private void complete() {
getCompleteEvent().raise(this, EventArgs.EMPTY);
}
}