String implicitViewId = null;
boolean includeViewParams = false;
int index;
boolean isRedirect = false;
String queryString = null;
NavigationCase result = null;
String viewId = facesContext.getViewRoot() != null ? facesContext.getViewRoot().getViewId() : null;
//String viewIdToTest = outcome;
StringBuilder viewIdToTest = SharedStringBuilder.get(facesContext, OUTCOME_NAVIGATION_SB);
viewIdToTest.append(outcome);
// If viewIdToTest contains a query string, remove it and set queryString with that value.
index = viewIdToTest.indexOf ("?");
if (index != -1)
{
queryString = viewIdToTest.substring (index + 1);
//viewIdToTest = viewIdToTest.substring (0, index);
viewIdToTest.setLength(index);
// If queryString contains "faces-redirect=true", set isRedirect to true.
if (queryString.indexOf ("faces-redirect=true") != -1)
{
isRedirect = true;
}
// If queryString contains "includeViewParams=true" or
// "faces-include-view-params=true", set includeViewParams to true.
if (queryString.indexOf("includeViewParams=true") != -1
|| queryString.indexOf("faces-include-view-params=true") != -1)
{
includeViewParams = true;
}
}
// If viewIdToTest does not have a "file extension", use the one from the current viewId.
index = viewIdToTest.indexOf (".");
if (index == -1)
{
if (viewId != null)
{
index = viewId.lastIndexOf(".");
if (index != -1)
{
//viewIdToTest += viewId.substring (index);
viewIdToTest.append(viewId.substring (index));
}
}
else
{
// This case happens when for for example there is a ViewExpiredException,
// and a custom ExceptionHandler try to navigate using implicit navigation.
// In this case, there is no UIViewRoot set on the FacesContext, so viewId
// is null.
// In this case, it should try to derive the viewId of the view that was
// not able to restore, to get the extension and apply it to
// the implicit navigation.
String tempViewId = getNavigationHandlerSupport().calculateViewId(facesContext);
if (tempViewId != null)
{
index = tempViewId.lastIndexOf(".");
if(index != -1)
{
viewIdToTest.append(tempViewId.substring (index));
}
}
}
if (log.isLoggable(Level.FINEST))
{
log.finest("getOutcomeNavigationCase -> viewIdToTest: " + viewIdToTest);
}
}
// If viewIdToTest does not start with "/", look for the last "/" in viewId. If not found, simply prepend "/".
// Otherwise, prepend everything before and including the last "/" in viewId.
//if (!viewIdToTest.startsWith ("/") && viewId != null)
boolean startWithSlash = false;
if (viewIdToTest.length() > 0)
{
startWithSlash = (viewIdToTest.charAt(0) == '/');
}
if (!startWithSlash)
{
index = -1;
if( viewId != null )
{
index = viewId.lastIndexOf ("/");
}
if (index == -1)
{
//viewIdToTest = "/" + viewIdToTest;
viewIdToTest.insert(0,"/");
}
else
{
//viewIdToTest = viewId.substring (0, index + 1) + viewIdToTest;
viewIdToTest.insert(0, viewId, 0, index + 1);
}
}
// Call ViewHandler.deriveViewId() and set the result as implicitViewId.
try
{
implicitViewId = facesContext.getApplication().getViewHandler().deriveViewId (
facesContext, viewIdToTest.toString());
}
catch (UnsupportedOperationException e)
{
// This is the case when a pre-JSF 2.0 ViewHandler is used.
// In this case, the default algorithm must be used.
// FIXME: I think we're always calling the "default" ViewHandler.deriveViewId() algorithm and we don't
// distinguish between pre-JSF 2.0 and JSF 2.0 ViewHandlers. This probably needs to be addressed.
}
if (implicitViewId != null)
{
// Append all params from the queryString
// (excluding faces-redirect, includeViewParams and faces-include-view-params)
Map<String, List<String>> params = null;
if (queryString != null && !"".equals(queryString))
{
//String[] splitQueryParams = queryString.split("&(amp;)?"); // "&" or "&"
String[] splitQueryParams = AMP_PATTERN.split(queryString); // "&" or "&"
params = new HashMap<String, List<String>>(splitQueryParams.length,
(splitQueryParams.length* 4 + 3) / 3);
for (String queryParam : splitQueryParams)
{
String[] splitParam = StringUtils.splitShortString(queryParam, '=');
if (splitParam.length == 2)
{
// valid parameter - add it to params
if ("includeViewParams".equals(splitParam[0])
|| "faces-include-view-params".equals(splitParam[0])
|| "faces-redirect".equals(splitParam[0]))
{
// ignore includeViewParams, faces-include-view-params and faces-redirect
continue;
}
List<String> paramValues = params.get(splitParam[0]);
if (paramValues == null)
{
// no value for the given parameter yet
paramValues = new ArrayList<String>();
params.put(splitParam[0], paramValues);
}
paramValues.add(splitParam[1]);
}
else
{
// invalid parameter
throw new FacesException("Invalid parameter \"" +
queryParam + "\" in outcome " + outcome);
}
}
}
// Finally, create the NavigationCase.
result = new NavigationCase (viewId, fromAction, outcome, null,
implicitViewId, params, isRedirect, includeViewParams);
}
return result;
}