List<Flow> activeFlows = FlowHandlerImpl.getActiveFlows(facesContext, flowHandler);
// JSF 2.2 section 7.4.2: "... When outside of a flow, view identifier
// has the additional possibility of being a flow id.
Flow targetFlow = calculateTargetFlow(facesContext, outcome, flowHandler, activeFlows, toFlowDocumentId);
Flow currentFlow = navigationContext.getCurrentFlow(facesContext);
FlowCallNode targetFlowCallNode = null;
boolean startFlow = false;
String startFlowDocumentId = null;
String startFlowId = null;
boolean checkFlowNode = false;
String outcomeToGo = outcome;
String actionToGo = fromAction;
if (currentFlow != null)
{
// JSF 2.2 section 7.4.2: When inside a flow, a view identifier has
// the additional possibility of being the id of any node within the
// current flow or the id of another flow
if (targetFlow != null)
{
startFlow = true;
}
else
{
// Check if thie
checkFlowNode = true;
}
}
else
{
if (targetFlow != null)
{
// start flow!
startFlow = true;
}
}
if (!startFlow)
{
for (Flow activeFlow : activeFlows)
{
FlowNode node = activeFlow.getNode(outcome);
if (node != null)
{
currentFlow = activeFlow;
break;
}
_FlowNavigationStructure flowNavigationStructure = _flowNavigationStructureMap.get(
activeFlow.getId());
navigationCase = getNavigationCaseFromFlowStructure(facesContext,
flowNavigationStructure, fromAction, outcome, viewId);
if (navigationCase != null)
{
currentFlow = activeFlow;
break;
}
}
}
// If is necessary to enter a flow or there is a current
// flow and it is necessary to check a flow node
if (startFlow || (checkFlowNode && currentFlow != null))
{
boolean complete = false;
boolean checkNavCase = true;
while (!complete && (startFlow || checkFlowNode))
{
if (startFlow)
{
if (flowHandler.isActive(facesContext, targetFlow.getDefiningDocumentId(), targetFlow.getId()))
{
// Add the transition to exit from the flow
Flow baseReturnFlow = navigationContext.getCurrentFlow(facesContext);
Flow sourceFlow = baseReturnFlow;
// This is the part when the pseudo "recursive call" is done.
while (baseReturnFlow != null && !(baseReturnFlow.getDefiningDocumentId().equals(
targetFlow.getDefiningDocumentId()) &&
baseReturnFlow.getId().equals(targetFlow.getId())) )
{
navigationContext.popFlow(facesContext);
baseReturnFlow = navigationContext.getCurrentFlow(facesContext);
}
navigationContext.popFlow(facesContext);
currentFlow = navigationContext.getCurrentFlow(facesContext);
navigationContext.addTargetFlow(baseReturnFlow, currentFlow, null);
}
if (startFlowId == null)
{
startFlowDocumentId = targetFlow.getDefiningDocumentId();
startFlowId = targetFlowCallNode == null ? targetFlow.getId() : targetFlowCallNode.getId();
}
navigationContext.addTargetFlow(currentFlow, targetFlow, targetFlowCallNode);
targetFlowCallNode = null;
// Since we start a new flow, the current flow is now the
// target flow.
navigationContext.pushFlow(facesContext, targetFlow);
currentFlow = targetFlow;
//No outboundCallNode.
//Resolve start node.
outcomeToGo = resolveStartNodeOutcome(targetFlow);
checkFlowNode = true;
startFlow = false;
}
if (checkFlowNode)
{
FlowNode flowNode = currentFlow.getNode(outcomeToGo);
if (flowNode != null)
{
checkNavCase = true;
if (!complete && flowNode instanceof SwitchNode)
{
outcomeToGo = calculateSwitchOutcome(facesContext, (SwitchNode) flowNode);
// Start over again checking if the node exists.
//fromAction = currentFlow.getId();
actionToGo = currentFlow.getId();
flowNode = currentFlow.getNode(outcomeToGo);
continue;
}
if (!complete && flowNode instanceof FlowCallNode)
{
// "... If the node is a FlowCallNode, save it aside as facesFlowCallNode. ..."
FlowCallNode flowCallNode = (FlowCallNode) flowNode;
targetFlow = calculateFlowCallTargetFlow(facesContext,
flowHandler, flowCallNode, currentFlow);
if (targetFlow != null)
{
targetFlowCallNode = flowCallNode;