001    // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002    // The Molly framework is freely distributable under the terms of an
003    // MIT-style license. For details, see the molly pages web site at:
004    // http://www.mollypages.org/. Use, modify, have fun !
005    
006    package fc.web.forms;
007    
008    import javax.servlet.*;
009    import javax.servlet.http.*;
010    import java.io.*;
011    import java.util.*;
012    import java.sql.*;
013      
014    import fc.jdbc.*;
015    import fc.io.*;
016    import fc.util.*;
017    
018    /** 
019    A dependency changes the values or state of some form element based
020    on the user selection or choice of some <i>other</i> form element. 
021    <p>
022    A typical example includes filling later select/popup values based on 
023    the user chosen value of an earlier select in the form. So, for example,
024    if the user chooses a country, then the later select shows the states
025    just for that country. 
026    <p>
027    There are several ways to handle dependency changes:
028    <ol>
029    <li>The data for some fields (like database based lookup tables) can be
030    looked up every time. 
031    <li>All possible options can be looked up ahead of time and then a
032    subset displayed accordingly. This can be done on the server side (on
033    form submit) or by client side javascript (using various javascript
034    arrays containing different sets of data, the arrays are written out
035    by the server as part of the page and swapped out by client side js).
036    <p>
037    Orthogonal to all this is field and form validation. Validation only
038    makes sense <b>after</b> we have displayed the updated fields to the user
039    For example, initially a country popup may be empty and a state popup
040    may be empty. When the user selects a country, then the form is submitted.
041    At that point, the states popup is still empty and we should *not* validate
042    the states data (i.e., not show the user a message that a state must be
043    chosen or show a validation error for any other fields which the user hasn't 
044    filled out yet). 
045    <p>
046    Validation can always be controlled by enabled/disabled flag on the field
047    since field validators are not run for fields that are disabled. In addition,
048    any time a field has new dependent values, the form is not validated by field
049    validators. 
050    
051    @author hursh jain
052    **/
053    public interface Dependency
054    {
055    
056    /**
057    Sets new values for target field in the FormData object. The target field
058    then uses those values to render itself to the client. The data should be
059    saved in FormData with the field name as the key.
060    <p>
061    <b>Note:</b>This method <blink>must</blink> invoke {@link FormData#setDependencyUpdated}
062    if it sets new values in the formdata object. New values are values that
063    are different from the values that were last displayed to the client.
064    <p>
065    There are 2 conditions that typically must be satisfied for this to be
066    true:
067    <ol>
068    <li><i>Source not null</i>: The source fields must have some data. For
069    example, a country popup needs to be selected to some country value before
070    the target dependent field (a state popup) can be populated. If no country
071    is selected, we cannot calculate a dependent state value.
072    </li>
073    <li><i>Source changed:</i> The source fields must have different data than
074    the last time the form was rendered (which means that the client made a
075    different selection/choice). For example, previously, the source field
076    could have been 'usa'. The client then either changes that to 'uk' or
077    leaves it alone. The last_value (which is rendered as a hidden field in the
078    form) in conjunction with the submittd value of the source field(s) can be
079    used to figure out if there was a dependency change. If the source value is
080    'usa' and the last_value is 'usa', then we know there is no need for any
081    dependency updates (since the usa values are already shown to the user).
082    </li>
083    </ol>
084    */
085    public void updateValues(FormData fd, HttpServletRequest req) throws DependencyException;
086    
087    /**
088    The inverse of {@link renderDependencyData}, sets any depedency data submitted
089    as part of the form. This data is set in the specified {@link FormData} object
090    and can be later used by the {@link updateValues} method.
091    */
092    public void setDependencyDataFromSubmit(FormData fd, HttpServletRequest req);
093    
094    /**
095    Writes out data to keep track of dependency state. This data is typically
096    the last selected values of some source field (say last selected source 
097    country for a target dependent state field) and usually written out as a
098    hidden field in the form.
099    */
100    public void renderDependencyData(FormData fd, Writer writer) 
101    throws SQLException, IOException;
102    
103    /**
104    Returns the initial values for the target field  These are the values that
105    are displayed when the form is first rendered. The returned object is of a
106    type that is suitable for the data of the target field. (typically an instance
107    of a static inner data class of that field).
108    <p>
109    If there is no initial data, the returned object can also be <tt>null</tt> or
110    an empty data object, depending on what the target field expects when there
111    is no data.
112    */
113    public Object getInitialValues(Field f);
114    
115    /**
116    Returns true if the submitted values are in a valid range of values. 
117    For ultra-secure applications, the validity can be computed every time by
118    recomputing/retrieving the dependent data and of-course, database
119    constraints should always be employed.
120    <p>
121    If this method is not applicable, this method should return
122    <tt>true</tt> every time.
123    */
124    public boolean  isSubmitDataValid(FormData fd);
125    }
126