From 05ec409ce96da92d430c4a8e58b08d46f42d667a Mon Sep 17 00:00:00 2001
From: Carlo Zancanaro <carlo@zancanaro.id.au>
Date: Fri, 5 Jun 2015 17:30:46 +1000
Subject: More work on the stateful checker; still not perfect, but it's
 getting better

---
 .../au/id/zancanaro/javacheck/state/Command.java   | 23 ++++++
 .../id/zancanaro/javacheck/state/CommandList.java  | 91 ++++++++++++++++++++++
 .../javacheck/state/CommandListGenerator.java      | 50 ++++++++++++
 .../zancanaro/javacheck/state/CommandResult.java   | 31 ++++++++
 .../id/zancanaro/javacheck/state/CommandValue.java | 47 +++++++++++
 .../javacheck/state/GeneratedCommand.java          | 52 +++++++++++++
 .../au/id/zancanaro/javacheck/statem/Command.java  | 23 ------
 .../id/zancanaro/javacheck/statem/CommandList.java | 85 --------------------
 .../javacheck/statem/CommandListGenerator.java     | 50 ------------
 .../zancanaro/javacheck/statem/CommandResult.java  | 31 --------
 .../zancanaro/javacheck/statem/CommandValue.java   | 60 --------------
 .../javacheck/statem/GeneratedCommand.java         | 56 -------------
 12 files changed, 294 insertions(+), 305 deletions(-)
 create mode 100644 src/main/java/au/id/zancanaro/javacheck/state/Command.java
 create mode 100644 src/main/java/au/id/zancanaro/javacheck/state/CommandList.java
 create mode 100644 src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java
 create mode 100644 src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java
 create mode 100644 src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java
 create mode 100644 src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java
 delete mode 100644 src/main/java/au/id/zancanaro/javacheck/statem/Command.java
 delete mode 100644 src/main/java/au/id/zancanaro/javacheck/statem/CommandList.java
 delete mode 100644 src/main/java/au/id/zancanaro/javacheck/statem/CommandListGenerator.java
 delete mode 100644 src/main/java/au/id/zancanaro/javacheck/statem/CommandResult.java
 delete mode 100644 src/main/java/au/id/zancanaro/javacheck/statem/CommandValue.java
 delete mode 100644 src/main/java/au/id/zancanaro/javacheck/statem/GeneratedCommand.java

(limited to 'src/main/java/au/id/zancanaro/javacheck')

diff --git a/src/main/java/au/id/zancanaro/javacheck/state/Command.java b/src/main/java/au/id/zancanaro/javacheck/state/Command.java
new file mode 100644
index 0000000..afa3957
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/javacheck/state/Command.java
@@ -0,0 +1,23 @@
+package au.id.zancanaro.javacheck.state;
+
+import au.id.zancanaro.javacheck.Generator;
+
+public abstract class Command<State,Args,Result> {
+    public Generator<Args> argsGenerator(State state) {
+        return Generator.pure(null);
+    }
+
+    public boolean preCondition(State state, Args args) {
+        return true;
+    }
+
+    public abstract Result runCommand(Args args);
+
+    public State nextState(State state, Args args, CommandValue<Result> result) {
+        return state;
+    }
+
+    public boolean postCondition(State oldState, State newState, Args args, Result result) {
+        return true;
+    }
+}
diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandList.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandList.java
new file mode 100644
index 0000000..0426fd3
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandList.java
@@ -0,0 +1,91 @@
+package au.id.zancanaro.javacheck.state;
+
+import java.util.*;
+
+public class CommandList<State> {
+    private final List<GeneratedCommand<State, ?, ?>> commands;
+
+    public CommandList(List<GeneratedCommand<State, ?, ?>> commands) {
+        this.commands = new ArrayList<>(commands);
+    }
+
+    public CommandResult<State> run(State initialState) {
+        Map<Integer, Object> values = new HashMap<>();
+        CommandResult<State> result = CommandResult.success(initialState);
+        for (GeneratedCommand<State, ?, ?> generated : commands) {
+            result = runRealCommand(generated, result.getState(), values);
+            if (result.isFailed()) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    private static <State, Args, Result> CommandResult<State> runRealCommand(
+            GeneratedCommand<State, Args, Result> generated,
+            State state,
+            Map<Integer, Object> values) {
+        int id = generated.getId();
+        Command<State, Args, Result> command = generated.getCommand();
+        Args args = generated.getArgs();
+        try {
+            if (!command.preCondition(state, args)) {
+                return CommandResult.fail(state, new Error("Precondition failed"));
+            }
+            Result result = CommandValue.withValues(values, () ->
+                    command.runCommand(args));
+            values.put(id, result);
+            final State oldState = state;
+            final State newState = CommandValue.withValues(values, () ->
+                    command.nextState(oldState, args, new CommandValue<>(id)));
+            state = newState;
+            if (!CommandValue.withValues(values, () -> command.postCondition(oldState, newState, args, result))) {
+                return CommandResult.fail(state, new Error("Postcondition failed"));
+            }
+            return CommandResult.success(state);
+        } catch (Throwable ex) {
+            return CommandResult.fail(state, ex);
+        }
+    }
+
+    private static <State, Args, Result> CommandResult<State> runAbstractCommand(
+            GeneratedCommand<State, Args, Result> generated,
+            State state) {
+        int id = generated.getId();
+        Command<State, Args, Result> command = generated.getCommand();
+        Args 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<State> result = CommandResult.success(null);
+        for (GeneratedCommand<State, ?, ?> generated : commands) {
+            result = runAbstractCommand(generated, result.getState());
+            if (result.isFailed()) {
+                break;
+            }
+        }
+        return !result.isFailed();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        Iterator<GeneratedCommand<State, ?, ?>> iterator = commands.iterator();
+        while (iterator.hasNext()) {
+            builder.append(iterator.next());
+            if (iterator.hasNext()) {
+                builder.append(", ");
+            }
+        }
+        return builder.toString();
+    }
+}
diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java
new file mode 100644
index 0000000..4c2c47f
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java
@@ -0,0 +1,50 @@
+package au.id.zancanaro.javacheck.state;
+
+import au.id.zancanaro.javacheck.Generator;
+import au.id.zancanaro.javacheck.ShrinkTree;
+
+import java.util.Random;
+import java.util.function.Function;
+
+import static au.id.zancanaro.javacheck.Generator.pure;
+import static au.id.zancanaro.javacheck.Generators.noShrink;
+
+public class CommandListGenerator<State> implements Generator<CommandList<State>> {
+    private final Function<State, Generator<Command<State, ?, ?>>> generateCommand;
+
+    public CommandListGenerator(Function<State, Generator<Command<State, ?, ?>>> generateCommand) {
+        this.generateCommand = generateCommand;
+    }
+
+    public Generator<GeneratedCommand<State, ?, ?>> commandGenerator(int id, State state) {
+        return noShrink(generateCommand.apply(state))
+                .flatMap(command -> generateSingleCommand(id, command, state));
+    }
+
+    public <Args, Result> Generator<GeneratedCommand<State, ?, ?>> generateSingleCommand(int id, Command<State, Args, Result> command, State state) {
+        return command.argsGenerator(state).flatMap(generatedArgs ->
+                command.preCondition(state, generatedArgs) ?
+                        pure(new GeneratedCommand<>(id, command, generatedArgs)) :
+                        commandGenerator(id, state));
+    }
+
+    public <Args, Result> State nextState(int id, GeneratedCommand<State, Args, Result> generatedCommand, State state) {
+        return generatedCommand.getCommand().nextState(state, generatedCommand.getArgs(), new CommandValue<>(id));
+    }
+
+    @Override
+    public ShrinkTree<CommandList<State>> generate(Random random, int size) {
+        int count = random.nextInt(size);
+        @SuppressWarnings("unchecked")
+        ShrinkTree<GeneratedCommand<State, ?, ?>>[] commandTrees = (ShrinkTree<GeneratedCommand<State, ?, ?>>[]) new ShrinkTree[count];
+        State state = null;
+        for (int i = 0; i < count; ++i) {
+            commandTrees[i] = commandGenerator(i, state).generate(random, size);
+            GeneratedCommand<State, ?, ?> generatedCommand = commandTrees[i].getValue();
+            state = nextState(i, generatedCommand, state);
+        }
+        return ShrinkTree.combine(commandTrees, ShrinkTree::removeAndPromoteChildren)
+                .map(list -> new CommandList<>(list))
+                .filter(CommandList::isValid);
+    }
+}
diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java
new file mode 100644
index 0000000..12f650d
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java
@@ -0,0 +1,31 @@
+package au.id.zancanaro.javacheck.state;
+
+public class CommandResult<State> {
+    private final State state;
+    private final Throwable thrown;
+
+    private CommandResult(State state, Throwable thrown) {
+        this.state = state;
+        this.thrown = thrown;
+    }
+
+    public State getState() {
+        return state;
+    }
+
+    public boolean isFailed() {
+        return thrown != null;
+    }
+
+    public Throwable getThrown() {
+        return thrown;
+    }
+
+    public static <State> CommandResult<State> success(State state) {
+        return new CommandResult<>(state, null);
+    }
+
+    public static <State> CommandResult<State> fail(State state, Throwable ex) {
+        return new CommandResult<>(state, ex);
+    }
+}
diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java
new file mode 100644
index 0000000..8d3f272
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java
@@ -0,0 +1,47 @@
+package au.id.zancanaro.javacheck.state;
+
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.function.Supplier;
+
+public class CommandValue<T> {
+    private static Map<Integer, Object> values = null;
+
+    public static <T> T withValues(Map<Integer, Object> newValues, Supplier<T> action) {
+        Map<Integer,Object> oldValues = values;
+        try {
+            values = newValues;
+            return action.get();
+        } finally {
+            values = oldValues;
+        }
+    }
+
+    private final int id;
+
+    public CommandValue(int id) {
+        this.id = id;
+    }
+
+    public boolean isAbstract() {
+        return values == null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public T get() {
+        if (values.containsKey(getId())) {
+            return (T) values.get(getId());
+        } else {
+            throw new NoSuchElementException("Concrete values cannot be supplied prior to being calculated");
+        }
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    @Override
+    public String toString() {
+        return "#{" + id + "}";
+    }
+}
diff --git a/src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java b/src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java
new file mode 100644
index 0000000..90d9a47
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java
@@ -0,0 +1,52 @@
+package au.id.zancanaro.javacheck.state;
+
+public class GeneratedCommand<State, Args, Result> {
+    private final int id;
+    private final Command<State, Args, Result> command;
+    private final Args args;
+
+    public GeneratedCommand(int id, Command<State, Args, Result> command, Args args) {
+        this.id = id;
+        this.command = command;
+        this.args = args;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public Command<State, Args, Result> getCommand() {
+        return command;
+    }
+
+    public Args getArgs() {
+        return args;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        GeneratedCommand that = (GeneratedCommand) o;
+
+        if (args != null ? !args.equals(that.args) : that.args != null)
+            return false;
+        if (command != null ? !command.equals(that.command) : that.command != null)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = command != null ? command.hashCode() : 0;
+        result = 31 * result + (args != null ? args.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "#{" + id + "} = " + command + " <- " + args;
+    }
+}
diff --git a/src/main/java/au/id/zancanaro/javacheck/statem/Command.java b/src/main/java/au/id/zancanaro/javacheck/statem/Command.java
deleted file mode 100644
index a741f0a..0000000
--- a/src/main/java/au/id/zancanaro/javacheck/statem/Command.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package au.id.zancanaro.javacheck.statem;
-
-import au.id.zancanaro.javacheck.Generator;
-
-public abstract class Command<State,Args,Result> {
-    public Generator<Args> argsGenerator(State state) {
-        return Generator.pure(null);
-    }
-
-    public boolean preCondition(State state, Args args) {
-        return true;
-    }
-
-    public abstract Result runCommand(Args args);
-
-    public State nextState(State state, Args args, CommandValue<Result> result) {
-        return state;
-    }
-
-    public boolean postCondition(State oldState, State newState, Args args, Result result) {
-        return true;
-    }
-}
diff --git a/src/main/java/au/id/zancanaro/javacheck/statem/CommandList.java b/src/main/java/au/id/zancanaro/javacheck/statem/CommandList.java
deleted file mode 100644
index 9e8948a..0000000
--- a/src/main/java/au/id/zancanaro/javacheck/statem/CommandList.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package au.id.zancanaro.javacheck.statem;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class CommandList<State> {
-    private final List<GeneratedCommand<State, ?, ?>> commands;
-
-    public CommandList(List<GeneratedCommand<State, ?, ?>> commands) {
-        this.commands = new ArrayList<>(commands);
-    }
-
-    public CommandResult<State> run(State initialState) {
-        Map<Integer, Object> values = new HashMap<>();
-        CommandResult<State> result = CommandResult.success(initialState);
-        for (GeneratedCommand<State, ?, ?> generated : commands) {
-            result = runRealCommand(generated, result.getState(), values);
-            if (result.isFailed()) {
-                break;
-            }
-        }
-        return result;
-    }
-
-    private static <State, Args, Result> CommandResult<State> runRealCommand(
-            GeneratedCommand<State, Args, Result> generated,
-            State state,
-            Map<Integer, Object> values) {
-        int id = generated.getId();
-        Command<State, Args, Result> command = generated.getCommand();
-        Args args = generated.getArgs();
-        try {
-            if (!command.preCondition(state, args)) {
-                return CommandResult.fail(state, new Error("Precondition failed"));
-            }
-            Result result = command.runCommand(args);
-            values.put(id, result);
-            State oldState = state;
-            state = command.nextState(state, args, new CommandValue.ConcreteValue<>(id, values));
-            if (!command.postCondition(oldState, state, args, result)) {
-                return CommandResult.fail(state, new Error("Postcondition failed"));
-            }
-            return CommandResult.success(state);
-        } catch (Throwable ex) {
-            return CommandResult.fail(state, ex);
-        }
-    }
-
-    private static <State, Args, Result> CommandResult<State> runAbstractCommand(
-            GeneratedCommand<State, Args, Result> generated,
-            State state) {
-        int id = generated.getId();
-        Command<State, Args, Result> command = generated.getCommand();
-        Args args = generated.getArgs();
-        try {
-            if (!command.preCondition(state, args)) {
-                return CommandResult.fail(state, new Error("Precondition failed"));
-            }
-            state = command.nextState(state, args, new CommandValue.AbstractValue<>(id));
-            return CommandResult.success(state);
-        } catch (Throwable ex) {
-            return CommandResult.fail(state, ex);
-        }
-    }
-
-    public boolean isValid() {
-        CommandResult<State> result = CommandResult.success(null);
-        for (GeneratedCommand<State, ?, ?> generated : commands) {
-            result = runAbstractCommand(generated, result.getState());
-            if (result.isFailed()) {
-                break;
-            }
-        }
-        return !result.isFailed();
-    }
-
-    @Override
-    public String toString() {
-        return "CommandList{" +
-                "commands=" + commands +
-                '}';
-    }
-}
diff --git a/src/main/java/au/id/zancanaro/javacheck/statem/CommandListGenerator.java b/src/main/java/au/id/zancanaro/javacheck/statem/CommandListGenerator.java
deleted file mode 100644
index a0df66f..0000000
--- a/src/main/java/au/id/zancanaro/javacheck/statem/CommandListGenerator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package au.id.zancanaro.javacheck.statem;
-
-import au.id.zancanaro.javacheck.Generator;
-import au.id.zancanaro.javacheck.ShrinkTree;
-
-import java.util.Random;
-import java.util.function.Function;
-
-import static au.id.zancanaro.javacheck.Generator.pure;
-import static au.id.zancanaro.javacheck.Generators.noShrink;
-
-public class CommandListGenerator<State> implements Generator<CommandList<State>> {
-    private final Function<State, Generator<Command<State, ?, ?>>> generateCommand;
-
-    public CommandListGenerator(Function<State, Generator<Command<State, ?, ?>>> generateCommand) {
-        this.generateCommand = generateCommand;
-    }
-
-    public Generator<GeneratedCommand<State, ?, ?>> commandGenerator(int id, State state) {
-        return noShrink(generateCommand.apply(state))
-                .flatMap(command -> generateSingleCommand(id, command, state));
-    }
-
-    public <Args, Result> Generator<GeneratedCommand<State, ?, ?>> generateSingleCommand(int id, Command<State, Args, Result> command, State state) {
-        return command.argsGenerator(state).flatMap(generatedArgs ->
-                command.preCondition(state, generatedArgs) ?
-                        pure(new GeneratedCommand<>(id, command, generatedArgs)) :
-                        commandGenerator(id, state));
-    }
-
-    public <Args, Result> State nextState(int id, GeneratedCommand<State, Args, Result> generatedCommand, State state) {
-        return generatedCommand.getCommand().nextState(state, generatedCommand.getArgs(), new CommandValue.AbstractValue<>(id));
-    }
-
-    @Override
-    public ShrinkTree<CommandList<State>> generate(Random random, int size) {
-        int count = random.nextInt(size);
-        @SuppressWarnings("unchecked")
-        ShrinkTree<GeneratedCommand<State, ?, ?>>[] commandTrees = (ShrinkTree<GeneratedCommand<State, ?, ?>>[]) new ShrinkTree[count];
-        State state = null;
-        for (int i = 0; i < count; ++i) {
-            commandTrees[i] = commandGenerator(i, state).generate(random, size);
-            GeneratedCommand<State, ?, ?> generatedCommand = commandTrees[i].getValue();
-            state = nextState(i, generatedCommand, state);
-        }
-        return ShrinkTree.combine(commandTrees, ShrinkTree::removeAndPromoteChildren)
-                .map(list -> new CommandList<>(list))
-                .filter(CommandList::isValid);
-    }
-}
diff --git a/src/main/java/au/id/zancanaro/javacheck/statem/CommandResult.java b/src/main/java/au/id/zancanaro/javacheck/statem/CommandResult.java
deleted file mode 100644
index dc5b085..0000000
--- a/src/main/java/au/id/zancanaro/javacheck/statem/CommandResult.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package au.id.zancanaro.javacheck.statem;
-
-public class CommandResult<State> {
-    private final State state;
-    private final Throwable thrown;
-
-    private CommandResult(State state, Throwable thrown) {
-        this.state = state;
-        this.thrown = thrown;
-    }
-
-    public State getState() {
-        return state;
-    }
-
-    public boolean isFailed() {
-        return thrown != null;
-    }
-
-    public Throwable getThrown() {
-        return thrown;
-    }
-
-    public static <State> CommandResult<State> success(State state) {
-        return new CommandResult<>(state, null);
-    }
-
-    public static <State> CommandResult<State> fail(State state, Throwable ex) {
-        return new CommandResult<>(state, ex);
-    }
-}
diff --git a/src/main/java/au/id/zancanaro/javacheck/statem/CommandValue.java b/src/main/java/au/id/zancanaro/javacheck/statem/CommandValue.java
deleted file mode 100644
index 0a1fb61..0000000
--- a/src/main/java/au/id/zancanaro/javacheck/statem/CommandValue.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package au.id.zancanaro.javacheck.statem;
-
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-public abstract class CommandValue<T> {
-    private final int id;
-
-    public CommandValue(int id) {
-        this.id = id;
-    }
-
-    public abstract boolean isAbstract();
-
-    public abstract T get();
-
-    public int getId() {
-        return id;
-    }
-
-    static class AbstractValue<T> extends CommandValue<T> {
-        public AbstractValue(int id) {
-            super(id);
-        }
-
-        @Override
-        public boolean isAbstract() {
-            return true;
-        }
-
-        @Override
-        public T get() {
-            throw new NoSuchElementException("Abstract values cannot be supplied");
-        }
-    }
-
-    static class ConcreteValue<T> extends CommandValue<T> {
-        private final Map<Integer, Object> values;
-
-        public ConcreteValue(int id, Map<Integer, Object> values) {
-            super(id);
-            this.values = values;
-        }
-
-        @Override
-        public boolean isAbstract() {
-            return true;
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public T get() {
-            if (values.containsKey(getId())) {
-                return (T) values.get(getId());
-            } else {
-                throw new NoSuchElementException("Concrete values cannot be supplied prior to being calculated");
-            }
-        }
-    }
-}
diff --git a/src/main/java/au/id/zancanaro/javacheck/statem/GeneratedCommand.java b/src/main/java/au/id/zancanaro/javacheck/statem/GeneratedCommand.java
deleted file mode 100644
index 5e576b4..0000000
--- a/src/main/java/au/id/zancanaro/javacheck/statem/GeneratedCommand.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package au.id.zancanaro.javacheck.statem;
-
-public class GeneratedCommand<State, Args, Result> {
-    private final int id;
-    private final Command<State, Args, Result> command;
-    private final Args args;
-
-    public GeneratedCommand(int id, Command<State, Args, Result> command, Args args) {
-        this.id = id;
-        this.command = command;
-        this.args = args;
-    }
-
-    public int getId() {
-        return id;
-    }
-
-    public Command<State, Args, Result> getCommand() {
-        return command;
-    }
-
-    public Args getArgs() {
-        return args;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        GeneratedCommand that = (GeneratedCommand) o;
-
-        if (args != null ? !args.equals(that.args) : that.args != null)
-            return false;
-        if (command != null ? !command.equals(that.command) : that.command != null)
-            return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = command != null ? command.hashCode() : 0;
-        result = 31 * result + (args != null ? args.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "GeneratedCommand{" +
-                "id=" + id +
-                ", command=" + command +
-                ", args=" + args +
-                '}';
-    }
-}
-- 
cgit v1.2.3