1 16 17 package org.springframework.web.portlet.mvc; 18 19 import java.util.Enumeration ; 20 import java.util.HashMap ; 21 import java.util.Iterator ; 22 import java.util.Map ; 23 24 import javax.portlet.ActionRequest; 25 import javax.portlet.ActionResponse; 26 import javax.portlet.PortletException; 27 import javax.portlet.PortletRequest; 28 import javax.portlet.RenderRequest; 29 import javax.portlet.RenderResponse; 30 31 import org.springframework.validation.BindException; 32 import org.springframework.validation.Errors; 33 import org.springframework.web.portlet.ModelAndView; 34 import org.springframework.web.portlet.util.PortletUtils; 35 import org.springframework.web.util.WebUtils; 36 37 89 public abstract class AbstractWizardFormController extends AbstractFormController { 90 91 95 public static final String PARAM_FINISH = "_finish"; 96 97 101 public static final String PARAM_CANCEL = "_cancel"; 102 103 107 public static final String PARAM_TARGET = "_target"; 108 109 114 public static final String PARAM_PAGE = "_page"; 115 116 117 private String [] pages; 118 119 private String pageAttribute; 120 121 private boolean allowDirtyBack = true; 122 123 private boolean allowDirtyForward = false; 124 125 126 132 public AbstractWizardFormController() { 133 super(); 135 136 setSessionForm(true); 138 139 setValidateOnBinding(false); 142 } 143 144 149 public final void setPages(String [] pages) { 150 if (pages == null || pages.length == 0) { 151 throw new IllegalArgumentException ("No wizard pages defined"); 152 } 153 this.pages = pages; 154 } 155 156 164 public final String [] getPages() { 165 return pages; 166 } 167 168 176 protected final int getPageCount() { 177 return this.pages.length; 178 } 179 180 188 public final void setPageAttribute(String pageAttribute) { 189 this.pageAttribute = pageAttribute; 190 } 191 192 195 public final String getPageAttribute() { 196 return pageAttribute; 197 } 198 199 204 public final void setAllowDirtyBack(boolean allowDirtyBack) { 205 this.allowDirtyBack = allowDirtyBack; 206 } 207 208 211 public final boolean isAllowDirtyBack() { 212 return allowDirtyBack; 213 } 214 215 220 public final void setAllowDirtyForward(boolean allowDirtyForward) { 221 this.allowDirtyForward = allowDirtyForward; 222 } 223 224 227 public final boolean isAllowDirtyForward() { 228 return allowDirtyForward; 229 } 230 231 232 235 protected final void onBindAndValidate(PortletRequest request, Object command, BindException errors) 236 throws Exception { 237 238 onBindAndValidate(request, command, errors, getCurrentPage(request)); 239 } 240 241 257 protected void onBindAndValidate(PortletRequest request, Object command, BindException errors, int page) 258 throws Exception { 259 } 260 261 266 protected boolean isFormSubmission(PortletRequest request) { 267 return super.isFormSubmission(request) || isFinishRequest(request) || isCancelRequest(request); 268 } 269 270 273 protected final Map referenceData(PortletRequest request, Object command, Errors errors) 274 throws Exception { 275 276 return referenceData(request, command, errors, getCurrentPage(request)); 277 } 278 279 293 protected Map referenceData(PortletRequest request, Object command, Errors errors, int page) 294 throws Exception { 295 296 return referenceData(request, page); 297 } 298 299 310 protected Map referenceData(PortletRequest request, int page) throws Exception { 311 return null; 312 } 313 314 315 318 protected final ModelAndView showForm( 319 RenderRequest request, RenderResponse response, BindException errors) throws Exception { 320 321 return showPage(request, errors, getInitialPage(request, errors.getTarget())); 322 } 323 324 334 protected final ModelAndView showPage(RenderRequest request, BindException errors, int page) 335 throws Exception { 336 337 if (page >= 0 && page < getPageCount(request, errors.getTarget())) { 338 if (logger.isDebugEnabled()) { 339 logger.debug("Showing wizard page " + page + " for form bean '" + getCommandName() + "'"); 340 } 341 342 Integer pageInteger = new Integer (page); 344 String pageAttrName = getPageSessionAttributeName(request); 345 if (isSessionForm()) { 346 if (logger.isDebugEnabled()) { 347 logger.debug("Setting page session attribute [" + pageAttrName + "] to: " + pageInteger); 348 } 349 request.getPortletSession().setAttribute(pageAttrName, pageInteger); 350 } 351 request.setAttribute(pageAttrName, pageInteger); 352 353 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(), page); 359 return showForm(request, errors, viewName, controlModel); 360 } 361 362 else { 363 throw new PortletException("Invalid wizard page number: " + page); 364 } 365 } 366 367 376 protected int getPageCount(PortletRequest request, Object command) { 377 return getPageCount(); 378 } 379 380 390 protected String getViewName(PortletRequest request, Object command, int page) { 391 return getPages()[page]; 392 } 393 394 403 protected int getInitialPage(PortletRequest request, Object command) { 404 return getInitialPage(request); 405 } 406 407 413 protected int getInitialPage(PortletRequest request) { 414 return 0; 415 } 416 417 428 protected String getPageSessionAttributeName(PortletRequest request) { 429 return getPageSessionAttributeName(); 430 } 431 432 443 protected String getPageSessionAttributeName() { 444 return getClass().getName() + ".PAGE." + getCommandName(); 445 } 446 447 455 protected void setPageRenderParameter(ActionResponse response, int page) { 456 if (logger.isDebugEnabled()) 457 logger.debug("Setting page number render parameter [" + PARAM_PAGE + "] to [" + page + "]"); 458 try { 459 response.setRenderParameter(PARAM_PAGE, new Integer (page).toString()); 460 } 461 catch (IllegalStateException ex) { 462 } 464 } 465 466 477 protected void setTargetRenderParameter(ActionRequest request, ActionResponse response) { 478 try { 479 Iterator it = PortletUtils.getParametersStartingWith(request, PARAM_TARGET).entrySet().iterator(); 480 while (it.hasNext()) { 481 Map.Entry entry = (Map.Entry ) it.next(); 482 String param = PARAM_TARGET + (String ) entry.getKey(); 483 Object value = entry.getValue(); 484 if (logger.isDebugEnabled()) logger.debug("Setting target render parameter [" + param + "]"); 485 if (value instanceof String ) response.setRenderParameter(param, (String ) value); 486 if (value instanceof String []) response.setRenderParameter(param, (String []) value); 487 } 488 } 489 catch (IllegalStateException ex) { 490 } 492 } 493 494 504 protected void setFinishRenderParameter(ActionRequest request, ActionResponse response) { 505 if (logger.isDebugEnabled()) 506 logger.debug("Setting cancel render parameter [" + PARAM_FINISH + "]"); 507 try { 508 String name = PortletUtils.getSubmitParameter(request, PARAM_FINISH); 509 if (name != null) 510 response.setRenderParameter(name, request.getParameter(name)); 511 } 512 catch (IllegalStateException ex) { 513 } 515 } 516 517 527 protected void setCancelRenderParameter(ActionRequest request, ActionResponse response) { 528 if (logger.isDebugEnabled()) 529 logger.debug("Setting cancel render parameter [" + PARAM_CANCEL + "]"); 530 try { 531 String name = PortletUtils.getSubmitParameter(request, PARAM_CANCEL); 532 if (name != null) 533 response.setRenderParameter(name, request.getParameter(name)); 534 } 535 catch (IllegalStateException ex) { 536 } 538 } 539 540 554 protected ModelAndView renderInvalidSubmit(RenderRequest request, RenderResponse response) 555 throws Exception { 556 557 return showNewForm(request, response); 558 } 559 560 571 protected void handleInvalidSubmit(ActionRequest request, ActionResponse response) throws Exception { 572 } 573 574 578 protected final ModelAndView renderFormSubmission(RenderRequest request, RenderResponse response, Object command, BindException errors) 579 throws Exception { 580 581 int currentPage = getCurrentPage(request); 582 String pageAttrName = getPageSessionAttributeName(request); 583 request.setAttribute(pageAttrName, new Integer (currentPage)); 584 585 if (isCancelRequest(request)) { 587 if (logger.isDebugEnabled()) { 588 logger.debug("Cancelling wizard for form bean '" + getCommandName() + "'"); 589 } 590 return renderCancel(request, response, command, errors); 591 } 592 593 if (isFinishRequest(request)) { 595 if (logger.isDebugEnabled()) { 596 logger.debug("Finishing wizard for form bean '" + getCommandName() + "'"); 597 } 598 return renderValidatePagesAndFinish(request, response, command, errors, currentPage); 599 } 600 601 int targetPage = getTargetPage(request, command, errors, currentPage); 603 if (logger.isDebugEnabled()) { 604 logger.debug("Target page " + targetPage + " requested"); 605 } 606 if (targetPage != currentPage) { 607 if (!errors.hasErrors() || (this.allowDirtyBack && targetPage < currentPage) || 608 (this.allowDirtyForward && targetPage > currentPage)) { 609 return showPage(request, errors, targetPage); 611 } 612 } 613 614 return showPage(request, errors, currentPage); 616 } 617 618 619 623 protected final void processFormSubmission( 624 ActionRequest request, ActionResponse response, Object command, BindException errors) 625 throws Exception { 626 627 int currentPage = getCurrentPage(request); 628 String pageAttrName = getPageSessionAttributeName(request); 630 if (isSessionForm()) { 631 if (logger.isDebugEnabled()) { 632 logger.debug("Removing page session attribute [" + pageAttrName + "]"); 633 } 634 request.getPortletSession().removeAttribute(pageAttrName); 635 } 636 request.setAttribute(pageAttrName, new Integer (currentPage)); 637 638 if (isCancelRequest(request)) { 640 if (logger.isDebugEnabled()) { 641 logger.debug("Cancelling wizard for form bean '" + getCommandName() + "'"); 642 } 643 setPageRenderParameter(response, currentPage); 644 setCancelRenderParameter(request, response); 645 processCancel(request, response, command, errors); 646 return; 647 } 648 649 if (isFinishRequest(request)) { 651 if (logger.isDebugEnabled()) { 652 logger.debug("Finishing wizard for form bean '" + getCommandName() + "'"); 653 } 654 if (!isRedirectAction()) { 655 setPageRenderParameter(response, currentPage); 656 setFinishRenderParameter(request, response); 657 } 658 validatePagesAndFinish(request, response, command, errors, currentPage); 659 return; 660 } 661 662 if (!suppressValidation(request)) { 664 if (logger.isDebugEnabled()) { 665 logger.debug("Validating wizard page " + currentPage + " for form bean '" + getCommandName() + "'"); 666 } 667 validatePage(command, errors, currentPage, false); 668 } 669 670 setPageRenderParameter(response, currentPage); 671 setTargetRenderParameter(request, response); 672 passRenderParameters(request, response); 673 674 postProcessPage(request, command, errors, currentPage); 677 678 } 679 680 687 protected int getCurrentPage(PortletRequest request) { 688 String pageAttrName = getPageSessionAttributeName(request); 690 Integer pageAttr = (Integer ) request.getAttribute(pageAttrName); 691 if (pageAttr != null) { 692 return pageAttr.intValue(); 693 } 694 String pageParam = request.getParameter(PARAM_PAGE); 696 if (pageParam != null) { 697 return Integer.parseInt(pageParam); 698 } 699 if (isSessionForm()) { 701 pageAttr = (Integer ) request.getPortletSession().getAttribute(pageAttrName); 702 if (pageAttr != null) { 703 return pageAttr.intValue(); 704 } 705 } 706 throw new IllegalStateException ("Page attribute [" + pageAttrName + "] neither found in session nor in request"); 707 } 708 709 721 protected boolean isFinishRequest(PortletRequest request) { 722 return PortletUtils.hasSubmitParameter(request, PARAM_FINISH); 723 } 724 725 737 protected boolean isCancelRequest(PortletRequest request) { 738 return PortletUtils.hasSubmitParameter(request, PARAM_CANCEL); 739 } 740 741 754 protected int getTargetPage(PortletRequest request, Object command, Errors errors, int currentPage) { 755 return getTargetPage(request, currentPage); 756 } 757 758 768 protected int getTargetPage(PortletRequest request, int currentPage) { 769 Enumeration paramNames = request.getParameterNames(); 770 while (paramNames.hasMoreElements()) { 771 String paramName = (String ) paramNames.nextElement(); 772 if (paramName.startsWith(PARAM_TARGET)) { 773 for (int i = 0; i < WebUtils.SUBMIT_IMAGE_SUFFIXES.length; i++) { 774 String suffix = WebUtils.SUBMIT_IMAGE_SUFFIXES[i]; 775 if (paramName.endsWith(suffix)) { 776 paramName = paramName.substring(0, paramName.length() - suffix.length()); 777 } 778 } 779 return Integer.parseInt(paramName.substring(PARAM_TARGET.length())); 780 } 781 } 782 return currentPage; 783 } 784 785 790 private ModelAndView renderValidatePagesAndFinish( 791 RenderRequest request, RenderResponse response, Object command, BindException errors, int currentPage) 792 throws Exception { 793 794 if (errors.hasErrors()) 796 return showPage(request, errors, currentPage); 797 798 return renderFinish(request, response, command, errors); 800 } 801 802 807 private void validatePagesAndFinish( 808 ActionRequest request, ActionResponse response, Object command, BindException errors, int currentPage) 809 throws Exception { 810 811 if (errors.hasErrors()) { 813 setPageRenderParameter(response, currentPage); 814 passRenderParameters(request, response); 815 return; 816 } 817 818 if (!suppressValidation(request)) { 819 for (int page = 0; page < getPageCount(request, command); page++) { 821 validatePage(command, errors, page, true); 822 if (errors.hasErrors()) { 823 setPageRenderParameter(response, currentPage); 824 passRenderParameters(request, response); 825 return; 826 } 827 } 828 } 829 830 if (!isRedirectAction()) 832 setPageRenderParameter(response, currentPage); 833 processFinish(request, response, command, errors); 834 835 } 836 837 852 protected void validatePage(Object command, Errors errors, int page, boolean finish) { 853 validatePage(command, errors, page); 854 } 855 856 868 protected void validatePage(Object command, Errors errors, int page) { 869 } 870 871 883 protected void postProcessPage(ActionRequest request, Object command, Errors errors, int page) 884 throws Exception { 885 } 886 887 905 protected ModelAndView renderFinish( 906 RenderRequest request, RenderResponse response, Object command, BindException errors) 907 throws Exception { 908 909 throw new PortletException("Wizard form controller class [" + getClass().getName() + "] does not support a finish render request"); 910 } 911 912 925 protected void processFinish( 926 ActionRequest request, ActionResponse response, Object command, BindException errors) 927 throws Exception { 928 929 throw new PortletException( 930 "Wizard form controller class [" + getClass().getName() + "] does not support a finish action request"); 931 } 932 933 951 protected ModelAndView renderCancel( 952 RenderRequest request, RenderResponse response, Object command, BindException errors) 953 throws Exception { 954 955 throw new PortletException( 956 "Wizard form controller class [" + getClass().getName() + "] does not support a cancel render request"); 957 } 958 959 972 protected void processCancel( 973 ActionRequest request, ActionResponse response, Object command, BindException errors) 974 throws Exception { 975 976 throw new PortletException( 977 "Wizard form controller class [" + getClass().getName() + "] does not support a cancel action request"); 978 } 979 980 } 981 | Popular Tags |