diff --git a/CHANGELOG.md b/CHANGELOG.md
index 525292e87267f6a53daabed30a1ca02e1bed77dd..35ff11516d65b633db6285ecde0205190ba70af4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@
 
 * Updated ProB 2 to version 4.0.0-SNAPSHOT.
 * Improved the performance of loading machines by reusing the existing instance of ProB instead of starting a new one for each machine.
+* Changed the `:exec`, `:init` and `:constants` commands to automatically move forward or backward in the trace to allow the command to execute successfully.
+	* Executing `:init` in an already initialised state will return to the last uninitialised state to re-initialise the machine (possibly with different initial values). The same works for `:constants`. Previously this caused an error "Machine is already initialised" or "Machine constants are already set up".
+	* Executing an operation in an uninitialised state will automatically initialise the machine with an arbitrary valid initialisation transition. If the machine has constants, they are also set up automatically in a similar way. This is useful if the machine's constants/initial variables are unambiguous or the exact values are not important. Previously this caused an error "Machine is not initialised".
 * Significantly refactored the logic for parsing commands and their arguments.
 	* This is an internal change and should not affect any user-visible behavior. That is, all inputs that were accepted by previous versions should still be accepted - if any previously valid inputs are no longer accepted, this is a bug.
 	* As a side effect, the inspection and code completion features now work better in a few edge cases.
diff --git a/notebooks/tests/animate.ipynb b/notebooks/tests/animate.ipynb
index 15c0a4cca42da0bad896fee6c2cfadf83265566c..997fb31159d0c74e9b6e027fecbaf50c82fcf9e2 100644
--- a/notebooks/tests/animate.ipynb
+++ b/notebooks/tests/animate.ipynb
@@ -564,15 +564,15 @@
    "outputs": [
     {
      "ename": "IllegalArgumentException",
-     "evalue": "Executing operation $setup_constants with predicate 1=1 produced errors: Machine is already initialised, cannot execute SETUP_CONSTANTS",
+     "evalue": "Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope",
      "output_type": "error",
      "traceback": [
-      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $setup_constants with predicate 1=1 produced errors: Machine is already initialised, cannot execute SETUP_CONSTANTS\u001b[0m"
+      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope\u001b[0m"
      ]
     }
    ],
    "source": [
-    ":constants"
+    ":exec nope"
    ]
   },
   {
@@ -582,114 +582,294 @@
    "outputs": [
     {
      "ename": "IllegalArgumentException",
-     "evalue": "Executing operation $initialise_machine with predicate 1=1 produced errors: Machine is already initialised, cannot execute INITIALISATION",
+     "evalue": "Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)",
      "output_type": "error",
      "traceback": [
-      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $initialise_machine with predicate 1=1 produced errors: Machine is already initialised, cannot execute INITIALISATION\u001b[0m"
+      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)\u001b[0m"
      ]
     }
    ],
    "source": [
-    ":init"
+    ":exec add 1=0"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 25,
    "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Loaded machine: NoConstants"
+      ]
+     },
+     "execution_count": 25,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "::load\n",
+    "MACHINE NoConstants\n",
+    "VARIABLES z\n",
+    "INVARIANT z : MININT..MAXINT\n",
+    "INITIALISATION z :: {0, 1}\n",
+    "OPERATIONS\n",
+    "    nothing = skip\n",
+    "END"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "metadata": {},
    "outputs": [
     {
      "ename": "IllegalArgumentException",
-     "evalue": "Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope",
+     "evalue": "Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root",
      "output_type": "error",
      "traceback": [
-      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope\u001b[0m"
+      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root\u001b[0m"
      ]
     }
    ],
    "source": [
-    ":exec nope"
+    ":constants"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 27,
    "metadata": {},
    "outputs": [
     {
-     "ename": "IllegalArgumentException",
-     "evalue": "Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)",
+     "ename": "ProBError",
+     "evalue": "ProB reported Errors\nProB returned error messages:\nError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)",
      "output_type": "error",
      "traceback": [
-      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)\u001b[0m"
+      "\u001b[1m\u001b[30mError from ProB: \u001b[0m\u001b[1m\u001b[31mProB reported Errors\u001b[0m",
+      "\u001b[1m\u001b[31mError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)\u001b[0m",
+      "\u001b[1m\u001b[30m// Source code not known\u001b[0m"
      ]
     }
    ],
    "source": [
-    ":exec add 1=0"
+    ":init z = -1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Executing an operation in an uninitialised machine automatically initialises the machine."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 28,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "Loaded machine: NoConstants"
+       "Machine was not initialised yet. Automatically initialised machine using arbitrary transition: INITIALISATION()\n",
+       "Executed operation: nothing()"
+      ]
+     },
+     "execution_count": 28,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":exec nothing"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "An already initialised machine can be reinitialised."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Machine was already initialised. Returned to uninitialised state to re-initialise the machine.\n",
+       "Executed operation: INITIALISATION()"
+      ]
+     },
+     "execution_count": 29,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":init z = 1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The same also works if the machine has constants."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Loaded machine: ItHasConstants"
       ]
      },
-     "execution_count": 27,
+     "execution_count": 30,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "::load\n",
-    "MACHINE NoConstants\n",
+    "MACHINE ItHasConstants\n",
+    "CONSTANTS c\n",
+    "PROPERTIES c : MININT..MAXINT\n",
     "VARIABLES z\n",
     "INVARIANT z : MININT..MAXINT\n",
     "INITIALISATION z :: {0, 1}\n",
+    "OPERATIONS\n",
+    "    nothing = skip\n",
     "END"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 31,
    "metadata": {},
    "outputs": [
     {
      "ename": "IllegalArgumentException",
-     "evalue": "Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root",
+     "evalue": "Executing operation $initialise_machine with predicate z = 0 produced errors: Could not execute operation INITIALISATION in state root with additional predicate",
      "output_type": "error",
      "traceback": [
-      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root\u001b[0m"
+      "\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $initialise_machine with predicate z = 0 produced errors: Could not execute operation INITIALISATION in state root with additional predicate\u001b[0m"
      ]
     }
    ],
    "source": [
-    ":constants"
+    ":init z = 0"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 32,
    "metadata": {},
    "outputs": [
     {
-     "ename": "ProBError",
-     "evalue": "ProB reported Errors\nProB returned error messages:\nError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[1m\u001b[30mError from ProB: \u001b[0m\u001b[1m\u001b[31mProB reported Errors\u001b[0m",
-      "\u001b[1m\u001b[31mError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)\u001b[0m",
-      "\u001b[1m\u001b[30m// Source code not known\u001b[0m"
-     ]
+     "data": {
+      "text/plain": [
+       "Executed operation: SETUP_CONSTANTS()"
+      ]
+     },
+     "execution_count": 32,
+     "metadata": {},
+     "output_type": "execute_result"
     }
    ],
    "source": [
-    ":init z = -1"
+    ":constants c = 2"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Machine was not initialised yet. Automatically initialised machine using arbitrary transition: INITIALISATION()\n",
+       "Executed operation: nothing()"
+      ]
+     },
+     "execution_count": 33,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":exec nothing"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Machine was already initialised. Returned to uninitialised state to re-initialise the machine.\n",
+       "Executed operation: INITIALISATION()"
+      ]
+     },
+     "execution_count": 34,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":init z = 1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Changed to state with index -1"
+      ]
+     },
+     "execution_count": 35,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":goto -1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Machine constants were not set up yet. Automatically set up constants using arbitrary transition: SETUP_CONSTANTS()\n",
+       "Machine was not initialised yet. Automatically initialised machine using arbitrary transition: INITIALISATION()\n",
+       "Executed operation: nothing()"
+      ]
+     },
+     "execution_count": 36,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":exec nothing"
    ]
   },
   {
@@ -701,7 +881,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 37,
    "metadata": {},
    "outputs": [
     {
@@ -710,7 +890,7 @@
        "Loaded machine: Foo"
       ]
      },
-     "execution_count": 30,
+     "execution_count": 37,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -728,7 +908,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 31,
+   "execution_count": 38,
    "metadata": {},
    "outputs": [
     {
@@ -737,7 +917,7 @@
        "Executed operation: SETUP_CONSTANTS()"
       ]
      },
-     "execution_count": 31,
+     "execution_count": 38,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -748,7 +928,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 32,
+   "execution_count": 39,
    "metadata": {},
    "outputs": [
     {
@@ -757,7 +937,7 @@
        "Executed operation: INITIALISATION()"
       ]
      },
-     "execution_count": 32,
+     "execution_count": 39,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -768,7 +948,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 40,
    "metadata": {},
    "outputs": [
     {
@@ -780,7 +960,7 @@
        "1"
       ]
      },
-     "execution_count": 33,
+     "execution_count": 40,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -791,7 +971,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 41,
    "metadata": {},
    "outputs": [
     {
@@ -803,7 +983,7 @@
        "2"
       ]
      },
-     "execution_count": 34,
+     "execution_count": 41,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -821,7 +1001,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 42,
    "metadata": {},
    "outputs": [
     {
@@ -830,7 +1010,7 @@
        "Loaded machine: Counter"
       ]
      },
-     "execution_count": 35,
+     "execution_count": 42,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -854,7 +1034,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 36,
+   "execution_count": 43,
    "metadata": {},
    "outputs": [
     {
@@ -866,7 +1046,7 @@
        "1"
       ]
      },
-     "execution_count": 36,
+     "execution_count": 43,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -877,7 +1057,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 37,
+   "execution_count": 44,
    "metadata": {},
    "outputs": [
     {
@@ -889,7 +1069,7 @@
        "2"
       ]
      },
-     "execution_count": 37,
+     "execution_count": 44,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -900,7 +1080,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 38,
+   "execution_count": 45,
    "metadata": {},
    "outputs": [
     {
@@ -909,7 +1089,7 @@
        "Executed operation: SETUP_CONSTANTS()"
       ]
      },
-     "execution_count": 38,
+     "execution_count": 45,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -920,7 +1100,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 39,
+   "execution_count": 46,
    "metadata": {},
    "outputs": [
     {
@@ -932,7 +1112,7 @@
        "{−1,0,1,2}"
       ]
      },
-     "execution_count": 39,
+     "execution_count": 46,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -943,7 +1123,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 40,
+   "execution_count": 47,
    "metadata": {},
    "outputs": [
     {
@@ -952,7 +1132,7 @@
        "Executed operation: INITIALISATION()"
       ]
      },
-     "execution_count": 40,
+     "execution_count": 47,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -963,7 +1143,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 41,
+   "execution_count": 48,
    "metadata": {},
    "outputs": [
     {
@@ -975,7 +1155,7 @@
        "1"
       ]
      },
-     "execution_count": 41,
+     "execution_count": 48,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -986,7 +1166,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 42,
+   "execution_count": 49,
    "metadata": {},
    "outputs": [
     {
@@ -995,7 +1175,7 @@
        "Executed operation: add(-1)"
       ]
      },
-     "execution_count": 42,
+     "execution_count": 49,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1006,7 +1186,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 43,
+   "execution_count": 50,
    "metadata": {},
    "outputs": [
     {
@@ -1018,7 +1198,7 @@
        "0"
       ]
      },
-     "execution_count": 43,
+     "execution_count": 50,
      "metadata": {},
      "output_type": "execute_result"
     }
diff --git a/src/main/java/de/prob2/jupyter/ProBKernel.java b/src/main/java/de/prob2/jupyter/ProBKernel.java
index 9f852d19b88374ed76d3c63bd6e9ef602898cf9f..8bb100ceece1c3ac62203f5c3f10fd3123c9259a 100644
--- a/src/main/java/de/prob2/jupyter/ProBKernel.java
+++ b/src/main/java/de/prob2/jupyter/ProBKernel.java
@@ -15,6 +15,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Properties;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 import java.util.regex.Matcher;
@@ -32,6 +33,7 @@ import de.prob.animator.domainobjects.FormulaExpand;
 import de.prob.exception.ProBError;
 import de.prob.scripting.ClassicalBFactory;
 import de.prob.statespace.AnimationSelector;
+import de.prob.statespace.State;
 import de.prob.statespace.StateSpace;
 import de.prob.statespace.Trace;
 import de.prob.statespace.Transition;
@@ -304,22 +306,81 @@ public final class ProBKernel extends BaseKernel {
 		this.setCurrentMachineDirectory(machineDirectory);
 	}
 	
+	private static @NotNull Transition singleTransitionFromPredicate(final State state, final String opName, final String predicate) {
+		final List<Transition> ops = state.getStateSpace().transitionFromPredicate(state, opName, predicate, 1);
+		assert !ops.isEmpty();
+		return ops.get(0);
+	}
+	
 	public @NotNull DisplayData executeOperation(final @NotNull String name, final @Nullable String predicate) {
-		final Trace trace = this.animationSelector.getCurrentTrace();
+		Trace trace = this.animationSelector.getCurrentTrace();
 		final String translatedOpName = Transition.unprettifyName(name);
+		final StringBuilder sb = new StringBuilder();
+		
+		if (Transition.SETUP_CONSTANTS_NAME.equals(translatedOpName) && trace.getCurrentState().isConstantsSetUp()) {
+			trace = trace.gotoPosition(-1);
+			sb.append("Machine constants were already set up. Returned to root state to set up machine constants again.\n");
+		} else if (Transition.INITIALISE_MACHINE_NAME.equals(translatedOpName) && trace.getCurrentState().isInitialised()) {
+			// The last uninitialised state may be at index 0 (if SETUP_CONSTANTS exists) or at index -1 (if not).
+			trace = trace.gotoPosition(0);
+			if (trace.getCurrentState().isInitialised()) {
+				trace = trace.gotoPosition(-1);
+			}
+			sb.append("Machine was already initialised. Returned to uninitialised state to re-initialise the machine.\n");
+		}
+		
 		final String modifiedPredicate;
 		if (predicate == null) {
 			modifiedPredicate = "1=1";
 		} else {
 			modifiedPredicate = this.insertLetVariables(predicate);
 		}
-		final List<Transition> ops = trace.getStateSpace().transitionFromPredicate(trace.getCurrentState(), translatedOpName, modifiedPredicate, 1);
-		assert !ops.isEmpty();
-		final Transition op = ops.get(0);
+		Transition op;
+		try {
+			op = singleTransitionFromPredicate(trace.getCurrentState(), translatedOpName, modifiedPredicate);
+		} catch (IllegalArgumentException e) {
+			if (!trace.getCurrentState().isConstantsSetUp()) {
+				if (Transition.PARTIAL_SETUP_CONSTANTS_NAME.equals(translatedOpName) || Transition.SETUP_CONSTANTS_NAME.equals(translatedOpName)) {
+					throw e;
+				} else {
+					final Set<Transition> setupConstantsTransitions = trace.getNextTransitions();
+					if (setupConstantsTransitions.isEmpty()) {
+						throw new UserErrorException("Machine constants are not set up and no valid constant values were found automatically - cannot execute operation " + name, e);
+					}
+					final Transition setupConstants = setupConstantsTransitions.iterator().next();
+					trace = trace.add(setupConstants);
+					trace.getStateSpace().evaluateTransitions(Collections.singleton(setupConstants), FormulaExpand.TRUNCATE);
+					sb.append("Machine constants were not set up yet. Automatically set up constants using arbitrary transition: ");
+					sb.append(setupConstants.getPrettyRep());
+					sb.append('\n');
+				}
+			}
+			
+			if (!trace.getCurrentState().isInitialised()) {
+				if (Transition.PARTIAL_SETUP_CONSTANTS_NAME.equals(translatedOpName) || Transition.SETUP_CONSTANTS_NAME.equals(translatedOpName) || Transition.INITIALISE_MACHINE_NAME.equals(translatedOpName)) {
+					throw e;
+				} else {
+					final Set<Transition> initialisationTransitions = trace.getNextTransitions();
+					if (initialisationTransitions.isEmpty()) {
+						throw new UserErrorException("Machine is not initialised and no valid initialisation was found automatically - cannot execute operation " + name, e);
+					}
+					final Transition initialisation = initialisationTransitions.iterator().next();
+					trace = trace.add(initialisation);
+					trace.getStateSpace().evaluateTransitions(Collections.singleton(initialisation), FormulaExpand.TRUNCATE);
+					sb.append("Machine was not initialised yet. Automatically initialised machine using arbitrary transition: ");
+					sb.append(initialisation.getPrettyRep());
+					sb.append('\n');
+				}
+			}
+			
+			op = singleTransitionFromPredicate(trace.getCurrentState(), translatedOpName, modifiedPredicate);
+		}
 		
 		this.animationSelector.changeCurrentAnimation(trace.add(op));
 		trace.getStateSpace().evaluateTransitions(Collections.singleton(op), FormulaExpand.TRUNCATE);
-		return new DisplayData(String.format("Executed operation: %s", op.getPrettyRep()));
+		sb.append("Executed operation: ");
+		sb.append(op.getPrettyRep());
+		return new DisplayData(sb.toString());
 	}
 	
 	@Override