/* * FormHandler.java * * This work is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This work is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * Copyright (c) 2004 Per Cederberg. All rights reserved. */ package org.liquidsite.core.web; /** * A form request handler. This class attempts to provide some * workflow support, by making initial request parameter analysis and * calling the appropriate event methods. A subclass should implement * the various event methods. * * @author Per Cederberg, <per at percederberg dot net> * @version 1.0 */ public abstract class FormHandler { /** * Processes the form request. This method is called for each * incoming request to the form workflow, including the first one * requesting presentation of the (first) form. This method * handles errors by calling the error event method. To handle * errors externally, use the processWithoutErrorHandling method * instead. * * @param request the request object * * @see #processWithoutErrorHandling */ public final void process(Request request) { try { processWithoutErrorHandling(request); } catch (FormHandlingException e) { workflowError(request, e); } } /** * Processes the form request. This method is called for each * incoming request to the form workflow, including the first one * requesting presentation of the (first) form. Note that this * method will not trigger the error event on error, but will * return an exception instead. * * @param request the request object * * @throws FormHandlingException if an error was encountered * while processing the form * * @see #process */ public final void processWithoutErrorHandling(Request request) throws FormHandlingException { String stepParam; String prevParam; int step; // Retrieve workflow parameters stepParam = request.getParameter("liquidsite.step", "0"); prevParam = request.getParameter("liquidsite.prev", ""); try { step = Integer.parseInt(stepParam); } catch (NumberFormatException e) { step = 0; } // Validate and handle form data if (step <= 0) { workflowEntered(request); step = 1; } else if (prevParam.equals("true")) { step--; } else { try { validate(request, step); step = handle(request, step); } catch (FormValidationException e) { request.setAttribute("error", e.getMessage()); } } // Display next form if (step <= 0) { workflowExited(request); display(request, 0); } else { display(request, step); } } /** * Displays a form for the specified workflow step. The special * workflow step zero (0) is used for indicating display of the * originating page outside the form workflow. Normally that * would cause a redirect. * * @param request the request object * @param step the workflow step, or zero (0) * * @throws FormHandlingException if an error was encountered * while processing the form */ protected abstract void display(Request request, int step) throws FormHandlingException; /** * Validates a form for the specified workflow step. If the form * validation fails in this step, the form page for the workflow * step will be displayed again with an 'error' attribute * containing the message in the validation exception. * * @param request the request object * @param step the workflow step * * @throws FormValidationException if the form request data * validation failed * @throws FormHandlingException if an error was encountered * while processing the form */ protected abstract void validate(Request request, int step) throws FormValidationException, FormHandlingException; /** * Handles a validated form for the specified workflow step. This * method returns the next workflow step, i.e. the step used when * calling the display method. If the special zero (0) workflow * step is returned, the workflow is assumed to have terminated. * Note that this method also allows additional validation to * occur. By returning the incoming workflow step number and * setting the appropriate request attributes the same results as * in the normal validate method can be achieved. For recoverable * errors, this is the recommended course of action. * * @param request the request object * @param step the workflow step * * @return the next workflow step, or * zero (0) if the workflow has finished * * @throws FormHandlingException if an error was encountered * while processing the form */ protected abstract int handle(Request request, int step) throws FormHandlingException; /** * This method is called when the user is entering the workflow. * This event can be used for handling object locking or * messaging related to the workflow. By default this method does * nothing. * * @param request the request object * * @throws FormHandlingException if an error was encountered * while processing the form */ protected void workflowEntered(Request request) throws FormHandlingException { // Nothing to do here, but subclasses may override this } /** * This method is called when the user is exiting the workflow. * This even is triggered either by finishing the complete * workflow, or by backing out to workflow step zero (0). This * event can be used for handling object locking or messaging * related to the workflow. By default this method does * nothing.<p> * * <strong>NOTE:</strong> This method will not be called when the * user exits the workflow in a non-standard way. Closing the * browser window, using back buttons or causing form handling * exceptions are all examples of when this method will NOT be * called. * * @param request the request object * * @throws FormHandlingException if an error was encountered * while processing the form */ protected void workflowExited(Request request) throws FormHandlingException { // Nothing to do here, but subclasses may override this } /** * This method is called when an error was encountered during the * processing. This event can be used for logging errors and * displaying a simple error page. By default this method does * nothing. * * @param request the request object * @param e the form handling exception */ protected void workflowError(Request request, FormHandlingException e) { // Nothing to do here, but subclasses may override this } }