package au.id.zancanaro.javacheck.state; import java.util.*; public class CommandList { private final List> commands; private final S initialState; public CommandList(S initialState, List> commands) { this.initialState = initialState; this.commands = new ArrayList<>(commands); } public int size() { return commands.size(); } public CommandResult run(S initialState) { Map values = new HashMap<>(); CommandResult result = CommandResult.success(initialState); for (GeneratedCommand generated : commands) { result = runRealCommand(generated, result.getState(), values); if (result.isFailed()) { break; } } return result; } private static CommandResult runRealCommand( GeneratedCommand generated, S state, Map values) { int id = generated.getId(); Command command = generated.getCommand(); A args = generated.getArgs(); try { if (!command.preCondition(state, args)) { return CommandResult.fail(state, new Error("Precondition failed")); } final S oldState = state; R result = CommandValue.withValues(values, () -> command.runCommand(oldState, args)); values.put(id, result); final S newState = CommandValue.withValues(values, () -> command.nextState(oldState, args, new CommandValue<>(id))); state = newState; try { CommandValue.withValues(values, () -> command.postCondition(oldState, newState, args, result)); } catch (Throwable ex) { return CommandResult.fail(state, ex); } return CommandResult.success(state); } catch (Throwable ex) { return CommandResult.fail(state, ex); } } private static CommandResult runAbstractCommand( GeneratedCommand generated, S state) { int id = generated.getId(); Command command = generated.getCommand(); A args = generated.getArgs(); try { if (!command.preCondition(state, args)) { return CommandResult.fail(state, new Error("Precondition failed")); } state = command.nextState(state, args, new CommandValue<>(id)); return CommandResult.success(state); } catch (Throwable ex) { return CommandResult.fail(state, ex); } } public boolean isValid() { CommandResult result = CommandResult.success(initialState); for (GeneratedCommand generated : commands) { result = runAbstractCommand(generated, result.getState()); if (result.isFailed()) { break; } } return !result.isFailed(); } @Override public String toString() { StringBuilder builder = new StringBuilder(); Iterator> iterator = commands.iterator(); while (iterator.hasNext()) { builder.append(iterator.next()); if (iterator.hasNext()) { builder.append(", \n\t"); } } return "\n\t" + builder.toString(); } }