You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2013/09/09 01:52:33 UTC
svn commit: r1520941 - in /myfaces/core/trunk/impl/src:
main/java/org/apache/myfaces/application/ main/java/org/apache/myfaces/flow/
test/java/org/apache/myfaces/application/flow/ test/resources/
test/resources/org/apache/myfaces/application/flow/ test...
Author: lu4242
Date: Sun Sep 8 23:52:33 2013
New Revision: 1520941
URL: http://svn.apache.org/r1520941
Log:
MYFACES-3691 Implement Faces Flows (consider enter/exit from multiple flows and make the different when a flow is open "globally" or it is open using a call node).
Added:
myfaces/core/trunk/impl/src/test/resources/begin.xhtml
- copied, changed from r1518877, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/ (with props)
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/content.xhtml (with props)
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/flow4.xhtml (with props)
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml
- copied, changed from r1509781, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1_end.xhtml
Modified:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/_FlowContextualInfo.java
myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow2/begin.xhtml
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java?rev=1520941&r1=1520940&r2=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java Sun Sep 8 23:52:33 2013
@@ -308,14 +308,14 @@ public class NavigationHandlerImpl
if (navigationContext != null)
{
// Is any flow transition on the way?
- if (navigationContext.getSourceFlow() != null ||
+ if (navigationContext.getSourceFlows() != null ||
(navigationContext.getTargetFlows() != null &&
!navigationContext.getTargetFlows().isEmpty()))
{
FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
- Flow sourceFlow = navigationContext.getSourceFlow();
for (int i = 0; i < navigationContext.getTargetFlows().size(); i++)
{
+ Flow sourceFlow = navigationContext.getSourceFlows().get(i);
Flow targetFlow = navigationContext.getTargetFlows().get(i);
flowHandler.transition(facesContext, sourceFlow, targetFlow,
@@ -524,10 +524,7 @@ public class NavigationHandlerImpl
{
// Add the transition to exit from the flow
Flow baseReturnFlow = navigationContext.getCurrentFlow(facesContext);
- if (navigationContext.getSourceFlow() == null)
- {
- navigationContext.setSourceFlow(baseReturnFlow);
- }
+ Flow sourceFlow = baseReturnFlow;
// This is the part when the pseudo "recursive call" is done.
while (baseReturnFlow != null && !(baseReturnFlow.getDefiningDocumentId().equals(
targetFlow.getDefiningDocumentId()) &&
@@ -535,19 +532,17 @@ public class NavigationHandlerImpl
{
navigationContext.popFlow(facesContext);
baseReturnFlow = navigationContext.getCurrentFlow(facesContext);
- navigationContext.addTargetFlow(baseReturnFlow, null);
}
navigationContext.popFlow(facesContext);
currentFlow = navigationContext.getCurrentFlow(facesContext);
- navigationContext.addTargetFlow(currentFlow, null);
+ navigationContext.addTargetFlow(baseReturnFlow, currentFlow, null);
}
if (startFlowId == null)
{
startFlowDocumentId = targetFlow.getDefiningDocumentId();
startFlowId = targetFlowCallNode == null ? targetFlow.getId() : targetFlowCallNode.getId();
}
- navigationContext.setSourceFlow(currentFlow);
- navigationContext.addTargetFlow(targetFlow, targetFlowCallNode);
+ navigationContext.addTargetFlow(currentFlow, targetFlow, targetFlowCallNode);
targetFlowCallNode = null;
// Since we start a new flow, the current flow is now the
// target flow.
@@ -613,13 +608,9 @@ public class NavigationHandlerImpl
{
ReturnNode returnNode = (ReturnNode) flowNode;
String fromOutcome = returnNode.getFromOutcome(facesContext);
-
actionToGo = currentFlow.getId();
+ Flow sourceFlow = currentFlow;
Flow baseReturnFlow = navigationContext.getCurrentFlow(facesContext);
- if (navigationContext.getSourceFlow() == null)
- {
- navigationContext.setSourceFlow(baseReturnFlow);
- }
// This is the part when the pseudo "recursive call" is done.
while (baseReturnFlow != null && !(baseReturnFlow.getDefiningDocumentId().equals(
currentFlow.getDefiningDocumentId()) &&
@@ -627,11 +618,10 @@ public class NavigationHandlerImpl
{
navigationContext.popFlow(facesContext);
baseReturnFlow = navigationContext.getCurrentFlow(facesContext);
- navigationContext.addTargetFlow(baseReturnFlow, null);
}
navigationContext.popFlow(facesContext);
currentFlow = navigationContext.getCurrentFlow(facesContext);
- navigationContext.addTargetFlow(currentFlow, null);
+ navigationContext.addTargetFlow(sourceFlow, currentFlow, null);
outcomeToGo = fromOutcome;
String lastDisplayedViewId = navigationContext.getLastDisplayedViewId(facesContext,
currentFlow);
@@ -664,7 +654,6 @@ public class NavigationHandlerImpl
complete = true;
}
continue;
- //complete = true;
}
if (!complete && flowNode instanceof ViewNode)
{
@@ -1503,7 +1492,7 @@ public class NavigationHandlerImpl
protected static class NavigationContext
{
private NavigationCase navigationCase;
- private Flow sourceFlow;
+ private List<Flow> sourceFlows;
private List<Flow> targetFlows;
private List<FlowCallNode> targetFlowCallNodes;
private List<Flow> currentFlows;
@@ -1528,14 +1517,9 @@ public class NavigationHandlerImpl
this.navigationCase = navigationCase;
}
- public Flow getSourceFlow()
- {
- return sourceFlow;
- }
-
- public void setSourceFlow(Flow sourceFlow)
+ public List<Flow> getSourceFlows()
{
- this.sourceFlow = sourceFlow;
+ return sourceFlows;
}
public List<Flow> getTargetFlows()
@@ -1548,13 +1532,15 @@ public class NavigationHandlerImpl
return targetFlowCallNodes;
}
- public void addTargetFlow(Flow targetFlow, FlowCallNode flowCallNode)
+ public void addTargetFlow(Flow sourceFlow, Flow targetFlow, FlowCallNode flowCallNode)
{
if (targetFlows == null)
{
+ sourceFlows = new ArrayList<Flow>(4);
targetFlows = new ArrayList<Flow>(4);
targetFlowCallNodes = new ArrayList<FlowCallNode>(4);
}
+ this.sourceFlows.add(sourceFlow);
this.targetFlows.add(targetFlow);
this.targetFlowCallNodes.add(flowCallNode);
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java?rev=1520941&r1=1520940&r2=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java Sun Sep 8 23:52:33 2013
@@ -191,14 +191,15 @@ public class FlowHandlerImpl extends Flo
return;
}
- // TODO: Implement me! In theory here lies the push/pop logic, but to know how it works, it is necessary
- // to add the code inside NavigationHandlerImpl first. For now, the logic only allows 1 flow at the time
- // but this should work with multiple nested flows.
if (sourceFlow == null && targetFlow == null)
{
return;
}
+ // Calculate the parentFlowReference, since it will be used later.
+ FlowReference parentFlowReference = (outboundCallNode != null && sourceFlow != null) ?
+ new FlowReference(sourceFlow.getDefiningDocumentId(), sourceFlow.getId()) : null;
+
if (sourceFlow == null)
{
// Entering a flow
@@ -206,24 +207,19 @@ public class FlowHandlerImpl extends Flo
targetFlow, !outboundCallNodeProcessed ? outboundCallNode : null);
outboundCallNodeProcessed = true;
pushFlowReference(context, clientWindow,
- new FlowReference(targetFlow.getDefiningDocumentId(), targetFlow.getId()), toViewId);
+ new FlowReference(targetFlow.getDefiningDocumentId(), targetFlow.getId()),
+ toViewId, parentFlowReference);
doAfterEnterFlow(context, targetFlow, outboundParameters);
}
else if (targetFlow == null)
{
- // Getting out of the flow, since targetFlow is null, just clear the stack
+ // Getting out of the flow, since targetFlow is null,
+ // we need to take sourceFlow and take it out and all the chain
List<_FlowContextualInfo> currentFlowStack = getCurrentFlowStack(context, clientWindow);
if (currentFlowStack != null)
{
- //currentFlowStack.clear();
- for (int i = currentFlowStack.size()-1; i >= 0; i--)
- {
- _FlowContextualInfo fci = currentFlowStack.get(i);
- FlowReference fr = fci.getFlowReference();
- doBeforeExitFlow(context, getFlow(context, fr.getDocumentId(), fr.getId()));
- popFlowReference(context, clientWindow, currentFlowStack, i);
- }
- }
+ removeFlowFromStack(context, currentFlowStack, sourceFlow);
+ }
}
else
{
@@ -246,61 +242,103 @@ public class FlowHandlerImpl extends Flo
}
if (targetFlowIndex >= 0)
{
- for (int i = currentFlowStack.size()-1; i > targetFlowIndex; i--)
- {
- _FlowContextualInfo fci = currentFlowStack.get(i);
- FlowReference fr = fci.getFlowReference();
- doBeforeExitFlow(context, getFlow(context, fr.getDocumentId(), fr.getId()));
- popFlowReference(context, clientWindow, currentFlowStack, i);
- }
+ // targetFlow is on the stack, so it is a return.
+ removeFlowFromStack(context, currentFlowStack, sourceFlow);
}
else
{
- // sourceFlow should match.
- FlowReference sourceFlowReference = new FlowReference(
- sourceFlow.getDefiningDocumentId(), sourceFlow.getId());
- if ( sourceFlowReference.equals(
- currentFlowStack.get(currentFlowStack.size()-1).getFlowReference()) )
- {
- Map<String, Object> outboundParameters = doBeforeEnterFlow(context,
- targetFlow, !outboundCallNodeProcessed ? outboundCallNode : null);
- outboundCallNodeProcessed = true;
- pushFlowReference(context, clientWindow,
- new FlowReference(targetFlow.getDefiningDocumentId(), targetFlow.getId()), toViewId);
- doAfterEnterFlow(context, targetFlow, outboundParameters);
- }
- else
- {
- // Chain gets broken. Clear stack and start again.
- for (int i = currentFlowStack.size()-1; i >= 0; i--)
- {
- _FlowContextualInfo fci = currentFlowStack.get(i);
- FlowReference fr = fci.getFlowReference();
- doBeforeExitFlow(context, getFlow(context, fr.getDocumentId(), fr.getId()));
- popFlowReference(context, clientWindow, currentFlowStack, i);
- }
-
- Map<String, Object> outboundParameters = doBeforeEnterFlow(context,
- targetFlow, !outboundCallNodeProcessed ? outboundCallNode : null);
- outboundCallNodeProcessed = true;
- pushFlowReference(context, clientWindow,
- new FlowReference(targetFlow.getDefiningDocumentId(), targetFlow.getId()), toViewId);
- doAfterEnterFlow(context, targetFlow, outboundParameters);
- }
+ // targetFlow is not on the stack, so it is flow call.
+ Map<String, Object> outboundParameters = doBeforeEnterFlow(context,
+ targetFlow, !outboundCallNodeProcessed ? outboundCallNode : null);
+ outboundCallNodeProcessed = true;
+ pushFlowReference(context, clientWindow,
+ new FlowReference(targetFlow.getDefiningDocumentId(), targetFlow.getId()), toViewId,
+ parentFlowReference);
+ doAfterEnterFlow(context, targetFlow, outboundParameters);
}
}
else
{
+ // sourceFlow and targetFlow are not null, but there is no currentFlowStack. It that
+ // case just enter into targetFlow
Map<String, Object> outboundParameters = doBeforeEnterFlow(context,
targetFlow, !outboundCallNodeProcessed ? outboundCallNode : null);
outboundCallNodeProcessed = true;
pushFlowReference(context, clientWindow,
- new FlowReference(targetFlow.getDefiningDocumentId(), targetFlow.getId()), toViewId);
+ new FlowReference(targetFlow.getDefiningDocumentId(), targetFlow.getId()), toViewId,
+ parentFlowReference);
doAfterEnterFlow(context, targetFlow, outboundParameters);
}
}
}
+ private void removeFlowFromStack(FacesContext context, List<_FlowContextualInfo> currentFlowStack, Flow sourceFlow)
+ {
+ // Steps to remove a flow:
+ // 1. locate where is the flow in the chain
+ int sourceFlowIndex = -1;
+ FlowReference sourceFlowReference = new FlowReference(sourceFlow.getDefiningDocumentId(),
+ sourceFlow.getId());
+ List<_FlowContextualInfo> flowsToRemove = new ArrayList<_FlowContextualInfo>();
+ for (int i = currentFlowStack.size()-1; i >= 0; i--)
+ {
+ _FlowContextualInfo fci = currentFlowStack.get(i);
+ if (fci.getFlowReference().equals(sourceFlowReference))
+ {
+ sourceFlowIndex = i;
+ flowsToRemove.add(fci);
+ break;
+ }
+ }
+
+ if (sourceFlowIndex != -1)
+ {
+ // From sourceFlowIndex, add all flows
+ traverseDependantFlows(sourceFlowReference, sourceFlowIndex+1, currentFlowStack, flowsToRemove);
+
+ // Remove all marked elements
+ if (!flowsToRemove.isEmpty())
+ {
+ for (int i = flowsToRemove.size()-1; i >= 0; i--)
+ {
+ _FlowContextualInfo fci = flowsToRemove.get(i);
+ FlowReference fr = fci.getFlowReference();
+ doBeforeExitFlow(context, getFlow(context, fr.getDocumentId(), fr.getId()));
+ //popFlowReference(context, clientWindow, currentFlowStack, i);
+ currentFlowStack.remove(fci);
+ }
+ }
+
+ if (currentFlowStack.isEmpty())
+ {
+ // Remove it from session but keep it in request scope.
+ context.getAttributes().put(ROOT_LAST_VIEW_ID,
+ context.getExternalContext().getSessionMap().remove(ROOT_LAST_VIEW_ID +
+ context.getExternalContext().getClientWindow().getId()));
+ }
+ }
+ }
+
+ private void traverseDependantFlows(FlowReference sourceFlowReference,
+ int index, List<_FlowContextualInfo> currentFlowStack, List<_FlowContextualInfo> flowsToRemove)
+ {
+ if (index < currentFlowStack.size())
+ {
+ for (int i = index; i < currentFlowStack.size(); i++)
+ {
+ _FlowContextualInfo info = currentFlowStack.get(i);
+ if (sourceFlowReference.equals(info.getSourceFlowReference()))
+ {
+ if (!flowsToRemove.contains(info))
+ {
+ flowsToRemove.add(info);
+ traverseDependantFlows(info.getFlowReference(), i+1, currentFlowStack, flowsToRemove);
+ }
+ }
+ }
+ }
+ }
+
private Map<String, Object> doBeforeEnterFlow(FacesContext context, Flow flow, FlowCallNode outboundCallNode)
{
Map<String, Object> outboundParameters = null;
@@ -466,8 +504,10 @@ public class FlowHandlerImpl extends Flo
// where the flow should return, because that information was not passed
// in the parameters of the link.
String toFlowDocumentId = FlowHandler.NULL_FLOW;
- String targetFlowId = null;
String fromOutcome = flowIdRequestParam;
+ //Flow sourceFlow = null;
+ List<Flow> sourceFlows = null;
+ List<Flow> targetFlows = null;
boolean failed = false;
int i = 0;
@@ -483,7 +523,13 @@ public class FlowHandlerImpl extends Flo
FlowNode node = currentFlow.getNode(fromOutcome);
if (node instanceof ReturnNode)
{
+ if (targetFlows == null)
+ {
+ sourceFlows = new ArrayList<Flow>(4);
+ targetFlows = new ArrayList<Flow>(4);
+ }
// Get the navigation case using the outcome
+ Flow sourceFlow = currentFlow;
flowHandler.pushReturnMode(context);
currentFlow = flowHandler.getCurrentFlow(context);
i++;
@@ -495,15 +541,17 @@ public class FlowHandlerImpl extends Flo
{
if (currentLastDisplayedViewId != null)
{
+ sourceFlows.add(sourceFlow);
if (currentFlow != null)
{
toFlowDocumentId = currentFlow.getDefiningDocumentId();
- targetFlowId = currentFlow.getId();
+ targetFlows.add(currentFlow);
}
else
{
// No active flow
toFlowDocumentId = null;
+ targetFlows.add(null);
}
}
else
@@ -521,23 +569,33 @@ public class FlowHandlerImpl extends Flo
}
else
{
+ sourceFlows.add(sourceFlow);
// The absence of FlowHandler.NULL_FLOW means the return went somewhere else.
if (currentFlow != null)
{
toFlowDocumentId = currentFlow.getDefiningDocumentId();
- targetFlowId = currentFlow.getId();
+ targetFlows.add(currentFlow);
}
else
{
// No active flow
toFlowDocumentId = null;
+ targetFlows.add(null);
}
}
}
}
else
{
- failed = true;
+ // No return node found in current flow, push it and check
+ // the next flow
+ flowHandler.pushReturnMode(context);
+ currentFlow = flowHandler.getCurrentFlow(context);
+ i++;
+ if (currentFlow == null)
+ {
+ failed = true;
+ }
}
}
for (int j = 0; j<i; j++)
@@ -550,12 +608,16 @@ public class FlowHandlerImpl extends Flo
}
else
{
- Flow targetFlow = targetFlowId == null ? null :
- getFlow(context, toFlowDocumentId, targetFlowId);
//Call transitions.
- flowHandler.transition(context,
- flowHandler.getCurrentFlow(context),
- targetFlow, null, context.getViewRoot().getViewId());
+ for (int j = 0; j < targetFlows.size(); j++)
+ {
+ Flow sourceFlow = sourceFlows.get(j);
+ Flow targetFlow = targetFlows.get(j);
+ flowHandler.transition(context,
+ sourceFlow,
+ targetFlow, null, context.getViewRoot().getViewId());
+
+ }
}
}
else
@@ -740,7 +802,7 @@ public class FlowHandlerImpl extends Flo
}
private void pushFlowReference(FacesContext context, ClientWindow clientWindow, FlowReference flowReference,
- String toViewId)
+ String toViewId, FlowReference sourceFlowReference)
{
Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
String currentFlowMapKey = CURRENT_FLOW_STACK + clientWindow.getId();
@@ -760,7 +822,7 @@ public class FlowHandlerImpl extends Flo
context.getExternalContext().getSessionMap().put(ROOT_LAST_VIEW_ID + clientWindow.getId(),
context.getViewRoot().getViewId());
}
- currentFlowStack.add(new _FlowContextualInfo(flowReference, toViewId));
+ currentFlowStack.add(new _FlowContextualInfo(flowReference, toViewId, sourceFlowReference));
}
private void popFlowReference(FacesContext context, ClientWindow clientWindow,
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/_FlowContextualInfo.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/_FlowContextualInfo.java?rev=1520941&r1=1520940&r2=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/_FlowContextualInfo.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/_FlowContextualInfo.java Sun Sep 8 23:52:33 2013
@@ -30,15 +30,18 @@ class _FlowContextualInfo implements Ser
private FlowReference flowReference;
private String lastDisplayedViewId;
+ private FlowReference sourceFlowReference;
public _FlowContextualInfo()
{
}
- public _FlowContextualInfo(FlowReference flowReference, String lastDisplayedViewId)
+ public _FlowContextualInfo(FlowReference flowReference, String lastDisplayedViewId,
+ FlowReference souFlowReference)
{
this.flowReference = flowReference;
this.lastDisplayedViewId = lastDisplayedViewId;
+ this.sourceFlowReference = souFlowReference;
}
@Override
@@ -107,4 +110,20 @@ class _FlowContextualInfo implements Ser
{
this.lastDisplayedViewId = lastDisplayedViewId;
}
+
+ /**
+ * @return the sourceFlowReference
+ */
+ public FlowReference getSourceFlowReference()
+ {
+ return sourceFlowReference;
+ }
+
+ /**
+ * @param sourceFlowReference the sourceFlowReference to set
+ */
+ public void setSourceFlowReference(FlowReference sourceFlowReference)
+ {
+ this.sourceFlowReference = sourceFlowReference;
+ }
}
Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java?rev=1520941&r1=1520940&r2=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java Sun Sep 8 23:52:33 2013
@@ -480,4 +480,949 @@ public class FlowMyFacesRequestTestCase
{
return new org.apache.el.ExpressionFactoryImpl();
}
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 1
+ * - Start flow 2
+ * - End flow 1
+ * - End flow 2
+ *
+ * Since flow2 was called using the flow name, end flow 1 doesn't end flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_6() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ NavigationCase navCase = handler.getNavigationCase(facesContext, null, "flow1");
+
+ Assert.assertNotNull(navCase);
+
+ // Check begin view node
+ Assert.assertEquals("/flow1/begin.xhtml", navCase.getToViewId(facesContext));
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow1");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow1");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow2");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow4);
+
+ processRender();
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 1
+ * - Start flow 2 (using call node)
+ * - End flow 1
+ *
+ * Since flow2 was called using a call node, end flow 1 also end flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_7() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ NavigationCase navCase = handler.getNavigationCase(facesContext, null, "flow1");
+
+ Assert.assertNotNull(navCase);
+
+ // Check begin view node
+ Assert.assertEquals("/flow1/begin.xhtml", navCase.getToViewId(facesContext));
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow1");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow1");
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow3);
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 3 (start flow 1)
+ * - Start flow 2
+ * - End flow 1
+ * - End flow 2
+ *
+ * Since flow2 was called using the flow name, end flow 1 doesn't end flow 2
+ * At the end flow 3 should still be active
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_8() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow3");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow1");
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow3");
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 2
+ * - Start flow 3 (start flow 1)
+ * - Return flow 1 and 3
+ * - End flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_9() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow2");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow3");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow1");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1_3");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow2");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow4);
+
+ processRender();
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 2
+ * - Start flow 3 (start flow 1)
+ * - Return flow 1 and 3 (GET)
+ * - End flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_9_1() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow2");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow3");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow1");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ //UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1_3");
+ //submit(button5);
+
+ NavigationCase endCase = handler.getNavigationCase(facesContext, null, "back_flow_1_3");
+ Assert.assertNotNull(endCase);
+
+ String toViewId = endCase.getToViewId(facesContext);
+ // Check if the dynamic outcome return hack has been correctly resolved.
+ Assert.assertEquals(toViewId, "/flow_base.xhtml");
+ String fromOutcome = endCase.getFromOutcome();
+ String clientWindowId = facesContext.getExternalContext().getClientWindow().getId();
+
+ tearDownRequest();
+ setupRequest(toViewId);
+ request.addParameter(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, FlowHandler.NULL_FLOW);
+ request.addParameter(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, fromOutcome);
+ request.addParameter(ResponseStateManager.CLIENT_WINDOW_URL_PARAM, clientWindowId);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow2");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow4);
+
+ processRender();
+ }
+
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 3 (start flow 1)
+ * - Start flow 2
+ * - End flow 2
+ * - Return flow 1 and 3
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_10() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow3");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow1");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow1");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1_3");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow4);
+
+ processRender();
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 3 (start flow 1)
+ * - Start flow 2
+ * - Return flow 1 and 3
+ * - End flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_10_1() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow3");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow1");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1_3");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow2");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow4);
+
+ processRender();
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 3 (start flow 1)
+ * - Start flow 2
+ * - Return flow 1 and 3 (GET)
+ * - End flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_10_2() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow3");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow1");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ //UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1_3");
+ //submit(button5);
+ NavigationCase endCase = handler.getNavigationCase(facesContext, null, "back_flow_1_3");
+ Assert.assertNotNull(endCase);
+
+ String toViewId = endCase.getToViewId(facesContext);
+ // Check if the dynamic outcome return hack has been correctly resolved.
+ Assert.assertEquals(toViewId, "/flow_base.xhtml");
+ String fromOutcome = endCase.getFromOutcome();
+ String clientWindowId = facesContext.getExternalContext().getClientWindow().getId();
+
+ tearDownRequest();
+ setupRequest(toViewId);
+ request.addParameter(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, FlowHandler.NULL_FLOW);
+ request.addParameter(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, fromOutcome);
+ request.addParameter(ResponseStateManager.CLIENT_WINDOW_URL_PARAM, clientWindowId);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow2");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow4);
+
+ processRender();
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 4
+ * - Start flow 2
+ * - Start flow 1 (use call node from flow 4)
+ * - Return flow 1 and 4
+ * - Return flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_11() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow4");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow4/flow4.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow4");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow1_4");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow1");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+
+ UICommand button7 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1_4");
+ submit(button7);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow4);
+ Assert.assertEquals(currentFlow4.getId(), "flow2");
+
+ processRender();
+
+ UICommand button8 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button8);
+
+ processLifecycleExecute();
+
+ Flow currentFlow5 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow5);
+
+ processRender();
+
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start flow 4
+ * - Start flow 2
+ * - Start flow 1 (use call node from flow 4)
+ * - Return flow 1 and 4 (GET)
+ * - Return flow 2
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFlow1_11_1() throws Exception
+ {
+ setupRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ processRender();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow4");
+ submit(button);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow4/flow4.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flow4");
+
+ processRender();
+
+ NavigationCase goFlowBase = handler.getNavigationCase(facesContext, null, "flow_base");
+ Assert.assertNotNull(goFlowBase);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow2");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ Flow currentFlow2 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow2);
+ Assert.assertEquals(currentFlow2.getId(), "flow2");
+
+ processRender();
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlow1_4");
+ submit(button5);
+
+ processLifecycleExecute();
+
+ Flow currentFlow3 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow3);
+ Assert.assertEquals(currentFlow3.getId(), "flow1");
+
+ processRender();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ submit(button6);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ processRender();
+
+ //UICommand button7 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow1_4");
+ //submit(button7);
+
+ NavigationCase endCase = handler.getNavigationCase(facesContext, null, "back_flow_1_4");
+ Assert.assertNotNull(endCase);
+
+ String toViewId = endCase.getToViewId(facesContext);
+ // Check if the dynamic outcome return hack has been correctly resolved.
+ Assert.assertEquals(toViewId, "/flow_base.xhtml");
+ String fromOutcome = endCase.getFromOutcome();
+ String clientWindowId = facesContext.getExternalContext().getClientWindow().getId();
+
+ tearDownRequest();
+ setupRequest(toViewId);
+ request.addParameter(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, FlowHandler.NULL_FLOW);
+ request.addParameter(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, fromOutcome);
+ request.addParameter(ResponseStateManager.CLIENT_WINDOW_URL_PARAM, clientWindowId);
+
+ processLifecycleExecute();
+
+ Assert.assertEquals("/flow_base.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow4 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow4);
+ Assert.assertEquals(currentFlow4.getId(), "flow2");
+
+ processRender();
+
+ UICommand button8 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:returnFlow2");
+ submit(button8);
+
+ processLifecycleExecute();
+
+ Flow currentFlow5 = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNull(currentFlow5);
+
+ processRender();
+
+ }
}
Copied: myfaces/core/trunk/impl/src/test/resources/begin.xhtml (from r1518877, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml)
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/begin.xhtml?p2=myfaces/core/trunk/impl/src/test/resources/begin.xhtml&p1=myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml&r1=1518877&r2=1520941&rev=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/begin.xhtml Sun Sep 8 23:52:33 2013
@@ -35,6 +35,7 @@
<h:commandButton id="call_flow2" value="Start Flow 2" action="call_flow2"/>
<h:commandButton id="end_flow" value="End" action="end"/>
<h:commandButton id="back_flow" value="Back" action="back"/>
+ <h:commandButton id="go_flow_base" value="Go to base" action="flow_base"/>
</h:form>
<!-- resolve outcome is quite useful to check how the flow target is resolved -->
<h:link outcome="end" value="End Outcome Link"/>
Modified: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml?rev=1520941&r1=1520940&r2=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml Sun Sep 8 23:52:33 2013
@@ -46,6 +46,16 @@
<from-outcome>back</from-outcome>
</flow-return>
+ <flow-return id="back_flow_1"/>
+
+ <flow-return id="back_flow_1_3">
+ <from-outcome>back_flow_3</from-outcome>
+ </flow-return>
+
+ <flow-return id="back_flow_1_4">
+ <from-outcome>back_flow_4</from-outcome>
+ </flow-return>
+
<!-- The idea is use a switch combo to get back, since
the from-outcome of the switch cannot receive
EL expressions -->
@@ -106,6 +116,8 @@
default-->
<flow-return id="back"/>
+ <flow-return id="back_flow_2"/>
+
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
@@ -151,12 +163,48 @@
<from-outcome>exit</from-outcome>
</flow-return>
+ <flow-return id="back_flow_3"/>
+
<view id="content">
<vdl-document>/flow3/content.xhtml</vdl-document>
</view>
</flow-definition>
+ <flow-definition id="flow4">
+
+ <flow-call id="call_flow1_4">
+ <flow-reference>
+ <flow-document-id>flow_def_1</flow-document-id>
+ <flow-id>flow1</flow-id>
+ </flow-reference>
+ <outbound-parameter>
+ <name>backOutcome</name>
+ <value>content</value>
+ </outbound-parameter>
+ </flow-call>
+
+ <navigation-rule>
+ <from-view-id>*</from-view-id>
+ <navigation-case>
+ <from-action>flow1</from-action>
+ <from-outcome>exit</from-outcome>
+ <to-view-id>content</to-view-id>
+ </navigation-case>
+ </navigation-rule>
+
+ <flow-return id="end">
+ <from-outcome>exit</from-outcome>
+ </flow-return>
+
+ <flow-return id="back_flow_4"/>
+
+ <view id="content">
+ <vdl-document>/flow4/content.xhtml</vdl-document>
+ </view>
+
+ </flow-definition>
+
<navigation-rule>
<from-view-id>*</from-view-id>
<!-- End Flow 1 -->
@@ -165,7 +213,10 @@
<from-outcome>exit</from-outcome>
<to-view-id>/flow1_end.xhtml</to-view-id>
</navigation-case>
-
+ <navigation-case>
+ <from-outcome>flow_base</from-outcome>
+ <to-view-id>/flow_base.xhtml</to-view-id>
+ </navigation-case>
</navigation-rule>
</faces-config>
Modified: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml?rev=1520941&r1=1520940&r2=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1/begin.xhtml Sun Sep 8 23:52:33 2013
@@ -35,6 +35,7 @@
<h:commandButton id="call_flow2" value="Start Flow 2" action="call_flow2"/>
<h:commandButton id="end_flow" value="End" action="end"/>
<h:commandButton id="back_flow" value="Back" action="back"/>
+ <h:commandButton id="go_flow_base" value="Go to base" action="flow_base"/>
</h:form>
<!-- resolve outcome is quite useful to check how the flow target is resolved -->
<h:link outcome="end" value="End Outcome Link"/>
Modified: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow2/begin.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow2/begin.xhtml?rev=1520941&r1=1520940&r2=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow2/begin.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow2/begin.xhtml Sun Sep 8 23:52:33 2013
@@ -33,6 +33,7 @@
<h:commandButton id="content" value="Content" action="content"/>
<h:commandButton id="end_flow" value="End" action="end"/>
<h:commandButton id="back_flow" value="Back" action="back"/>
+ <h:commandButton id="go_flow_base" value="Go to base" action="flow_base"/>
</h:form>
<!-- resolve outcome is quite useful to check how the flow target is resolved -->
<h:link outcome="end" value="End Outcome Link"/>
Propchange: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/
------------------------------------------------------------------------------
bugtraq:number = true
Added: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/content.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/content.xhtml?rev=1520941&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/content.xhtml (added)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/content.xhtml Sun Sep 8 23:52:33 2013
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:c="http://java.sun.com/jsp/jstl/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ >
+<body>
+<ui:composition>
+ <h1>Myfaces Flow Examples</h1>
+ <h2>begin.xhtml</h2>
+ <h:form id="mainForm">
+ <h:commandButton value="End" action="end"/>
+ </h:form>
+ <!-- resolve outcome is quite useful to check how the flow target is resolved -->
+ <h:link outcome="end" value="End Outcome Link"/>
+</ui:composition>
+</body>
+</html>
Propchange: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/content.xhtml
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/flow4.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/flow4.xhtml?rev=1520941&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/flow4.xhtml (added)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/flow4.xhtml Sun Sep 8 23:52:33 2013
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:c="http://java.sun.com/jsp/jstl/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ >
+<body>
+<ui:composition>
+ <h1>Myfaces Flow Examples</h1>
+ <h2>begin.xhtml</h2>
+ <h:form id="mainForm">
+ <h:commandButton value="End" action="content"/>
+ <h:commandButton id="end_flow" value="End" action="end"/>
+ <h:commandButton id="back_flow" value="Back" action="back"/>
+ <h:commandButton id="go_flow_base" value="Go to base" action="flow_base"/>
+ </h:form>
+ <!-- resolve outcome is quite useful to check how the flow target is resolved -->
+ <h:link outcome="end" value="End Outcome Link"/>
+</ui:composition>
+</body>
+</html>
Propchange: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow4/flow4.xhtml
------------------------------------------------------------------------------
svn:eol-style = native
Copied: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml (from r1509781, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1_end.xhtml)
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml?p2=myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml&p1=myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1_end.xhtml&r1=1509781&r2=1520941&rev=1520941&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow1_end.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml Sun Sep 8 23:52:33 2013
@@ -28,6 +28,16 @@
<h:panelGrid columns="1">
<h:form id="mainForm">
<h:commandButton id="startFlow1" action="flow1" value="Start Flow 1"/>
+ <h:commandButton id="startFlow2" action="flow2" value="Start Flow 2"/>
+ <h:commandButton id="startFlow3" action="flow3" value="Start Flow 3"/>
+ <h:commandButton id="startFlow4" action="flow4" value="Start Flow 4"/>
+ <h:commandButton id="startFlow1_4" action="call_flow1_4" value="Start Flow 1 from 4"/>
+ <h:commandButton id="returnFlow1" action="back_flow_1" value="Return Flow 1"/>
+ <h:commandButton id="returnFlow2" action="back_flow_2" value="Return Flow 2"/>
+ <h:commandButton id="returnFlow3" action="back_flow_3" value="Return Flow 3"/>
+ <h:commandButton id="returnFlow4" action="back_flow_4" value="Return Flow 4"/>
+ <h:commandButton id="returnFlow1_3" action="back_flow_1_3" value="Return from Flow 1 and 3"/>
+ <h:commandButton id="returnFlow1_4" action="back_flow_1_4" value="Return from Flow 1 and 4"/>
</h:form>
</h:panelGrid>
</h:body>