| Method from org.springframework.web.portlet.mvc.AbstractWizardFormController Detail: |
protected int getCurrentPage(PortletRequest request) {
// Check for overriding attribute in request.
String pageAttrName = getPageSessionAttributeName(request);
Integer pageAttr = (Integer) request.getAttribute(pageAttrName);
if (pageAttr != null) {
return pageAttr.intValue();
}
// Check for explicit request parameter.
String pageParam = request.getParameter(PARAM_PAGE);
if (pageParam != null) {
return Integer.parseInt(pageParam);
}
// Check for original attribute in session.
if (isSessionForm()) {
pageAttr = (Integer) request.getPortletSession().getAttribute(pageAttrName);
if (pageAttr != null) {
return pageAttr.intValue();
}
}
throw new IllegalStateException("Page attribute [" + pageAttrName + "] neither found in session nor in request");
}
Return the current page number. Used by #processFormSubmission .
The default implementation checks the page session attribute.
Subclasses can override this for customized page determination. |
protected int getInitialPage(PortletRequest request) {
return 0;
}
Return the initial page of the wizard, i.e. the page shown at wizard startup.
Default implementation returns 0 for first page. |
protected int getInitialPage(PortletRequest request,
Object command) {
return getInitialPage(request);
}
Return the initial page of the wizard, i.e. the page shown at wizard startup.
Default implementation delegates to getInitialPage(PortletRequest). |
public final String getPageAttribute() {
return this.pageAttribute;
}
Return the name of the page attribute in the model. |
protected final int getPageCount() {
return this.pages.length;
}
Return the number of wizard pages.
Useful to check whether the last page has been reached.
Note that a concrete wizard form controller might override
getPageCount(PortletRequest, Object) to determine
the page count dynamically. |
protected int getPageCount(PortletRequest request,
Object command) {
return getPageCount();
}
|
protected String getPageSessionAttributeName() {
return getClass().getName() + ".PAGE." + getCommandName();
}
Return the name of the PortletSession attribute that holds the page object
for this wizard form controller.
Default is an internal name, of no relevance to applications, as the form
session attribute is not usually accessed directly. Can be overridden to use
an application-specific attribute name, which allows other code to access
the session attribute directly. |
protected String getPageSessionAttributeName(PortletRequest request) {
return getPageSessionAttributeName();
}
|
public final String[] getPages() {
return this.pages;
}
Return the wizard pages, i.e. the view names for the pages.
The array index corresponds to the page number.
Note that a concrete wizard form controller might override
getViewName(PortletRequest, Object, int) to
determine the view name for each page dynamically. |
protected int getTargetPage(PortletRequest request,
int currentPage) {
return PortletUtils.getTargetPage(request, PARAM_TARGET, currentPage);
}
Return the target page specified in the request.
Default implementation examines "_target" parameter (e.g. "_target1").
Subclasses can override this for customized target page determination. |
protected int getTargetPage(PortletRequest request,
Object command,
Errors errors,
int currentPage) {
return getTargetPage(request, currentPage);
}
Return the target page specified in the request.
Default implementation delegates to
getTargetPage(PortletRequest, int).
Subclasses can override this for customized target page determination. |
protected String getViewName(PortletRequest request,
Object command,
int page) {
return getPages()[page];
}
Return the name of the view for the specified page of this wizard form controller.
Default implementation takes the view name from the getPages() array.
Can be overridden to dynamically switch the page view or to return view names
for dynamically defined pages. |
protected void handleInvalidSubmit(ActionRequest request,
ActionResponse response) throws Exception {
}
Handle an invalid submit request, e.g. when in session form mode but no form object
was found in the session (like in case of an invalid resubmit by the browser).
Default implementation for wizard form controllers simply shows the initial page
of a new wizard form, so here in the action phase this method does nothing. If you
want to take some action on an invalid submit, you need to override this method. |
public final boolean isAllowDirtyBack() {
return this.allowDirtyBack;
}
Return whether "dirty back" is allowed. |
public final boolean isAllowDirtyForward() {
return this.allowDirtyForward;
}
Return whether "dirty forward" is allowed. |
protected boolean isCancelRequest(PortletRequest request) {
return PortletUtils.hasSubmitParameter(request, PARAM_CANCEL);
}
Determine whether the incoming request is a request to cancel the
processing of the current form.
By default, this method returns true if a parameter
matching the "_cancel" key is present in the request, otherwise it
returns false. Subclasses may override this method
to provide custom logic to detect a cancel request.
The parameter is recognized both when sent as a plain parameter
("_cancel") or when triggered by an image button ("_cancel.x"). |
protected boolean isFinishRequest(PortletRequest request) {
return PortletUtils.hasSubmitParameter(request, PARAM_FINISH);
}
Determine whether the incoming request is a request to finish the
processing of the current form.
By default, this method returns true if a parameter
matching the "_finish" key is present in the request, otherwise it
returns false. Subclasses may override this method
to provide custom logic to detect a finish request.
The parameter is recognized both when sent as a plain parameter
("_finish") or when triggered by an image button ("_finish.x"). |
protected boolean isFormSubmission(PortletRequest request) {
return super.isFormSubmission(request) || isFinishRequest(request) || isCancelRequest(request);
}
Consider an explicit finish or cancel request as a form submission too. |
protected final void onBindAndValidate(PortletRequest request,
Object command,
BindException errors) throws Exception {
onBindAndValidate(request, command, errors, getCurrentPage(request));
}
Calls page-specific onBindAndValidate method. |
protected void onBindAndValidate(PortletRequest request,
Object command,
BindException errors,
int page) throws Exception {
}
Callback for custom post-processing in terms of binding and validation.
Called on each submit, after standard binding but before page-specific
validation of this wizard form controller.
Note: AbstractWizardFormController does not perform standard
validation on binding but rather applies page-specific validation
on processing the form submission. |
protected void postProcessPage(ActionRequest request,
Object command,
Errors errors,
int page) throws Exception {
}
Post-process the given page after binding and validation, potentially
updating its command object. The passed-in request might contain special
parameters sent by the page.
Only invoked when displaying another page or the same page again,
not when finishing or cancelling. |
protected void processCancel(ActionRequest request,
ActionResponse response,
Object command,
BindException errors) throws Exception {
throw new PortletException(
"Wizard form controller class [" + getClass().getName() + "] does not support a cancel action request");
}
Template method for the action phase of the cancel action of this wizard.
Default implementation throws a PortletException, saying that a cancel
action request is not supported by this controller. Thus, you do not need to
implement this template method if you do not support a cancel operation. |
protected void processFinish(ActionRequest request,
ActionResponse response,
Object command,
BindException errors) throws Exception {
throw new PortletException(
"Wizard form controller class [" + getClass().getName() + "] does not support a finish action request");
}
Template method for the action phase of the finish action of this wizard.
Default implementation throws a PortletException, saying that a finish
action request is not supported by this controller. You will almost certainly
need to override this method. |
protected final void processFormSubmission(ActionRequest request,
ActionResponse response,
Object command,
BindException errors) throws Exception {
int currentPage = getCurrentPage(request);
// Remove page session attribute, provide copy as request attribute.
String pageAttrName = getPageSessionAttributeName(request);
if (isSessionForm()) {
if (logger.isDebugEnabled()) {
logger.debug("Removing page session attribute [" + pageAttrName + "]");
}
request.getPortletSession().removeAttribute(pageAttrName);
}
request.setAttribute(pageAttrName, new Integer(currentPage));
// cancel?
if (isCancelRequest(request)) {
if (logger.isDebugEnabled()) {
logger.debug("Cancelling wizard for form bean '" + getCommandName() + "'");
}
setPageRenderParameter(response, currentPage);
setCancelRenderParameter(request, response);
processCancel(request, response, command, errors);
return;
}
// finish?
if (isFinishRequest(request)) {
if (logger.isDebugEnabled()) {
logger.debug("Finishing wizard for form bean '" + getCommandName() + "'");
}
if (!isRedirectAction()) {
setPageRenderParameter(response, currentPage);
setFinishRenderParameter(request, response);
}
validatePagesAndFinish(request, response, command, errors, currentPage);
return;
}
// Normal submit: validate current page
if (!suppressValidation(request)) {
if (logger.isDebugEnabled()) {
logger.debug("Validating wizard page " + currentPage + " for form bean '" + getCommandName() + "'");
}
validatePage(command, errors, currentPage, false);
}
setPageRenderParameter(response, currentPage);
setTargetRenderParameter(request, response);
passRenderParameters(request, response);
// Give subclasses a change to perform custom post-procession
// of the current page and its command object.
postProcessPage(request, command, errors, currentPage);
}
Apply wizard workflow: finish, cancel, page change. |
protected Map referenceData(PortletRequest request,
int page) throws Exception {
return null;
}
Create a reference data map for the given request, consisting of
bean name/bean instance pairs as expected by ModelAndView.
Default implementation returns null.
Subclasses can override this to set reference data used in the view. |
protected final Map referenceData(PortletRequest request,
Object command,
Errors errors) throws Exception {
return referenceData(request, command, errors, getCurrentPage(request));
}
Calls page-specific referenceData method. |
protected Map referenceData(PortletRequest request,
Object command,
Errors errors,
int page) throws Exception {
return referenceData(request, page);
}
Create a reference data map for the given request, consisting of
bean name/bean instance pairs as expected by ModelAndView.
Default implementation delegates to referenceData(HttpServletRequest, int).
Subclasses can override this to set reference data used in the view. |
protected ModelAndView renderCancel(RenderRequest request,
RenderResponse response,
Object command,
BindException errors) throws Exception {
throw new PortletException(
"Wizard form controller class [" + getClass().getName() + "] does not support a cancel render request");
}
Template method for the render phase of the cancel action of this wizard.
Default implementation throws a PortletException, saying that a cancel
render request is not supported by this controller. Thus, you do not need to
implement this template method if you do not support a cancel operation.
Call errors.getModel() to populate the ModelAndView model
with the command and the Errors instance, under the specified command name,
as expected by the "spring:bind" tag. |
protected ModelAndView renderFinish(RenderRequest request,
RenderResponse response,
Object command,
BindException errors) throws Exception {
throw new PortletException("Wizard form controller class [" + getClass().getName() + "] does not support a finish render request");
}
Template method for the render phase of the finish action of this wizard.
Default implementation throws a PortletException, saying that a finish
render request is not supported by this controller. Thus, you do not need to
implement this template method if you do not need to render after a finish.
Call errors.getModel() to populate the ModelAndView model
with the command and the Errors instance, under the specified command name,
as expected by the "spring:bind" tag. |
protected final ModelAndView renderFormSubmission(RenderRequest request,
RenderResponse response,
Object command,
BindException errors) throws Exception {
int currentPage = getCurrentPage(request);
String pageAttrName = getPageSessionAttributeName(request);
request.setAttribute(pageAttrName, new Integer(currentPage));
// cancel?
if (isCancelRequest(request)) {
if (logger.isDebugEnabled()) {
logger.debug("Cancelling wizard for form bean '" + getCommandName() + "'");
}
return renderCancel(request, response, command, errors);
}
// finish?
if (isFinishRequest(request)) {
if (logger.isDebugEnabled()) {
logger.debug("Finishing wizard for form bean '" + getCommandName() + "'");
}
return renderValidatePagesAndFinish(request, response, command, errors, currentPage);
}
// Normal submit: show specified target page.
int targetPage = getTargetPage(request, command, errors, currentPage);
if (logger.isDebugEnabled()) {
logger.debug("Target page " + targetPage + " requested");
}
if (targetPage != currentPage) {
if (!errors.hasErrors() || (this.allowDirtyBack && targetPage < currentPage) ||
(this.allowDirtyForward && targetPage > currentPage)) {
// Allowed to go to target page.
return showPage(request, errors, targetPage);
}
}
// Show current page again
return showPage(request, errors, currentPage);
}
Apply wizard workflow: finish, cancel, page change. |
protected ModelAndView renderInvalidSubmit(RenderRequest request,
RenderResponse response) throws Exception {
return showNewForm(request, response);
}
Handle an invalid submit request, e.g. when in session form mode but no form object
was found in the session (like in case of an invalid resubmit by the browser).
Default implementation for wizard form controllers simply shows the initial page
of a new wizard form. If you want to show some "invalid submit" message, you need
to override this method. |
public final void setAllowDirtyBack(boolean allowDirtyBack) {
this.allowDirtyBack = allowDirtyBack;
}
Set if "dirty back" is allowed, i.e. if moving to a former wizard
page is allowed in case of validation errors for the current page. |
public final void setAllowDirtyForward(boolean allowDirtyForward) {
this.allowDirtyForward = allowDirtyForward;
}
Set if "dirty forward" is allowed, i.e. if moving to a later wizard
page is allowed in case of validation errors for the current page. |
protected void setCancelRenderParameter(ActionRequest request,
ActionResponse response) {
if (logger.isDebugEnabled())
logger.debug("Setting cancel render parameter [" + PARAM_CANCEL + "]");
try {
String name = PortletUtils.getSubmitParameter(request, PARAM_CANCEL);
if (name != null)
response.setRenderParameter(name, request.getParameter(name));
}
catch (IllegalStateException ex) {
// ignore in case sendRedirect was already set
}
}
Pass the the parameter that indicates a cancel request forward to the
render phase. If the isCancelRequest method
was overridden, this may need to be overriden as well. |
protected void setFinishRenderParameter(ActionRequest request,
ActionResponse response) {
if (logger.isDebugEnabled())
logger.debug("Setting cancel render parameter [" + PARAM_FINISH + "]");
try {
String name = PortletUtils.getSubmitParameter(request, PARAM_FINISH);
if (name != null)
response.setRenderParameter(name, request.getParameter(name));
}
catch (IllegalStateException ex) {
// ignore in case sendRedirect was already set
}
}
Pass the the parameter that indicates a finish request forward to the
render phase. If the isFinishRequest method
was overridden, this may need to be overriden as well. |
public final void setPageAttribute(String pageAttribute) {
this.pageAttribute = pageAttribute;
}
Set the name of the page attribute in the model, containing
an Integer with the current page number.
This will be necessary for single views rendering multiple view pages.
It also allows for specifying the optional "_page" parameter. |
protected void setPageRenderParameter(ActionResponse response,
int page) {
if (logger.isDebugEnabled())
logger.debug("Setting page number render parameter [" + PARAM_PAGE + "] to [" + page + "]");
try {
response.setRenderParameter(PARAM_PAGE, new Integer(page).toString());
}
catch (IllegalStateException ex) {
// ignore in case sendRedirect was already set
}
}
|
public final void setPages(String[] pages) {
if (pages == null || pages.length == 0) {
throw new IllegalArgumentException("No wizard pages defined");
}
this.pages = pages;
}
Set the wizard pages, i.e. the view names for the pages.
The array index is interpreted as page number. |
protected void setTargetRenderParameter(ActionRequest request,
ActionResponse response) {
try {
Iterator it = PortletUtils.getParametersStartingWith(request, PARAM_TARGET).entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String param = PARAM_TARGET + (String) entry.getKey();
Object value = entry.getValue();
if (logger.isDebugEnabled()) {
logger.debug("Setting target render parameter [" + param + "]");
}
if (value instanceof String) {
response.setRenderParameter(param, (String) value);
}
else if (value instanceof String[]) {
response.setRenderParameter(param, (String[]) value);
}
}
}
catch (IllegalStateException ex) {
// ignore in case sendRedirect was already set
}
}
Pass the the parameter that indicates the target page of the request
forward to the render phase. If the getTargetPage method
was overridden, this may need to be overriden as well. |
protected ModelAndView showForm(RenderRequest request,
RenderResponse response,
BindException errors) throws Exception {
return showPage(request, errors, getInitialPage(request, errors.getTarget()));
}
Show the first page as form view.
This can be overridden in subclasses, e.g. to prepare wizard-specific
error views in case of an Exception. |
protected final ModelAndView showPage(RenderRequest request,
BindException errors,
int page) throws Exception {
if (page >= 0 && page < getPageCount(request, errors.getTarget())) {
if (logger.isDebugEnabled()) {
logger.debug("Showing wizard page " + page + " for form bean '" + getCommandName() + "'");
}
// Set page session attribute, expose overriding request attribute.
Integer pageInteger = new Integer(page);
String pageAttrName = getPageSessionAttributeName(request);
if (isSessionForm()) {
if (logger.isDebugEnabled()) {
logger.debug("Setting page session attribute [" + pageAttrName + "] to: " + pageInteger);
}
request.getPortletSession().setAttribute(pageAttrName, pageInteger);
}
request.setAttribute(pageAttrName, pageInteger);
// Set page request attribute for evaluation by views.
Map controlModel = new HashMap();
if (this.pageAttribute != null) {
controlModel.put(this.pageAttribute, new Integer(page));
}
String viewName = getViewName(request, errors.getTarget(), page);
return showForm(request, errors, viewName, controlModel);
}
else {
throw new PortletException("Invalid wizard page number: " + page);
}
}
Prepare the form model and view, including reference and error data,
for the given page. Can be used in processFinish implementations,
to show the corresponding page in case of validation errors. |
protected void validatePage(Object command,
Errors errors,
int page) {
}
Template method for custom validation logic for individual pages.
Default implementation is empty.
Implementations will typically call fine-granular validateXXX methods of this
instance's validator, combining them to validation of the corresponding pages.
The validator's default validate method will not be called by a
wizard form controller! |
protected void validatePage(Object command,
Errors errors,
int page,
boolean finish) {
validatePage(command, errors, page);
}
Template method for custom validation logic for individual pages.
Default implementation calls validatePage(command, errors, page).
Implementations will typically call fine-granular validateXXX
methods of this instance's Validator, combining them to validation of the
corresponding pages. The Validator's default validate method
will not be called by a wizard form controller! |