Source Code Cross Referenced for AbstractWizardFormController.java in  » J2EE » spring-framework-2.0.6 » org » springframework » web » servlet » mvc » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.0.6 » org.springframework.web.servlet.mvc 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.web.servlet.mvc;
018:
019:        import java.util.Enumeration;
020:        import java.util.HashMap;
021:        import java.util.Map;
022:
023:        import javax.servlet.ServletException;
024:        import javax.servlet.http.HttpServletRequest;
025:        import javax.servlet.http.HttpServletResponse;
026:
027:        import org.springframework.validation.BindException;
028:        import org.springframework.validation.Errors;
029:        import org.springframework.web.servlet.ModelAndView;
030:        import org.springframework.web.util.WebUtils;
031:
032:        /**
033:         * Form controller for typical wizard-style workflows.
034:         *
035:         * <p>In contrast to classic forms, wizards have more than one form view page.
036:         * Therefore, there are various actions instead of one single submit action:
037:         * <ul>
038:         * <li>finish: trying to leave the wizard successfully, that is, perform its
039:         * final action, and thus requiring a valid state;
040:         * <li>cancel: leaving the wizard without performing its final action, and
041:         * thus without regard to the validity of its current state;
042:         * <li>page change: showing another wizard page, e.g. the next or previous
043:         * one, with regard to "dirty back" and "dirty forward".
044:         * </ul>
045:         *
046:         * <p>Finish and cancel actions can be triggered by request parameters, named
047:         * PARAM_FINISH ("_finish") and PARAM_CANCEL ("_cancel"), ignoring parameter
048:         * values to allow for HTML buttons. The target page for page changes can be
049:         * specified by PARAM_TARGET, appending the page number to the parameter name
050:         * (e.g. "_target1"). The action parameters are recognized when triggered by
051:         * image buttons too (via "_finish.x", "_abort.x", or "_target1.x").
052:         *
053:         * <p>The current page number will be stored in the session. It can also be
054:         * specified as request parameter PARAM_PAGE, to properly handle usage of
055:         * the back button in a browser: In this case, a submission always contains
056:         * the correct page number, even if the user submitted from an old view.
057:         *
058:         * <p>The page can only be changed if it validates correctly, except if a
059:         * "dirty back" or "dirty forward" is allowed. At finish, all pages get
060:         * validated again to guarantee a consistent state.
061:         *
062:         * <p>Note that a validator's default validate method is not executed when using
063:         * this class! Rather, the {@link #validatePage} implementation should call
064:         * special <code>validateXXX</code> methods that the validator needs to provide,
065:         * validating certain pieces of the object. These can be combined to validate
066:         * the elements of individual pages.
067:         *
068:         * <p>Note: Page numbering starts with 0, to be able to pass an array
069:         * consisting of the corresponding view names to the "pages" bean property.
070:         *
071:         * @author Juergen Hoeller
072:         * @since 25.04.2003
073:         * @see #setPages
074:         * @see #validatePage
075:         * @see #processFinish
076:         * @see #processCancel
077:         */
078:        public abstract class AbstractWizardFormController extends
079:                AbstractFormController {
080:
081:            /**
082:             * Parameter triggering the finish action.
083:             * Can be called from any wizard page!
084:             */
085:            public static final String PARAM_FINISH = "_finish";
086:
087:            /**
088:             * Parameter triggering the cancel action.
089:             * Can be called from any wizard page!
090:             */
091:            public static final String PARAM_CANCEL = "_cancel";
092:
093:            /**
094:             * Parameter specifying the target page,
095:             * appending the page number to the name.
096:             */
097:            public static final String PARAM_TARGET = "_target";
098:
099:            /**
100:             * Parameter specifying the current page as value. Not necessary on
101:             * form pages, but allows to properly handle usage of the back button.
102:             * @see #setPageAttribute
103:             */
104:            public static final String PARAM_PAGE = "_page";
105:
106:            private String[] pages;
107:
108:            private String pageAttribute;
109:
110:            private boolean allowDirtyBack = true;
111:
112:            private boolean allowDirtyForward = false;
113:
114:            /**
115:             * Create a new AbstractWizardFormController.
116:             * <p>"sessionForm" is automatically turned on, "validateOnBinding"
117:             * turned off, and "cacheSeconds" set to 0 by the base class
118:             * (-> no caching for all form controllers).
119:             */
120:            public AbstractWizardFormController() {
121:                // AbstractFormController sets default cache seconds to 0.
122:                super ();
123:
124:                // Always needs session to keep data from all pages.
125:                setSessionForm(true);
126:
127:                // Never validate everything on binding ->
128:                // wizards validate individual pages.
129:                setValidateOnBinding(false);
130:            }
131:
132:            /**
133:             * Set the wizard pages, i.e. the view names for the pages.
134:             * The array index is interpreted as page number.
135:             * @param pages view names for the pages
136:             */
137:            public final void setPages(String[] pages) {
138:                if (pages == null || pages.length == 0) {
139:                    throw new IllegalArgumentException(
140:                            "No wizard pages defined");
141:                }
142:                this .pages = pages;
143:            }
144:
145:            /**
146:             * Return the wizard pages, i.e. the view names for the pages.
147:             * The array index corresponds to the page number.
148:             * <p>Note that a concrete wizard form controller might override
149:             * {@link #getViewName(HttpServletRequest, Object, int)} to
150:             * determine the view name for each page dynamically.
151:             * @see #getViewName(javax.servlet.http.HttpServletRequest, Object, int)
152:             */
153:            public final String[] getPages() {
154:                return pages;
155:            }
156:
157:            /**
158:             * Return the number of wizard pages.
159:             * Useful to check whether the last page has been reached.
160:             * <p>Note that a concrete wizard form controller might override
161:             * {@link #getPageCount(HttpServletRequest, Object)} to determine
162:             * the page count dynamically. The default implementation of that extended
163:             * <code>getPageCount</code> variant returns the static page count as
164:             * determined by this <code>getPageCount()</code> method.
165:             * @see #getPageCount(javax.servlet.http.HttpServletRequest, Object)
166:             */
167:            protected final int getPageCount() {
168:                return this .pages.length;
169:            }
170:
171:            /**
172:             * Set the name of the page attribute in the model, containing
173:             * an Integer with the current page number.
174:             * <p>This will be necessary for single views rendering multiple view pages.
175:             * It also allows for specifying the optional "_page" parameter.
176:             * @param pageAttribute name of the page attribute
177:             * @see #PARAM_PAGE
178:             */
179:            public final void setPageAttribute(String pageAttribute) {
180:                this .pageAttribute = pageAttribute;
181:            }
182:
183:            /**
184:             * Return the name of the page attribute in the model.
185:             */
186:            public final String getPageAttribute() {
187:                return pageAttribute;
188:            }
189:
190:            /**
191:             * Set if "dirty back" is allowed, that is, if moving to a former wizard
192:             * page is allowed in case of validation errors for the current page.
193:             * @param allowDirtyBack if "dirty back" is allowed
194:             */
195:            public final void setAllowDirtyBack(boolean allowDirtyBack) {
196:                this .allowDirtyBack = allowDirtyBack;
197:            }
198:
199:            /**
200:             * Return whether "dirty back" is allowed.
201:             */
202:            public final boolean isAllowDirtyBack() {
203:                return allowDirtyBack;
204:            }
205:
206:            /**
207:             * Set if "dirty forward" is allowed, that is, if moving to a later wizard
208:             * page is allowed in case of validation errors for the current page.
209:             * @param allowDirtyForward if "dirty forward" is allowed
210:             */
211:            public final void setAllowDirtyForward(boolean allowDirtyForward) {
212:                this .allowDirtyForward = allowDirtyForward;
213:            }
214:
215:            /**
216:             * Return whether "dirty forward" is allowed.
217:             */
218:            public final boolean isAllowDirtyForward() {
219:                return allowDirtyForward;
220:            }
221:
222:            /**
223:             * Calls page-specific onBindAndValidate method.
224:             */
225:            protected final void onBindAndValidate(HttpServletRequest request,
226:                    Object command, BindException errors) throws Exception {
227:
228:                onBindAndValidate(request, command, errors,
229:                        getCurrentPage(request));
230:            }
231:
232:            /**
233:             * Callback for custom post-processing in terms of binding and validation.
234:             * Called on each submit, after standard binding but before page-specific
235:             * validation of this wizard form controller.
236:             * <p>Note: AbstractWizardFormController does not perform standand
237:             * validation on binding but rather applies page-specific validation
238:             * on processing the form submission.
239:             * @param request current HTTP request
240:             * @param command bound command
241:             * @param errors Errors instance for additional custom validation
242:             * @param page current wizard page
243:             * @throws Exception in case of invalid state or arguments
244:             * @see #bindAndValidate
245:             * @see #processFormSubmission
246:             * @see org.springframework.validation.Errors
247:             */
248:            protected void onBindAndValidate(HttpServletRequest request,
249:                    Object command, BindException errors, int page)
250:                    throws Exception {
251:            }
252:
253:            /**
254:             * Consider an explicit finish or cancel request as a form submission too.
255:             * @see #isFinishRequest(javax.servlet.http.HttpServletRequest)
256:             * @see #isCancelRequest(javax.servlet.http.HttpServletRequest)
257:             */
258:            protected boolean isFormSubmission(HttpServletRequest request) {
259:                return super .isFormSubmission(request)
260:                        || isFinishRequest(request) || isCancelRequest(request);
261:            }
262:
263:            /**
264:             * Calls page-specific referenceData method.
265:             */
266:            protected final Map referenceData(HttpServletRequest request,
267:                    Object command, Errors errors) throws Exception {
268:
269:                return referenceData(request, command, errors,
270:                        getCurrentPage(request));
271:            }
272:
273:            /**
274:             * Create a reference data map for the given request, consisting of
275:             * bean name/bean instance pairs as expected by ModelAndView.
276:             * <p>The default implementation delegates to referenceData(HttpServletRequest, int).
277:             * Subclasses can override this to set reference data used in the view.
278:             * @param request current HTTP request
279:             * @param command form object with request parameters bound onto it
280:             * @param errors validation errors holder
281:             * @param page current wizard page
282:             * @return a Map with reference data entries, or <code>null</code> if none
283:             * @throws Exception in case of invalid state or arguments
284:             * @see #referenceData(HttpServletRequest, int)
285:             * @see ModelAndView
286:             */
287:            protected Map referenceData(HttpServletRequest request,
288:                    Object command, Errors errors, int page) throws Exception {
289:
290:                return referenceData(request, page);
291:            }
292:
293:            /**
294:             * Create a reference data map for the given request, consisting of
295:             * bean name/bean instance pairs as expected by ModelAndView.
296:             * <p>The default implementation returns <code>null</code>.
297:             * Subclasses can override this to set reference data used in the view.
298:             * @param request current HTTP request
299:             * @param page current wizard page
300:             * @return a Map with reference data entries, or <code>null</code> if none
301:             * @throws Exception in case of invalid state or arguments
302:             * @see ModelAndView
303:             */
304:            protected Map referenceData(HttpServletRequest request, int page)
305:                    throws Exception {
306:                return null;
307:            }
308:
309:            /**
310:             * Show first page as form view.
311:             */
312:            protected final ModelAndView showForm(HttpServletRequest request,
313:                    HttpServletResponse response, BindException errors)
314:                    throws Exception {
315:
316:                return showPage(request, errors, getInitialPage(request, errors
317:                        .getTarget()));
318:            }
319:
320:            /**
321:             * Prepare the form model and view, including reference and error data,
322:             * for the given page. Can be used in {@link #processFinish} implementations,
323:             * to show the corresponding page in case of validation errors.
324:             * @param request current HTTP request
325:             * @param errors validation errors holder
326:             * @param page number of page to show
327:             * @return the prepared form view
328:             * @throws Exception in case of invalid state or arguments
329:             */
330:            protected final ModelAndView showPage(HttpServletRequest request,
331:                    BindException errors, int page) throws Exception {
332:
333:                if (page >= 0
334:                        && page < getPageCount(request, errors.getTarget())) {
335:                    if (logger.isDebugEnabled()) {
336:                        logger.debug("Showing wizard page " + page
337:                                + " for form bean '" + getCommandName() + "'");
338:                    }
339:
340:                    // Set page session attribute, expose overriding request attribute.
341:                    Integer pageInteger = new Integer(page);
342:                    String pageAttrName = getPageSessionAttributeName(request);
343:                    if (isSessionForm()) {
344:                        if (logger.isDebugEnabled()) {
345:                            logger.debug("Setting page session attribute ["
346:                                    + pageAttrName + "] to: " + pageInteger);
347:                        }
348:                        request.getSession().setAttribute(pageAttrName,
349:                                pageInteger);
350:                    }
351:                    request.setAttribute(pageAttrName, pageInteger);
352:
353:                    // Set page request attribute for evaluation by views.
354:                    Map controlModel = new HashMap();
355:                    if (this .pageAttribute != null) {
356:                        controlModel.put(this .pageAttribute, new Integer(page));
357:                    }
358:                    String viewName = getViewName(request, errors.getTarget(),
359:                            page);
360:                    return showForm(request, errors, viewName, controlModel);
361:                }
362:
363:                else {
364:                    throw new ServletException("Invalid wizard page number: "
365:                            + page);
366:                }
367:            }
368:
369:            /**
370:             * Return the page count for this wizard form controller.
371:             * The default implementation delegates to {@link #getPageCount()}.
372:             * <p>Can be overridden to dynamically adapt the page count.
373:             * @param request current HTTP request
374:             * @param command the command object as returned by formBackingObject
375:             * @return the current page count
376:             * @see #getPageCount
377:             */
378:            protected int getPageCount(HttpServletRequest request,
379:                    Object command) {
380:                return getPageCount();
381:            }
382:
383:            /**
384:             * Return the name of the view for the specified page of this wizard form controller.
385:             * <p>The default implementation takes the view name from the {@link #getPages()} array.
386:             * <p>Can be overridden to dynamically switch the page view or to return view names
387:             * for dynamically defined pages.
388:             * @param request current HTTP request
389:             * @param command the command object as returned by formBackingObject
390:             * @return the current page count
391:             * @see #getPageCount
392:             */
393:            protected String getViewName(HttpServletRequest request,
394:                    Object command, int page) {
395:                return getPages()[page];
396:            }
397:
398:            /**
399:             * Return the initial page of the wizard, that is, the page shown at wizard startup.
400:             * <p>The default implementation delegates to {@link #getInitialPage(HttpServletRequest)}.
401:             * @param request current HTTP request
402:             * @param command the command object as returned by formBackingObject
403:             * @return the initial page number
404:             * @see #getInitialPage(HttpServletRequest)
405:             * @see #formBackingObject
406:             */
407:            protected int getInitialPage(HttpServletRequest request,
408:                    Object command) {
409:                return getInitialPage(request);
410:            }
411:
412:            /**
413:             * Return the initial page of the wizard, that is, the page shown at wizard startup.
414:             * <p>The default implementation returns 0 for first page.
415:             * @param request current HTTP request
416:             * @return the initial page number
417:             */
418:            protected int getInitialPage(HttpServletRequest request) {
419:                return 0;
420:            }
421:
422:            /**
423:             * Return the name of the HttpSession attribute that holds the page object
424:             * for this wizard form controller.
425:             * <p>The default implementation delegates to the {@link #getPageSessionAttributeName()}
426:             * variant without arguments.
427:             * @param request current HTTP request
428:             * @return the name of the form session attribute, or <code>null</code> if not in session form mode
429:             * @see #getPageSessionAttributeName
430:             * @see #getFormSessionAttributeName(javax.servlet.http.HttpServletRequest)
431:             * @see javax.servlet.http.HttpSession#getAttribute
432:             */
433:            protected String getPageSessionAttributeName(
434:                    HttpServletRequest request) {
435:                return getPageSessionAttributeName();
436:            }
437:
438:            /**
439:             * Return the name of the HttpSession attribute that holds the page object
440:             * for this wizard form controller.
441:             * <p>Default is an internal name, of no relevance to applications, as the form
442:             * session attribute is not usually accessed directly. Can be overridden to use
443:             * an application-specific attribute name, which allows other code to access
444:             * the session attribute directly.
445:             * @return the name of the page session attribute
446:             * @see #getFormSessionAttributeName
447:             * @see javax.servlet.http.HttpSession#getAttribute
448:             */
449:            protected String getPageSessionAttributeName() {
450:                return getClass().getName() + ".PAGE." + getCommandName();
451:            }
452:
453:            /**
454:             * Handle an invalid submit request, e.g. when in session form mode but no form object
455:             * was found in the session (like in case of an invalid resubmit by the browser).
456:             * <p>The default implementation for wizard form controllers simply shows the initial page
457:             * of a new wizard form. If you want to show some "invalid submit" message, you need
458:             * to override this method.
459:             * @param request current HTTP request
460:             * @param response current HTTP response
461:             * @return a prepared view, or <code>null</code> if handled directly
462:             * @throws Exception in case of errors
463:             * @see #showNewForm
464:             * @see #setBindOnNewForm
465:             */
466:            protected ModelAndView handleInvalidSubmit(
467:                    HttpServletRequest request, HttpServletResponse response)
468:                    throws Exception {
469:
470:                return showNewForm(request, response);
471:            }
472:
473:            /**
474:             * Apply wizard workflow: finish, cancel, page change.
475:             */
476:            protected final ModelAndView processFormSubmission(
477:                    HttpServletRequest request, HttpServletResponse response,
478:                    Object command, BindException errors) throws Exception {
479:
480:                int currentPage = getCurrentPage(request);
481:                // Remove page session attribute, provide copy as request attribute.
482:                String pageAttrName = getPageSessionAttributeName(request);
483:                if (isSessionForm()) {
484:                    if (logger.isDebugEnabled()) {
485:                        logger.debug("Removing page session attribute ["
486:                                + pageAttrName + "]");
487:                    }
488:                    request.getSession().removeAttribute(pageAttrName);
489:                }
490:                request.setAttribute(pageAttrName, new Integer(currentPage));
491:
492:                // cancel?
493:                if (isCancelRequest(request)) {
494:                    if (logger.isDebugEnabled()) {
495:                        logger.debug("Cancelling wizard for form bean '"
496:                                + getCommandName() + "'");
497:                    }
498:                    return processCancel(request, response, command, errors);
499:                }
500:
501:                // finish?
502:                if (isFinishRequest(request)) {
503:                    if (logger.isDebugEnabled()) {
504:                        logger.debug("Finishing wizard for form bean '"
505:                                + getCommandName() + "'");
506:                    }
507:                    return validatePagesAndFinish(request, response, command,
508:                            errors, currentPage);
509:                }
510:
511:                // Normal submit: validate current page and show specified target page.
512:                if (!suppressValidation(request, command, errors)) {
513:                    if (logger.isDebugEnabled()) {
514:                        logger.debug("Validating wizard page " + currentPage
515:                                + " for form bean '" + getCommandName() + "'");
516:                    }
517:                    validatePage(command, errors, currentPage, false);
518:                }
519:
520:                // Give subclasses a change to perform custom post-procession
521:                // of the current page and its command object.
522:                postProcessPage(request, command, errors, currentPage);
523:
524:                int targetPage = getTargetPage(request, command, errors,
525:                        currentPage);
526:                if (logger.isDebugEnabled()) {
527:                    logger.debug("Target page " + targetPage + " requested");
528:                }
529:                if (targetPage != currentPage) {
530:                    if (!errors.hasErrors()
531:                            || (this .allowDirtyBack && targetPage < currentPage)
532:                            || (this .allowDirtyForward && targetPage > currentPage)) {
533:                        // Allowed to go to target page.
534:                        return showPage(request, errors, targetPage);
535:                    }
536:                }
537:
538:                // Show current page again.
539:                return showPage(request, errors, currentPage);
540:            }
541:
542:            /**
543:             * Return the current page number. Used by processFormSubmission.
544:             * <p>The default implementation checks the page session attribute.
545:             * Subclasses can override this for customized page determination.
546:             * @see #processFormSubmission
547:             * @see #getPageSessionAttributeName
548:             */
549:            protected int getCurrentPage(HttpServletRequest request) {
550:                // Check for overriding attribute in request.
551:                String pageAttrName = getPageSessionAttributeName(request);
552:                Integer pageAttr = (Integer) request.getAttribute(pageAttrName);
553:                if (pageAttr != null) {
554:                    return pageAttr.intValue();
555:                }
556:                // Check for explicit request parameter.
557:                String pageParam = request.getParameter(PARAM_PAGE);
558:                if (pageParam != null) {
559:                    return Integer.parseInt(pageParam);
560:                }
561:                // Check for original attribute in session.
562:                if (isSessionForm()) {
563:                    pageAttr = (Integer) request.getSession().getAttribute(
564:                            pageAttrName);
565:                    if (pageAttr != null) {
566:                        return pageAttr.intValue();
567:                    }
568:                }
569:                throw new IllegalStateException("Page attribute ["
570:                        + pageAttrName
571:                        + "] neither found in session nor in request");
572:            }
573:
574:            /**
575:             * Determine whether the incoming request is a request to finish the
576:             * processing of the current form.
577:             * <p>By default, this method returns <code>true</code> if a parameter
578:             * matching the "_finish" key is present in the request, otherwise it
579:             * returns <code>false</code>. Subclasses may override this method
580:             * to provide custom logic to detect a finish request.
581:             * <p>The parameter is recognized both when sent as a plain parameter
582:             * ("_finish") or when triggered by an image button ("_finish.x").
583:             * @param request current HTTP request
584:             * @see #PARAM_FINISH
585:             */
586:            protected boolean isFinishRequest(HttpServletRequest request) {
587:                return WebUtils.hasSubmitParameter(request, PARAM_FINISH);
588:            }
589:
590:            /**
591:             * Determine whether the incoming request is a request to cancel the
592:             * processing of the current form.
593:             * <p>By default, this method returns <code>true</code> if a parameter
594:             * matching the "_cancel" key is present in the request, otherwise it
595:             * returns <code>false</code>. Subclasses may override this method
596:             * to provide custom logic to detect a cancel request.
597:             * <p>The parameter is recognized both when sent as a plain parameter
598:             * ("_cancel") or when triggered by an image button ("_cancel.x").
599:             * @param request current HTTP request
600:             * @see #PARAM_CANCEL
601:             */
602:            protected boolean isCancelRequest(HttpServletRequest request) {
603:                return WebUtils.hasSubmitParameter(request, PARAM_CANCEL);
604:            }
605:
606:            /**
607:             * Return the target page specified in the request.
608:             * <p>The default implementation delegates to {@link #getTargetPage(HttpServletRequest, int)}.
609:             * Subclasses can override this for customized target page determination.
610:             * @param request current HTTP request
611:             * @param command form object with request parameters bound onto it
612:             * @param errors validation errors holder
613:             * @param currentPage the current page, to be returned as fallback
614:             * if no target page specified
615:             * @return the page specified in the request, or current page if not found
616:             * @see #getTargetPage(HttpServletRequest, int)
617:             */
618:            protected int getTargetPage(HttpServletRequest request,
619:                    Object command, Errors errors, int currentPage) {
620:                return getTargetPage(request, currentPage);
621:            }
622:
623:            /**
624:             * Return the target page specified in the request.
625:             * <p>The default implementation examines "_target" parameter (e.g. "_target1").
626:             * Subclasses can override this for customized target page determination.
627:             * @param request current HTTP request
628:             * @param currentPage the current page, to be returned as fallback
629:             * if no target page specified
630:             * @return the page specified in the request, or current page if not found
631:             * @see #PARAM_TARGET
632:             */
633:            protected int getTargetPage(HttpServletRequest request,
634:                    int currentPage) {
635:                Enumeration paramNames = request.getParameterNames();
636:                while (paramNames.hasMoreElements()) {
637:                    String paramName = (String) paramNames.nextElement();
638:                    if (paramName.startsWith(PARAM_TARGET)) {
639:                        for (int i = 0; i < WebUtils.SUBMIT_IMAGE_SUFFIXES.length; i++) {
640:                            String suffix = WebUtils.SUBMIT_IMAGE_SUFFIXES[i];
641:                            if (paramName.endsWith(suffix)) {
642:                                paramName = paramName.substring(0, paramName
643:                                        .length()
644:                                        - suffix.length());
645:                            }
646:                        }
647:                        return Integer.parseInt(paramName
648:                                .substring(PARAM_TARGET.length()));
649:                    }
650:                }
651:                return currentPage;
652:            }
653:
654:            /**
655:             * Validate all pages and process finish.
656:             * If there are page validation errors, show the corresponding view page.
657:             */
658:            private ModelAndView validatePagesAndFinish(
659:                    HttpServletRequest request, HttpServletResponse response,
660:                    Object command, BindException errors, int currentPage)
661:                    throws Exception {
662:
663:                // In case of binding errors -> show current page.
664:                if (errors.hasErrors()) {
665:                    return showPage(request, errors, currentPage);
666:                }
667:
668:                if (!suppressValidation(request, command, errors)) {
669:                    // In case of remaining errors on a page -> show the page.
670:                    for (int page = 0; page < getPageCount(request, command); page++) {
671:                        validatePage(command, errors, page, true);
672:                        if (errors.hasErrors()) {
673:                            return showPage(request, errors, page);
674:                        }
675:                    }
676:                }
677:
678:                // No remaining errors -> proceed with finish.
679:                return processFinish(request, response, command, errors);
680:            }
681:
682:            /**
683:             * Template method for custom validation logic for individual pages.
684:             * The default implementation calls {@link #validatePage(Object, Errors, int)}.
685:             * <p>Implementations will typically call fine-granular <code>validateXXX</code>
686:             * methods of this instance's Validator, combining them to validation of the
687:             * corresponding pages. The Validator's default <code>validate</code> method
688:             * will not be called by a wizard form controller!
689:             * @param command form object with the current wizard state
690:             * @param errors validation errors holder
691:             * @param page number of page to validate
692:             * @param finish whether this method is called during final revalidation on finish
693:             * (else, it is called for validating the current page)
694:             * @see #validatePage(Object, Errors, int)
695:             * @see org.springframework.validation.Validator#validate
696:             */
697:            protected void validatePage(Object command, Errors errors,
698:                    int page, boolean finish) {
699:                validatePage(command, errors, page);
700:            }
701:
702:            /**
703:             * Template method for custom validation logic for individual pages.
704:             * The default implementation is empty.
705:             * <p>Implementations will typically call fine-granular validateXXX methods of this
706:             * instance's validator, combining them to validation of the corresponding pages.
707:             * The validator's default <code>validate</code> method will not be called by a
708:             * wizard form controller!
709:             * @param command form object with the current wizard state
710:             * @param errors validation errors holder
711:             * @param page number of page to validate
712:             * @see org.springframework.validation.Validator#validate
713:             */
714:            protected void validatePage(Object command, Errors errors, int page) {
715:            }
716:
717:            /**
718:             * Post-process the given page after binding and validation, potentially
719:             * updating its command object. The passed-in request might contain special
720:             * parameters sent by the page.
721:             * <p>Only invoked when displaying another page or the same page again,
722:             * not when finishing or cancelling.
723:             * @param request current HTTP request
724:             * @param command form object with request parameters bound onto it
725:             * @param errors validation errors holder
726:             * @param page number of page to post-process
727:             * @throws Exception in case of invalid state or arguments
728:             */
729:            protected void postProcessPage(HttpServletRequest request,
730:                    Object command, Errors errors, int page) throws Exception {
731:            }
732:
733:            /**
734:             * Template method for processing the final action of this wizard.
735:             * <p>Call <code>errors.getModel()</code> to populate the ModelAndView model
736:             * with the command and the Errors instance, under the specified command name,
737:             * as expected by the "spring:bind" tag.
738:             * <p>You can call the {@link #showPage} method to return back to the wizard,
739:             * in case of last-minute validation errors having been found that you would
740:             * like to present to the user within the original wizard form.
741:             * @param request current HTTP request
742:             * @param response current HTTP response
743:             * @param command form object with the current wizard state
744:             * @param errors validation errors holder
745:             * @return the finish view
746:             * @throws Exception in case of invalid state or arguments
747:             * @see org.springframework.validation.Errors
748:             * @see org.springframework.validation.BindException#getModel
749:             * @see #showPage(javax.servlet.http.HttpServletRequest, org.springframework.validation.BindException, int)
750:             */
751:            protected abstract ModelAndView processFinish(
752:                    HttpServletRequest request, HttpServletResponse response,
753:                    Object command, BindException errors) throws Exception;
754:
755:            /**
756:             * Template method for processing the cancel action of this wizard.
757:             * <p>The default implementation throws a ServletException, saying that a cancel
758:             * operation is not supported by this controller. Thus, you do not need to
759:             * implement this template method if you do not support a cancel operation.
760:             * <p>Call <code>errors.getModel()</code> to populate the ModelAndView model
761:             * with the command and the Errors instance, under the specified command name,
762:             * as expected by the "spring:bind" tag.
763:             * @param request current HTTP request
764:             * @param response current HTTP response
765:             * @param command form object with the current wizard state
766:             * @param errors Errors instance containing errors
767:             * @return the cancellation view
768:             * @throws Exception in case of invalid state or arguments
769:             * @see org.springframework.validation.Errors
770:             * @see org.springframework.validation.BindException#getModel
771:             */
772:            protected ModelAndView processCancel(HttpServletRequest request,
773:                    HttpServletResponse response, Object command,
774:                    BindException errors) throws Exception {
775:
776:                throw new ServletException("Wizard form controller class ["
777:                        + getClass().getName()
778:                        + "] does not support a cancel operation");
779:            }
780:
781:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.