mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
First cut of dialog/wizard framework
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2577 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -26,23 +26,37 @@ import javax.faces.context.FacesContext;
|
||||
|
||||
import org.alfresco.config.Config;
|
||||
import org.alfresco.config.ConfigService;
|
||||
import org.alfresco.web.app.context.UIContextService;
|
||||
import org.alfresco.web.bean.NavigationBean;
|
||||
import org.alfresco.web.bean.dialog.DialogManager;
|
||||
import org.alfresco.web.bean.repository.Node;
|
||||
import org.alfresco.web.bean.wizard.WizardManager;
|
||||
import org.alfresco.web.config.DialogsConfigElement;
|
||||
import org.alfresco.web.config.NavigationConfigElement;
|
||||
import org.alfresco.web.config.NavigationElementReader;
|
||||
import org.alfresco.web.config.NavigationResult;
|
||||
import org.alfresco.web.config.DialogsConfigElement.DialogConfig;
|
||||
import org.alfresco.web.config.WizardsConfigElement.WizardConfig;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.web.jsf.FacesContextUtils;
|
||||
|
||||
/**
|
||||
* @author gavinc
|
||||
*/
|
||||
public class AlfrescoNavigationHandler extends NavigationHandler
|
||||
{
|
||||
public final static String DIALOG_SEPARATOR = ":";
|
||||
public final static String DIALOG_PREXIX = "dialog" + DIALOG_SEPARATOR;
|
||||
public final static String OUTCOME_SEPARATOR = ":";
|
||||
public final static String DIALOG_PREXIX = "dialog" + OUTCOME_SEPARATOR;
|
||||
public final static String WIZARD_PREFIX = "wizard" + OUTCOME_SEPARATOR;
|
||||
public final static String CLOSE_DIALOG_OUTCOME = DIALOG_PREXIX + "close";
|
||||
public final static String CLOSE_WIZARD_OUTCOME = WIZARD_PREFIX + "close";
|
||||
|
||||
protected final static String CONFIG_NAV_BEAN = "NavigationBean";
|
||||
protected final static String CONFIG_DIALOGS = "Dialogs";
|
||||
protected final static String CONFIG_WIZARDS = "Wizards";
|
||||
|
||||
protected String dialogContainer = null;
|
||||
protected String wizardContainer = null;
|
||||
|
||||
private final static Log logger = LogFactory.getLog(AlfrescoNavigationHandler.class);
|
||||
private final static String VIEW_STACK = "_alfViewStack";
|
||||
@@ -69,186 +83,530 @@ public class AlfrescoNavigationHandler extends NavigationHandler
|
||||
public void handleNavigation(FacesContext context, String fromAction, String outcome)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("handleNavigation (fromAction=" + fromAction + ", outcome=" + outcome + ")");
|
||||
logger.debug("Current view id: " + context.getViewRoot().getViewId());
|
||||
}
|
||||
|
||||
boolean isDialog = isDialog(outcome);
|
||||
if (isDialog || isWizard(outcome))
|
||||
{
|
||||
boolean dialogWizardClosing = isDialogOrWizardClosing(outcome);
|
||||
outcome = stripPrefix(outcome);
|
||||
|
||||
if (dialogWizardClosing)
|
||||
{
|
||||
handleDialogOrWizardClose(context, fromAction, outcome);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDialog)
|
||||
{
|
||||
handleDialogOpen(context, fromAction, outcome);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleWizardOpen(context, fromAction, outcome);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("view stack: " + getViewStack(context));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handleDispatch(context, fromAction, outcome);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given outcome is dialog related
|
||||
*
|
||||
* @param outcome The outcome to test
|
||||
* @return true if outcome is dialog related i.e. starts with dialog:
|
||||
*/
|
||||
protected boolean isDialog(String outcome)
|
||||
{
|
||||
boolean dialog = false;
|
||||
|
||||
boolean useOriginalNavHandler = true;
|
||||
boolean closingDialog = false;
|
||||
String viewId = context.getViewRoot().getViewId();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Current view id: " + viewId);
|
||||
|
||||
// determine if we are dealing with a dialog
|
||||
if (outcome != null && outcome.startsWith(DIALOG_PREXIX))
|
||||
{
|
||||
// determine whether it's being closed or opened
|
||||
closingDialog = outcome.startsWith(CLOSE_DIALOG_OUTCOME);
|
||||
|
||||
// remove the dialog prefix
|
||||
outcome = outcome.substring(DIALOG_PREXIX.length());
|
||||
|
||||
if (closingDialog)
|
||||
dialog = true;
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given outcome is wizard related
|
||||
*
|
||||
* @param outcome The outcome to test
|
||||
* @return true if outcome is wizard related
|
||||
* i.e. starts with create-wizard: or edit-wizard:
|
||||
*/
|
||||
protected boolean isWizard(String outcome)
|
||||
{
|
||||
boolean wizard = false;
|
||||
|
||||
if (outcome != null && outcome.startsWith(WIZARD_PREFIX))
|
||||
{
|
||||
wizard = true;
|
||||
}
|
||||
|
||||
return wizard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given outcome represents a dialog or wizard closing
|
||||
*
|
||||
* @param outcome The outcome to test
|
||||
* @return true if the outcome represents a closing dialog or wizard
|
||||
*/
|
||||
protected boolean isDialogOrWizardClosing(String outcome)
|
||||
{
|
||||
boolean closing = false;
|
||||
|
||||
if (outcome != null &&
|
||||
(outcome.startsWith(CLOSE_DIALOG_OUTCOME) ||
|
||||
outcome.startsWith(CLOSE_WIZARD_OUTCOME)))
|
||||
{
|
||||
closing = true;
|
||||
}
|
||||
|
||||
return closing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the dialog or wizard prefix from the given outcome
|
||||
*
|
||||
* @param outcome The outcome to remove the prefix from
|
||||
* @return The remaining outcome
|
||||
*/
|
||||
protected String stripPrefix(String outcome)
|
||||
{
|
||||
String newOutcome = outcome;
|
||||
|
||||
if (outcome != null)
|
||||
{
|
||||
int idx = outcome.indexOf(OUTCOME_SEPARATOR);
|
||||
if (idx != -1)
|
||||
{
|
||||
// if we are closing the dialog take the view off the
|
||||
// top of the stack then decide whether to use the view
|
||||
// or any overridden outcome that may be present
|
||||
if (getViewStack(context).empty() == false)
|
||||
newOutcome = outcome.substring(idx+1);
|
||||
}
|
||||
}
|
||||
|
||||
return newOutcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the overridden outcome.
|
||||
* Used by dialogs and wizards to go to a particular page after it closes
|
||||
* rather than back to the page it was launched from.
|
||||
*
|
||||
* @param outcome The current outcome
|
||||
* @return The overridden outcome or null if there isn't an override
|
||||
*/
|
||||
protected String getOutcomeOverride(String outcome)
|
||||
{
|
||||
String override = null;
|
||||
|
||||
if (outcome != null)
|
||||
{
|
||||
int idx = outcome.indexOf(OUTCOME_SEPARATOR);
|
||||
if (idx != -1)
|
||||
{
|
||||
override = outcome.substring(idx+1);
|
||||
}
|
||||
}
|
||||
|
||||
return override;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dialog configuration object for the given dialog name.
|
||||
* If there is a node in the dispatch context a lookup is performed using
|
||||
* the node. If this doesn't return any config or there is no dispatch
|
||||
* context node a 'global' dialog lookup is performed.
|
||||
*
|
||||
*
|
||||
* @param name The name of dialog being launched
|
||||
* @param dispatchContext The node being acted upon
|
||||
* @return The DialogConfig for the dialog or null if no config could be found
|
||||
*/
|
||||
protected DialogConfig getDialogConfig(FacesContext context, String name, Node dispatchContext)
|
||||
{
|
||||
DialogConfig dialogConfig = null;
|
||||
ConfigService configSvc = Application.getConfigService(context);
|
||||
|
||||
if (dispatchContext != null)
|
||||
{
|
||||
Config config = configSvc.getConfig(dispatchContext);
|
||||
if (config != null)
|
||||
{
|
||||
DialogsConfigElement dialogsCfg = (DialogsConfigElement)config.getConfigElement(
|
||||
DialogsConfigElement.CONFIG_ELEMENT_ID);
|
||||
if (dialogsCfg != null)
|
||||
{
|
||||
String newViewId = (String)getViewStack(context).pop();
|
||||
dialogConfig = dialogsCfg.getDialog(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find a dialog via the dispatch look it up in the 'global' dialogs config
|
||||
if (dialogConfig == null)
|
||||
{
|
||||
Config config = configSvc.getConfig(CONFIG_DIALOGS);
|
||||
if (config != null)
|
||||
{
|
||||
DialogsConfigElement dialogsCfg = (DialogsConfigElement)config.getConfigElement(
|
||||
DialogsConfigElement.CONFIG_ELEMENT_ID);
|
||||
if (dialogsCfg != null)
|
||||
{
|
||||
dialogConfig = dialogsCfg.getDialog(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dialogConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wizard configuration object for the given wizard name.
|
||||
* If there is a node in the dispatch context a lookup is performed using
|
||||
* the node otherwise a 'global' wizard lookup is performed.
|
||||
*
|
||||
* @param name The name of wizard being launched
|
||||
* @param dispatchContext The node being acted upon
|
||||
* @return The WizardConfig for the wizard or null if no config could be found
|
||||
*/
|
||||
protected WizardConfig getWizardConfig(FacesContext context, String name, Node dispatchContext)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the configured dialog container page
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @return The container page
|
||||
*/
|
||||
protected String getDialogContainer(FacesContext context)
|
||||
{
|
||||
if (this.dialogContainer == null)
|
||||
{
|
||||
ConfigService configSvc = Application.getConfigService(context);
|
||||
Config dialogsConfig = configSvc.getConfig(CONFIG_DIALOGS);
|
||||
|
||||
if (dialogsConfig != null)
|
||||
{
|
||||
this.dialogContainer = dialogsConfig.getConfigElement("dialog-container").getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return this.dialogContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the configured wizard container page
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @return The container page
|
||||
*/
|
||||
protected String getWizardContainer(FacesContext context)
|
||||
{
|
||||
if (this.wizardContainer == null)
|
||||
{
|
||||
ConfigService configSvc = Application.getConfigService(context);
|
||||
Config wizardsConfig = configSvc.getConfig(CONFIG_WIZARDS);
|
||||
|
||||
if (wizardsConfig != null)
|
||||
{
|
||||
this.wizardContainer = wizardsConfig.getConfigElement("wizard-container").getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return this.wizardContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node currently in the dispatch context
|
||||
*
|
||||
* @return The node currently in the dispatch context or null if
|
||||
* the dispatch context is empty
|
||||
*/
|
||||
protected Node getDispatchContextNode(FacesContext context)
|
||||
{
|
||||
Node dispatchNode = null;
|
||||
|
||||
NavigationBean navBean = (NavigationBean)context.getExternalContext().
|
||||
getSessionMap().get(CONFIG_NAV_BEAN);
|
||||
|
||||
if (navBean != null)
|
||||
{
|
||||
dispatchNode = navBean.getDispatchContextNode();
|
||||
}
|
||||
|
||||
return dispatchNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes any dispatching that may need to occur
|
||||
*
|
||||
* @param node The node in the current dispatch context
|
||||
* @param viewId The current view id
|
||||
* @param outcome The outcome
|
||||
*/
|
||||
protected void handleDispatch(FacesContext context, String fromAction, String outcome)
|
||||
{
|
||||
Node dispatchNode = getDispatchContextNode(context);
|
||||
|
||||
if (dispatchNode != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found node with type '" + dispatchNode.getType().toString() +
|
||||
"' in dispatch context");
|
||||
|
||||
// get the current view id
|
||||
String viewId = context.getViewRoot().getViewId();
|
||||
|
||||
// is there an overiddent outcome?
|
||||
int idx = outcome.indexOf(DIALOG_SEPARATOR);
|
||||
if (idx == -1)
|
||||
{
|
||||
// there isn't an overidden outcome so go back to the previous view
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Closing dialog, going back to view id: " + newViewId);
|
||||
// see if there is any navigation config for the node type
|
||||
ConfigService configSvc = Application.getConfigService(context);
|
||||
Config nodeConfig = configSvc.getConfig(dispatchNode);
|
||||
NavigationConfigElement navigationCfg = (NavigationConfigElement)nodeConfig.
|
||||
getConfigElement(NavigationElementReader.ELEMENT_NAVIGATION);
|
||||
|
||||
if (navigationCfg != null)
|
||||
{
|
||||
// see if there is config for the current view state
|
||||
NavigationResult navResult = navigationCfg.getOverride(viewId, outcome);
|
||||
|
||||
if (navResult != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found navigation config: " + navResult);
|
||||
|
||||
goToView(context, newViewId);
|
||||
if (navResult.isOutcome())
|
||||
{
|
||||
navigate(context, fromAction, navResult.getResult());
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is an overidden outcome so extract it
|
||||
outcome = outcome.substring(idx+1, outcome.length());
|
||||
String newViewId = navResult.getResult();
|
||||
|
||||
// we also need to empty the dialog stack if we have been given
|
||||
// an overidden outcome as we could be going anywhere in the app
|
||||
getViewStack(context).clear();
|
||||
if (newViewId.equals(viewId) == false)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Dispatching to new view id: " + newViewId);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Closing dialog with an overridden outcome of '" + outcome + "'");
|
||||
|
||||
this.origHandler.handleNavigation(context, fromAction, outcome);
|
||||
goToView(context, newViewId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("New view id is the same as the current one so setting outcome to null");
|
||||
|
||||
navigate(context, fromAction, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are trying to close a dialog when one hasn't been opened!
|
||||
// log a warning and return a null outcome to stay on the same page
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("Attempting to close a dialog with an empty view stack, returning null outcome");
|
||||
}
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("No override configuration found for current view or outcome");
|
||||
|
||||
this.origHandler.handleNavigation(context, fromAction, null);
|
||||
navigate(context, fromAction, outcome);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are opening a dialog push the current view id
|
||||
// on to the stack, but only if it is different than the
|
||||
// current view at the top (you can't launch a dialog from
|
||||
// the same page 2 times in a row!)
|
||||
|
||||
// TODO: This wouldn't happen if we could be sure a dialog is
|
||||
// ALWAYS exited properly, look into a way of ensuring
|
||||
// dialogs get closed if a user navigates away from the page,
|
||||
// would a PhaseListener help in any way??
|
||||
|
||||
if (getViewStack(context).empty() ||
|
||||
viewId.equals(getViewStack(context).peek()) == false)
|
||||
{
|
||||
getViewStack(context).push(viewId);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Pushed current view to stack: " + viewId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getViewStack(context).empty() == false && logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("current view is already top the view stack!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("view stack: " + getViewStack(context));
|
||||
}
|
||||
|
||||
if (closingDialog == false)
|
||||
{
|
||||
NavigationBean navBean = (NavigationBean)context.getExternalContext().
|
||||
getSessionMap().get("NavigationBean");
|
||||
|
||||
// only continue if we have some dispatching context
|
||||
if (navBean != null && navBean.getDispatchContextNode() != null)
|
||||
{
|
||||
Node node = navBean.getDispatchContextNode();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found node with type '" + node.getType().toString() +
|
||||
"' in dispatch context");
|
||||
|
||||
// see if there is any navigation config for the node type
|
||||
ConfigService configSvc = Application.getConfigService(context);
|
||||
Config nodeConfig = configSvc.getConfig(node);
|
||||
NavigationConfigElement navigationCfg = (NavigationConfigElement)nodeConfig.
|
||||
getConfigElement(NavigationElementReader.ELEMENT_NAVIGATION);
|
||||
|
||||
if (navigationCfg != null)
|
||||
{
|
||||
// see if there is config for the current view state
|
||||
NavigationResult navResult = navigationCfg.getOverride(viewId, outcome);
|
||||
|
||||
if (navResult != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found navigation config: " + navResult);
|
||||
|
||||
if (navResult.isOutcome())
|
||||
{
|
||||
outcome = navResult.getResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
String newViewId = navResult.getResult();
|
||||
|
||||
if (newViewId.equals(viewId) == false)
|
||||
{
|
||||
useOriginalNavHandler = false;
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Dispatching to new view id: " + newViewId);
|
||||
|
||||
goToView(context, newViewId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("New view id is the same as the current one so setting outcome to null");
|
||||
|
||||
outcome = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("No override configuration found for current view or outcome");
|
||||
}
|
||||
}
|
||||
else if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("No navigation configuration found for node");
|
||||
}
|
||||
|
||||
// reset the dispatch context
|
||||
navBean.resetDispatchContext();
|
||||
}
|
||||
else if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("No dispatch context found");
|
||||
navigate(context, fromAction, outcome);
|
||||
}
|
||||
|
||||
// do the appropriate navigation handling
|
||||
if (useOriginalNavHandler)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Passing outcome '" + outcome + "' to original navigation handler");
|
||||
// reset the dispatch context
|
||||
((NavigationBean)context.getExternalContext().getSessionMap().
|
||||
get(CONFIG_NAV_BEAN)).resetDispatchContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("No dispatch context found");
|
||||
|
||||
this.origHandler.handleNavigation(context, fromAction, outcome);
|
||||
// pass off to the original handler
|
||||
navigate(context, fromAction, outcome);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a dialog
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param fromAction The fromAction
|
||||
* @param name The name of the dialog to open
|
||||
*/
|
||||
protected void handleDialogOpen(FacesContext context, String fromAction, String name)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Opening dialog '" + name + "'");
|
||||
|
||||
// firstly add the current view to the stack so we know where to go back to
|
||||
addCurrentViewToStack(context);
|
||||
|
||||
DialogConfig config = getDialogConfig(context, name, getDispatchContextNode(context));
|
||||
if (config != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found config for dialog '" + name + "': " + config);
|
||||
|
||||
// set the dialog manager up with the retrieved config
|
||||
DialogManager dialogManager = Application.getDialogManager();
|
||||
dialogManager.setCurrentDialog(config);
|
||||
|
||||
// retrieve the container page and navigate to it
|
||||
goToView(context, getDialogContainer(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
// send the dialog name as the outcome to the original handler
|
||||
handleDispatch(context, fromAction, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a wizard
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param fromAction The fromAction
|
||||
* @param name The name of the wizard to open
|
||||
*/
|
||||
protected void handleWizardOpen(FacesContext context, String fromAction, String name)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Opening wizard '" + name + "'");
|
||||
|
||||
// firstly add the current view to the stack so we know where to go back to
|
||||
addCurrentViewToStack(context);
|
||||
|
||||
WizardConfig wizard = getWizardConfig(context, name, getDispatchContextNode(context));
|
||||
if (wizard != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found config for wizard '" + name + "': " + wizard);
|
||||
|
||||
// set the wizard manager up with the retrieved config
|
||||
WizardManager wizardManager = Application.getWizardManager();
|
||||
wizardManager.setCurrentWizard(wizard);
|
||||
|
||||
// retrieve the container page and navigate to it
|
||||
goToView(context, getWizardContainer(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
// send the dialog name as the outcome to the original handler
|
||||
handleDispatch(context, fromAction, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the current dialog or wizard
|
||||
*/
|
||||
protected void handleDialogOrWizardClose(FacesContext context, String fromAction, String outcome)
|
||||
{
|
||||
// if we are closing the dialog take the view off the
|
||||
// top of the stack then decide whether to use the view
|
||||
// or any overridden outcome that may be present
|
||||
if (getViewStack(context).empty() == false)
|
||||
{
|
||||
String newViewId = (String)getViewStack(context).pop();
|
||||
|
||||
// is there an overidden outcome?
|
||||
String overriddenOutcome = getOutcomeOverride(outcome);
|
||||
if (overriddenOutcome == null)
|
||||
{
|
||||
// there isn't an overidden outcome so go back to the previous view
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Closing dialog, going back to view id: " + newViewId);
|
||||
|
||||
goToView(context, newViewId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we also need to empty the dialog stack if we have been given
|
||||
// an overidden outcome as we could be going anywhere in the app
|
||||
getViewStack(context).clear();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Closing dialog with an overridden outcome of '" + overriddenOutcome + "'");
|
||||
|
||||
navigate(context, fromAction, overriddenOutcome);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are trying to close a dialog when one hasn't been opened!
|
||||
// log a warning and return a null outcome to stay on the same page
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("Attempting to close a dialog with an empty view stack, returning null outcome");
|
||||
}
|
||||
|
||||
navigate(context, fromAction, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the current view to the stack (if required).
|
||||
* If the current view is already the top of the stack it is not added again
|
||||
* to stop the stack from growing and growing.
|
||||
*
|
||||
* @param context FacesContext
|
||||
*/
|
||||
protected void addCurrentViewToStack(FacesContext context)
|
||||
{
|
||||
// if we are opening a dialog push the current view id
|
||||
// on to the stack, but only if it is different than the
|
||||
// current view at the top (you can't launch a dialog from
|
||||
// the same page 2 times in a row!)
|
||||
|
||||
// TODO: This wouldn't happen if we could be sure a dialog is
|
||||
// ALWAYS exited properly, look into a way of ensuring
|
||||
// dialogs get closed if a user navigates away from the page,
|
||||
// would a PhaseListener help in any way??
|
||||
|
||||
String viewId = context.getViewRoot().getViewId();
|
||||
|
||||
if (getViewStack(context).empty() ||
|
||||
viewId.equals(getViewStack(context).peek()) == false)
|
||||
{
|
||||
getViewStack(context).push(viewId);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Pushed current view to stack: " + viewId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getViewStack(context).empty() == false && logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("current view is already top the view stack!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the appropriate page using the original navigation handler
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param fromAction The fromAction
|
||||
* @param outcome The outcome
|
||||
*/
|
||||
private void navigate(FacesContext context, String fromAction, String outcome)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Passing outcome '" + outcome + "' to original navigation handler");
|
||||
|
||||
this.origHandler.handleNavigation(context, fromAction, outcome);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,13 +632,13 @@ public class AlfrescoNavigationHandler extends NavigationHandler
|
||||
* the users session, will never be null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Stack getViewStack(FacesContext context)
|
||||
private Stack<String> getViewStack(FacesContext context)
|
||||
{
|
||||
Stack viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK);
|
||||
Stack<String> viewStack = (Stack)context.getExternalContext().getSessionMap().get(VIEW_STACK);
|
||||
|
||||
if (viewStack == null)
|
||||
{
|
||||
viewStack = new Stack();
|
||||
viewStack = new Stack<String>();
|
||||
context.getExternalContext().getSessionMap().put(VIEW_STACK, viewStack);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user