fc.web.forms
Class Form

java.lang.Object
  extended by fc.web.forms.Form

public class Form
extends Object

Represents an HTML form. It is possible to instantiate a different form object per user and store each form in that users session scope. However, more typically, instances of this object are instantiated once per unique form and stored in web application scope.

Method in this class are thread safe since form processing is done entirely within various methods and the form processing results in the creation of seperate FormData objects for each request.

Various Fields can be added to the form at form creation time. Some fields (like Hidden can also be added per user/request, dynamically, to the FormData object. This is useful while saving some user or request specific information.

A form collects data from the front-end/web-client and often saves it to a back end database entity. Form data validation can be done in 2 ways:

  1. at the form level where the form collects data and validates it via validators associated with the form object.
  2. at the field level where the form itself does no higher level validation but populates a field and then asks that field to validate itself.
In both cases, any errors associated with the form can be shown back to the user. This framework allows both types of validation methods to be used. Using validation and/or showing validation errors is optional. This framework can simply be used to maintain form state and validation can be done via other ad-hoc code (outside of this framework) as needed.

An HTML form presented to the user can contain fields from more than 1 database table. For example, there could to 2 database tables, say "person" and "office" both with a "other" column. Since each field contained in the form object must have a unique name, there will be a name clash between the fields/attributes of the entities when 2 fields with the name "other" are added to the form.

There are 2 general approaches to solving this problem.

  1. Seperate database tables should be represented by seperate Form objects (all of which can be rendered in the same HTML document shown to the user). Different instances of form objects (say 1 per table) act as seperate name-spaces and fields having the same name can exist in these seperate instances. However, the dynamic server page where the form object is rendered/submitted has to obtain these seperate instances from the application object (or wherever all forms are stored) -- which adds some complexity.
  2. Create 1 instance of a form object containing fields from more than one table. In this case, some or all field names can be prepended (or suffixed) with the name of the database table. This removes any name clashes if done only for clashing fields; if done for every field may help in documenting which table that field belongs to. There is more typing involved with this approach.
Either of the above approaches is valid.

Sometimes, other methods need to obtain a field (for a particular table) by name. For example, the managers generated by Generate have a addValidators(form) method that extract the fields for a particular table and add validators to that field. This method in particular need to be passed either the appropriate form object in which that field exists (if there are multiple form objects) or in the case of only 1 form object, passed the prefix for that particular field, if that field was added with a prefix to it's name.


Field Summary
static List empty_list
           
static Map empty_map
           
 
Constructor Summary
Form(String name)
          Creates a new form with the specified name, method=POST and no action URL
Form(String name, String method, String actionURL)
          Creates a new form with logging to the default log retreived by Log.getDefault() and the default SubmitHackedHandler
Form(String name, String method, String actionURL, Log log)
           
Form(String name, String method, String actionURL, Log log, SubmitHackedHandler handler)
          Creates a new form with the specified name, method (get/post) and URL
 
Method Summary
 Form add(Dependency d)
          Adds the specified dependency to the form.
 Form add(Field field)
          Adds the specified element to the form.
 Form add(FieldRef ref)
          Adds a FieldRef to this Form.
 void addDynamicField(FormData fd, Hidden f)
          Adds a Hidden field to this form.
 void addError(FormData fd, String errorMessage)
          Convenience method that invokes addError with an empty validation errorKey.
 void addError(FormData fd, String errorKey, String errorMessage)
          Adds a form level validation error message.
 void addMessage(FormData fd, String key, String value)
          Adds an arbitrary message for this request.
 void addSubmitHackedHandler(SubmitHackedHandler handler)
           
 void addValidator(FormValidator validator)
          Adds a form level validator to this form.
 boolean containsField(String fieldName)
          Returns true if the form contains the specified field.
 void destroy()
          This method should be called when the form is removed from session or application scope.
 Field get(String name)
          Returns the form field with the specified name.
 String getActionURL()
          Returns the action URL string.
 Collection getAllFields()
          Returns a collection view of all the fields contained in this form.
 Checkbox getCheckbox(String name)
          Returns the field with the specific name as a Checkbox.
 CheckboxGroup getCheckboxGroup(String name)
          Returns the field with the specific name as a Checkbox.
 List getContaining(String name)
          Returns all the fields that contains the specified name.
 String getDisplayURL()
          Returns the display URL string.
 Hidden getDynamicField(FormData fd, String fieldName)
          Gets a Hidden field added to the form data object.
 Map getFieldErrors(FormData fd)
           
 FieldRef getFieldRef(String key)
          Returns the FieldRef with the specified key.
 Collection getFormErrorsCollection(FormData fd)
           
 List getFormErrorsFor(FormData fd, String formValidatorName)
          Returns a list containing all form-level errors for the specified validator.
 Hidden getHidden(String name)
          Returns the field with the specific name as a Hidden.
 String getMessage(FormData fd, String key)
          Retrieves a previously added message or null if the speccified form data was null or if the message was not found.
 String getName()
          Returns the name of this form
 Password getPassword(String name)
          Returns the field with the specific name as a Password.
 Radio getRadio(String name)
          Returns the field with the specific name as a Radio.
 RadioGroup getRadioGroup(String name)
          Returns the field with the specific name as a Checkbox.
 Select getSelect(String name)
          Returns the field with the specific name as a Select.
 Hidden getSubmittedField(javax.servlet.http.HttpServletRequest req, String name)
          Once the form is displayed to the user (with, say, hidden fields that were added dynamically for that request), then when that form is submitted, those dynamic fields can be retrieved via any of: the ServletRequest.getParameter(java.lang.String) method (often the easiest way) the #getSubmittedField(HttpServletRequest) method (which will attempt to read the request parameter with the specified name and return is as a Hidden field.
 Text getText(String name)
          Returns the field with the specific name as a Text.
 TextArea getTextArea(String name)
          Returns the field with the specific name as a TextArea.
 Timer getTimer()
           
 RefreshableSelect getUpdatableSelect(String name)
          Returns the field with the specific name as a RefreshableSelect.
 FormData handleSubmit(javax.servlet.http.HttpServletRequest req)
          Processes the submitted form.
 FormData handleSubmit(javax.servlet.http.HttpServletRequest req, Connection con)
          This method is similar to handleSubmit(HttpServletRequest) except it stores the specified connection in the form data.
static boolean hasError(FormData fd)
          Returns true if validation did not succeed.
 FormData refresh(javax.servlet.http.HttpServletRequest req)
           
 FormData refresh(javax.servlet.http.HttpServletRequest req, Connection con)
          Refreshes the form for this request by running all attached refreshers and dependencies.
 Object remove(Field field)
          Removes the specified field from the form.
 void renderDynamicFields(FormData fd, Writer out)
          Renders all dynamically added hidden fields of the form.
 void renderError(FormData fd, Writer writer)
          Convenience method to render form-level validation errors.
 void renderErrorFor(FormData fd, Writer writer, String formValidatorName)
          Convenience method to render a validation error for a particluar form level validator.
 void setActionURL(String url)
          Sets an arbitrary application specific string that can later be retrieved.
 void setDisplayURL(String url)
          Sets an arbitrary application specific string.
 String toString()
           
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

empty_list

public static final List empty_list

empty_map

public static final Map empty_map
Constructor Detail

Form

public Form(String name,
            String method,
            String actionURL,
            Log log,
            SubmitHackedHandler handler)
Creates a new form with the specified name, method (get/post) and URL


Form

public Form(String name,
            String method,
            String actionURL,
            Log log)

Form

public Form(String name,
            String method,
            String actionURL)
Creates a new form with logging to the default log retreived by Log.getDefault() and the default SubmitHackedHandler


Form

public Form(String name)
Creates a new form with the specified name, method=POST and no action URL

Method Detail

destroy

public void destroy()
This method should be called when the form is removed from session or application scope. It is very important to do this if there are background update tasks because this method stops such background refresh timer thread (which would otherwise continue to run).


remove

public Object remove(Field field)
Removes the specified field from the form. See Map.remove(Object) for the general contract.

Parameters:
field - the field to remove from the form.

add

public Form add(Field field)
Adds the specified element to the form. The added field can later be retrieved via it's name. The field iteration order will be the same order in which fields are added via this method.

Note, field names have to be unique. "Grouped" fields (such as HTML form checkboxes or radio buttons) which require the same field name are encapsulated by a single appropriate grouped field object such as RadioGroup and CheckboxGroup. This field object itself should have a unique name.

Returns:
A reference to this form as a convenience for method chaining
Throws:
IllegalArgumentException - if an element with the same name already exists in this form.

add

public Form add(Dependency d)
Adds the specified dependency to the form.


add

public Form add(FieldRef ref)
Adds a FieldRef to this Form. This is useful when to track a set of related fields in a form. (Note: those fields must also directly be added to the form).


addError

public void addError(FormData fd,
                     String errorKey,
                     String errorMessage)
Adds a form level validation error message. This method is needed when form level validation is done via classes that are not subclasses of FormValidator (these classes are used outside of the validation framework and their error message still needs to be added to the form data).

This is a very useful method for adding the results of arbitrary code to this form.

Parameters:
fd - form data
errorKey - an arbitrary/optional validation key which allows to later retrieve and display a particular form error. Specify null for no key.
errorMessage - the form error message
See Also:
Field.addError(fc.web.forms.FormData, java.lang.String)

addError

public void addError(FormData fd,
                     String errorMessage)
Convenience method that invokes addError with an empty validation errorKey.


addDynamicField

public void addDynamicField(FormData fd,
                            Hidden f)
Adds a Hidden field to this form. This field exists only for the duration of this form data object and is useful for request specific data.


addValidator

public void addValidator(FormValidator validator)
Adds a form level validator to this form. Note, validator names have to be unique and not clash with other form level validator names.

Throws:
IllegalArgumentException - if a validator with the same name already exists in this form.

addMessage

public void addMessage(FormData fd,
                       String key,
                       String value)
Adds an arbitrary message for this request. Messages can include arbitrary warnings, usage help etc.


containsField

public boolean containsField(String fieldName)
Returns true if the form contains the specified field.


getMessage

public String getMessage(FormData fd,
                         String key)
Retrieves a previously added message or null if the speccified form data was null or if the message was not found.


addSubmitHackedHandler

public void addSubmitHackedHandler(SubmitHackedHandler handler)

handleSubmit

public FormData handleSubmit(javax.servlet.http.HttpServletRequest req)
                      throws javax.servlet.ServletException,
                             IOException
Processes the submitted form. This method must be called after each form submission by the servlet or page code that handles form submits. This method does the following:
  1. populates the fields of the form from the submitted request.
  2. if the form has any dependencies and if the dependencies need updating, then those dependencies are updated. Validation is not carried out in this case since the form has changed and the user needs to typically carry out some other action before submitting the form.
  3. if there are no updated dependencies, validates the form via any validators attached to the form and it's fields.
Note: To see if there were any validation errors, invoke the hasError(FormData) method with the formdata returned by this method. Seeing validation errors is optional of course, and so is using validators in the first place.

Parameters:
req - the HttpServletRequest corresponding to the request being processed by this form.
Returns:
a FormData object containing populated field data and the results of the validation.
Throws:
javax.servlet.ServletException
IOException

handleSubmit

public FormData handleSubmit(javax.servlet.http.HttpServletRequest req,
                             Connection con)
                      throws javax.servlet.ServletException,
                             IOException
This method is similar to handleSubmit(HttpServletRequest) except it stores the specified connection in the form data. This connection can be used by any attached dependency classes for database queries when updating form depedencies.

Note, we can set arbitrary objects in the HttpServletRequest via it's setAttribute method. However, specifying and storing the connection in the FormData is easier to remember and use.

There are 2 cases:

  1. The dependent fields (if any) will internally use WebApp#getConnection to obtain a connection and no connection has to be set in the form data.
  2. The handleSubmit(HttpServletRequest) can then be used.
  3. The dependent fields (if any) classes will expect a connection in the form data. In that case, this method should be invoked.
If there are no dependent fields, then the handleSubmit(HttpServletRequest) is sufficient.

Parameters:
req - the HttpServletRequest corresponding to the request being processed by this form.
con - a connection object. The connection is not closed and it is the callers responsiblity to do so.
Throws:
javax.servlet.ServletException
IOException

refresh

public FormData refresh(javax.servlet.http.HttpServletRequest req)
                 throws javax.servlet.ServletException,
                        IOException
Throws:
javax.servlet.ServletException
IOException

refresh

public FormData refresh(javax.servlet.http.HttpServletRequest req,
                        Connection con)
                 throws javax.servlet.ServletException,
                        IOException
Refreshes the form for this request by running all attached refreshers and dependencies. Maintains form state. Does not run any validatators. Useful for re-displaying a form when lookup fields have changed in the database.

To refresh the form for all users/requests from this point onwards, create a new instance of the form and replace the existing instance of the form with the newly created instance.

Throws:
javax.servlet.ServletException
IOException

hasError

public static boolean hasError(FormData fd)
Returns true if validation did not succeed.


renderError

public void renderError(FormData fd,
                        Writer writer)
                 throws IOException
Convenience method to render form-level validation errors. This method writes validation error message for the specified form level validator. The error messages are encapulated in a html <div> tag and the class of this tag is set to form-errmsg. Each error message within this div is assigned it's own div with class set to form-errmsg-item

Parameters:
writer - the Writer to render errors to
Throws:
IOException

renderErrorFor

public void renderErrorFor(FormData fd,
                           Writer writer,
                           String formValidatorName)
                    throws IOException
Convenience method to render a validation error for a particluar form level validator. The error messages are encapulated in a html <div> tag and the class of this tag is set to form-errmsg.

Parameters:
writer - the Writer to render errors to
formValidatorName - the name of a form level validator
Throws:
IOException

getFieldErrors

public Map getFieldErrors(FormData fd)
Parameters:
fd - a non-null form data object
Returns:
a map containing field names as keys and the field's validation error as the value. The data type of each value is that returned by the Field.getValidateErrors(fc.web.forms.FormData) method

getFormErrorsCollection

public Collection getFormErrorsCollection(FormData fd)
Parameters:
fd - a non-null form data object
Returns:
a list containing form level errors. The data type of each value is that returned by the FormValidator.getErrorMessage() method

getFormErrorsFor

public List getFormErrorsFor(FormData fd,
                             String formValidatorName)
Returns a list containing all form-level errors for the specified validator. If there are no errors for the specified validator, returns an empty list.

Parameters:
fd - a non-null form data object
formValidatorName - a form validator name

renderDynamicFields

public void renderDynamicFields(FormData fd,
                                Writer out)
                         throws SQLException,
                                IOException
Renders all dynamically added hidden fields of the form. Dynamic fields are created/ added per user per submit to the FormData if/as needed.

Note: Dynamic fields are not part of a form's fields and are not available via

Throws:
SQLException
IOException

getName

public String getName()
Returns the name of this form


setActionURL

public void setActionURL(String url)
Sets an arbitrary application specific string that can later be retrieved. Some applications may find this method useful.


getActionURL

public String getActionURL()
Returns the action URL string. Returns null if no url has been set.


setDisplayURL

public void setDisplayURL(String url)
Sets an arbitrary application specific string. Intended to store the URL to the jsp or front end page that will render this form for the user.


getDisplayURL

public String getDisplayURL()
Returns the display URL string. Returns null if no display url has been set.


getAllFields

public Collection getAllFields()
Returns a collection view of all the fields contained in this form.


get

public Field get(String name)
Returns the form field with the specified name.

Parameters:
name - the name of the field
Returns:
the field or null if no element with that name was found in this form.

getDynamicField

public Hidden getDynamicField(FormData fd,
                              String fieldName)
Gets a Hidden field added to the form data object. Returns null if the form data object is null or if the specified field does not exist. Dyanamic fields returned by this method are only available for the duration of the form data object and can not obtain a field from a submitted form. (use getDynamicField(FormData, HttpServletRequest) for that purpose.


getSubmittedField

public Hidden getSubmittedField(javax.servlet.http.HttpServletRequest req,
                                String name)
Once the form is displayed to the user (with, say, hidden fields that were added dynamically for that request), then when that form is submitted, those dynamic fields can be retrieved via any of:
  • the ServletRequest.getParameter(java.lang.String) method (often the easiest way)
  • the #getSubmittedField(HttpServletRequest) method (which will attempt to read the request parameter with the specified name and return is as a Hidden field. (this is slightly more convenient if there is more than 1 hidden field with the same name, since all hidden fields with the same name are encapsulated by one object of type Hidden).


getContaining

public List getContaining(String name)
Returns all the fields that contains the specified name. This is useful when a bunch of fields are created via database lookup tables (and each such field is prefixed/suffixed by say lookup_name + some number).

Parameters:
name - the name of the field
Returns:
a List containing fields with matching names or or an empty list if no elements containing that name were found in this form.

getFieldRef

public FieldRef getFieldRef(String key)
Returns the FieldRef with the specified key. This is used to retrieve an arbitrary object added the via #addObject method. Returns null if no object is found for the specified key.


getTimer

public Timer getTimer()

getSelect

public Select getSelect(String name)
Returns the field with the specific name as a Select.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Select

getUpdatableSelect

public RefreshableSelect getUpdatableSelect(String name)
Returns the field with the specific name as a RefreshableSelect.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type RefreshableSelect

getCheckbox

public Checkbox getCheckbox(String name)
Returns the field with the specific name as a Checkbox.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Checkbox

getCheckboxGroup

public CheckboxGroup getCheckboxGroup(String name)
Returns the field with the specific name as a Checkbox.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Checkbox

getHidden

public Hidden getHidden(String name)
Returns the field with the specific name as a Hidden.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Hidden

getText

public Text getText(String name)
Returns the field with the specific name as a Text.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Text

getTextArea

public TextArea getTextArea(String name)
Returns the field with the specific name as a TextArea.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type TextArea

getPassword

public Password getPassword(String name)
Returns the field with the specific name as a Password.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Password

getRadio

public Radio getRadio(String name)
Returns the field with the specific name as a Radio.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Radio

getRadioGroup

public RadioGroup getRadioGroup(String name)
Returns the field with the specific name as a Checkbox.

Throws:
IllegalArgumentException - if a field with the specified name does not exist or if the field exists but is not of type Checkbox

toString

public String toString()
Overrides:
toString in class Object