public ExecutionStatus doExecutionLoop()

in jbatch/src/main/java/org/apache/batchee/container/impl/controller/ExecutionTransitioner.java [87:170]


    public ExecutionStatus doExecutionLoop() {
        try {
            currentExecutionElement = modelNavigator.getFirstExecutionElement(jobExecution.getRestartOn());
        } catch (final IllegalTransitionException e) {
            throw new IllegalArgumentException("Could not transition to first execution element within job.", e);
        }

        while (true) {

            if (jobContext.getBatchStatus().equals(BatchStatus.STOPPING)) {
                return new ExecutionStatus(ExtendedBatchStatus.JOB_OPERATOR_STOPPING);
            }

            final ExecutionElementController currentElementController = getNextElementController();
            currentStoppableElementController = currentElementController;

            if (BaseStepController.class.isInstance(currentElementController)) {
                BaseStepController.class.cast(currentElementController).setParentStepContext(parentStepContext);
            }
            final ExecutionStatus status = currentElementController.execute();

            // Nothing special for decision or step except to get exit status.  For flow and split we want to bubble up though.
            if ((currentExecutionElement instanceof Split) || (currentExecutionElement instanceof Flow)) {
                // Exit status and restartOn should both be in the job context.
                if (!status.getExtendedBatchStatus().equals(ExtendedBatchStatus.NORMAL_COMPLETION)) {
                    return status;
                }
            }

            // Seems like this should only happen if an Error is thrown at the step level, since normally a step-level
            // exception is caught and the fact that it was thrown capture in the ExecutionStatus
            if (jobContext.getBatchStatus().equals(BatchStatus.FAILED)) {
                throw new BatchContainerRuntimeException("Sub-execution returned its own BatchStatus of FAILED.  Deal with this by throwing exception to the next layer.");
            }

            // set the execution element controller to null so we don't try to call stop on it after the element has finished executing
            currentStoppableElementController = null;

            if (jobContext.getBatchStatus().equals(BatchStatus.STOPPING)) {
                return new ExecutionStatus(ExtendedBatchStatus.JOB_OPERATOR_STOPPING);
            }

            Transition nextTransition;
            try {
                nextTransition = modelNavigator.getNextTransition(currentExecutionElement, status);
            } catch (final IllegalTransitionException e) {
                throw new BatchContainerRuntimeException("Problem transitioning to next execution element.", e);
            }

            //
            // We will find ourselves in one of four states now.
            //
            // 1. Finished transitioning after a normal execution, but nothing to do 'next'.
            // 2. We just executed a step which through an exception, but didn't match a transition element.
            // 3. We are going to 'next' to another execution element (and jump back to the top of this '
            //    'while'-loop.
            // 4. We matched a terminating transition element (<end>, <stop> or <fail).
            //

            // 1.
            if (nextTransition.isFinishedTransitioning()) {
                this.stepExecIds = currentElementController.getLastRunStepExecutions();
                // Consider just passing the last 'status' back, but let's unwrap the exit status and pass a new NORMAL_COMPLETION
                // status back instead.
                return new ExecutionStatus(ExtendedBatchStatus.NORMAL_COMPLETION, status.getExitStatus());
                // 2.
            } else if (nextTransition.noTransitionElementMatchedAfterException()) {
                return new ExecutionStatus(ExtendedBatchStatus.EXCEPTION_THROWN, status.getExitStatus());
                // 3.
            } else if (nextTransition.getNextExecutionElement() != null) {
                // hold on to the previous execution element for the decider
                // we need it because we need to inject the context of the
                // previous execution element into the decider
                previousExecutionElement = currentExecutionElement;
                previousElementController = currentElementController;
                currentExecutionElement = nextTransition.getNextExecutionElement();
                // 4.
            } else if (nextTransition.getTransitionElement() != null) {
                return handleTerminatingTransitionElement(nextTransition.getTransitionElement());
            } else {
                throw new IllegalStateException("Not sure how we'd end up in this state...aborting rather than looping.");
            }
        }
    }