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.util.regex.*;
013    
014    import fc.jdbc.*;
015    import fc.io.*;
016    import fc.util.*;
017    
018    /**
019    Validates that a certain radio or checkbox button selected
020    (or not selected) implies that other fields in the form are 
021    also filled out. For example:
022    <p>
023    A radio button called "yes" is chosen by the user and
024    this requires that a "yes_detail" field be filled out.
025    
026    @author hursh jain
027    **/
028    public class VFilledOnChoice extends VConditional
029    {
030    ChoiceGroup cg;
031    List    postFields;
032    String    choiceValue;
033    boolean   onSelect = true;
034    boolean   anyFilledOK = false;
035    static final boolean dbg = false;
036    
037    /** 
038    @param  f      the form
039    @param  name     name for this validator
040    @param  errorMessage validation error message
041    @param  choice     a pre condition choice group
042    @param  val      the specific value of the pre condition choice group
043               which will trigger the check to see that
044               post condition fields are filled out
045    @param  postFields   a non-empty list containing fields for
046               the post condition
047    */
048    public VFilledOnChoice(Form f, String name, String errorMessage, 
049     ChoiceGroup cg, String choiceValue, List postFields)
050      {
051      super(f, name, errorMessage);
052      Argcheck.istrue(postFields.size() > 0, "specified post field list was empty");
053      Argcheck.istrue(cg != null, "specified choicegroup field was null");
054      Argcheck.istrue(choiceValue != null && choiceValue.length() > 0, "choiceValue was null or empty");
055      
056      this.cg = cg;
057      this.choiceValue = choiceValue;
058      
059      //we must make a copy of the fields because the caller
060      //can change the list behind our back (by re-using the
061      //list variable during form creation)
062      this.postFields =  new ArrayList(postFields);
063      }
064    
065    public VFilledOnChoice(Form f, String name, String errorMessage, 
066     ChoiceGroup cg, String choiceValue, Field[] postFields)
067      {
068      this(f, name, errorMessage, cg, choiceValue, 
069        Arrays.asList(postFields));
070      }
071    
072    /**
073    By default, this validator checks to see that <i>all</i>
074    post-condition fields are filled. However, if <tt>true</tt> is
075    specified to this method, then validation will be successful if
076    <i>any</i> specified field is filled.
077    */
078    public VFilledOnChoice anyFilled(boolean val)
079      {
080      anyFilledOK = val;  
081      return this;
082      }
083    
084    public boolean preConditionMet(FormData fd, HttpServletRequest req)
085      {
086      boolean choiceFilled = cg.isFilled(fd);  //filled at all ?
087      if (choiceFilled)  //filled with the value we want ?
088        {
089        Iterator it = cg.getValue(fd).iterator();
090        while (it.hasNext())
091          {
092          ChoiceGroup.Choice c = (ChoiceGroup.Choice) it.next();
093          String str = c.getValue();
094          if (choiceValue.equals(str)) {
095            choiceFilled = true;
096            break;
097            }
098          else {
099            choiceFilled = false;
100            }
101          }
102        }
103      
104      if (onSelect)  //some choice has to be selected first
105        {
106        if (! choiceFilled) //not selected
107          return false;
108        }
109      else {   //choice should not selected by user
110        if (choiceFilled) //selected
111          return false;
112        }
113        
114      return true;
115      } 
116    
117    public boolean postConditionMet(FormData fd, HttpServletRequest req)
118      {
119      int count = postFields.size();
120      boolean one_filled = false;
121      
122      for (int n = 0; n < count; n++) 
123        {
124        Field f = (Field) postFields.get(n);
125        boolean filled = f.isFilled(fd);
126        
127        if (filled)
128          {
129          if (anyFilledOK) 
130            {   //any filled is a-ok
131            if (dbg) System.out.println(f.name + " is filled, anyfilled=ok, returning true");
132            return true;
133            }
134          else{ // ALL have to be filled, keep truckin
135            one_filled = true; //latch
136              }
137          }
138        
139        if (! filled)       //field is empty
140          {
141          if (! anyFilledOK)      //no empty field allowed
142            {
143            if (dbg) System.out.println(f.name + " is filled, anyfilled=!ok, returning false");
144            return false;
145            }
146          //else {
147          //   //keep truckin
148          //   }
149          }
150        }
151      
152      //we made it here, all fields were filled.
153      
154      if (! one_filled)
155        return false;
156      
157      return true;
158      } 
159    
160    /**
161    Sets whether validation will occur if the choice is
162    selected by the user or not. By default, validation
163    occurs when the choice is selected by the user.
164    
165    @param  val   <tt>true</tt> to validate only when selected
166            <tt>false</tt> otherwise.
167    */
168    public void onSelected(boolean val)
169      {
170      onSelect = val;
171      }
172    
173    }          //~class ValidatorConditionalFilled
174