public boolean checkForWorkflowCompletion(final WorkflowModel workflow)
            throws TerminateWorkflowException {

        Map<String, TaskModel.Status> taskStatusMap = new HashMap<>();
        List<TaskModel> nonExecutedTasks = new ArrayList<>();
        for (TaskModel task : workflow.getTasks()) {
            taskStatusMap.put(task.getReferenceTaskName(), task.getStatus());
            if (!task.getStatus().isTerminal()) {
                return false;
            }

            // If there is a TERMINATE task that has been executed successfuly then the workflow
            // should be marked as completed.
            if (TERMINATE.name().equals(task.getTaskType())
                    && task.getStatus().isTerminal()
                    && task.getStatus().isSuccessful()) {
                return true;
            }
            if (!task.isRetried() || !task.isExecuted()) {
                nonExecutedTasks.add(task);
            }
        }

        // If there are no tasks executed, then we are not done yet
        if (taskStatusMap.isEmpty()) {
            return false;
        }

        List<WorkflowTask> workflowTasks = workflow.getWorkflowDefinition().getTasks();

        for (WorkflowTask wftask : workflowTasks) {
            TaskModel.Status status = taskStatusMap.get(wftask.getTaskReferenceName());
            if (status == null || !status.isTerminal()) {
                return false;
            }
            // if we reach here, the task has been completed.
            // Was the task successful in completion?
            if (!status.isSuccessful()) {
                return false;
            }
        }

        boolean noPendingSchedule =
                nonExecutedTasks.stream()
                        .parallel()
                        .noneMatch(
                                wftask -> {
                                    String next = getNextTasksToBeScheduled(workflow, wftask);
                                    return next != null && !taskStatusMap.containsKey(next);
                                });

        return noPendingSchedule;
    }
Updates the workflow output.

@param workflow the workflow instance
@param task if not null, the output of this task will be copied to workflow output if no
    output parameters are specified in the workflow definition if null, the output of the
    last task in the workflow will be copied to workflow output of no output parameters are
    specified in the workflow definition
core/src/main/java/com/netflix/conductor/core/execution/DeciderService.java