/** * Runs a relay defined by a chain of steps. * * @param <RES> return type of the entire relay * @param firstStep a first step that defines the entire relay * @param callback * @param relaySyncCallback a {@link SyncCallback} wrapped as {@link RelaySyncCallback} */ public static <RES> RelayOk run( final WipCommandProcessor commandProcessor, Step<RES> firstStep, final GenericCallback<RES> callback, final RelaySyncCallback relaySyncCallback) { return firstStep.accept( new Step.Visitor<RelayOk, RES>() { @Override public RelayOk visitFinal(RES finalResult) { if (callback != null) { callback.success(finalResult); } return relaySyncCallback.finish(); } @Override public RelayOk visitSend(final SendStepSimple<RES> sendStep) { final RelaySyncCallback.Guard guard = relaySyncCallback.newGuard(); WipCommandCallback sendCallback = new WipCommandCallback() { @Override public void messageReceived(WipCommandResponse response) { Step<RES> processResult; try { processResult = sendStep.processResponse(); } catch (ProcessException e) { if (callback != null) { callback.failure(e); } // Todo: consider throwing e. return; } RelayOk relayOk = run(commandProcessor, processResult, callback, guard.getRelay()); guard.discharge(relayOk); } @Override public void failure(String message) { if (callback != null) { callback.failure(sendStep.processFailure(new Exception(message))); } } }; return commandProcessor.send( sendStep.getParams(), sendCallback, guard.asSyncCallback()); } @Override public <RESPONSE> RelayOk visitSend(final SendStepWithResponse<RESPONSE, RES> sendStep) { final RelaySyncCallback.Guard guard = relaySyncCallback.newGuard(); GenericCallback<RESPONSE> sendCallback = new GenericCallback<RESPONSE>() { @Override public void success(RESPONSE response) { Step<RES> processResult; try { processResult = sendStep.processResponse(response); } catch (ProcessException e) { if (callback != null) { callback.failure(e); } // Todo: consider throwing e. return; } RelayOk relayOk = run(commandProcessor, processResult, callback, guard.getRelay()); guard.discharge(relayOk); } @Override public void failure(Exception exception) { if (callback != null) { callback.failure(sendStep.processFailure(exception)); } } }; return commandProcessor.send( sendStep.getParams(), sendCallback, guard.asSyncCallback()); } }); }