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