public function run($args = [], $saveLog = false)
    {
        /**
         * The state machine must be able to re run the same processes again.
         */
        $this->reset();

        // just store the arguments for external logic
        $this->args = $args;

        $continueExecution = true;
        $nextState         = $this->currentStatus;

        /**
         * Based on the initial state, the algorithm
         * will try to execute each method until the
         * final state is reached
         */
        while (true === $continueExecution) {

            if ($nextState->getType() == StatusInterface::TYPE_FINAL) {
                $continueExecution = false;
            }

            /*
             * Every workflow class has methods, which names are equal to the state names in the
             * configuration file. By executing the methods, a return value can be given. This
             * depends on your graph logic.
             *
             * However the return value will be seen as a condition for the NEXT state
             * transition evaluation.
             */
            try {
                $this->executeMethod('preDispatch');
                $condition = $this->executeMethod($nextState->getName());
                $this->executeMethod('postDispatch');

            } catch (\Exception $e) {
                if (method_exists($this, 'exception')) {
                    call_user_func([$this, 'exception'], [$e]);
                    $nextState = $this->getNextStateFrom('exception');
                    $this->setState($nextState);
                    continue;
                } else {
                    throw $e;
                }
            }

            if (true === $saveLog) {
                $this->addToLog($nextState->getName(), $condition);
            }

            /**
             * Mark the execution to be stopped when the next state
             * is StatusInterface::TYPE_FINAL.
             */
            if (false === $continueExecution) {
                continue;
            }

            $nextState = $this->getNextStateFrom($nextState->getName(), $condition);

            /**
             * Overwrite the current state. This does not affect
             * the application logic but will be used for debugging purpose to be able
             * to inspect the current state machine
             */
            $this->setState($nextState);

        }

        if (true === $saveLog) {
            return $this->log;
        }
    }