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 javax.servlet.*;
009import javax.servlet.http.*;
010import java.io.*;
011import java.util.*;
012import java.util.regex.*;
013
014import fc.jdbc.*;
015import fc.io.*;
016import fc.util.*;
017
018/**
019Validates that a certain radio or checkbox button selected
020(or not selected) implies that other fields in the form are 
021also filled out. For example:
022<p>
023A radio button called "yes" is chosen by the user and
024this requires that a "yes_detail" field be filled out.
025
026@author hursh jain
027**/
028public class VFilledOnChoice extends VConditional
029{
030ChoiceGroup cg;
031List    postFields;
032String    choiceValue;
033boolean   onSelect = true;
034boolean   anyFilledOK = false;
035static 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*/
048public 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
065public 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/**
073By default, this validator checks to see that <i>all</i>
074post-condition fields are filled. However, if <tt>true</tt> is
075specified to this method, then validation will be successful if
076<i>any</i> specified field is filled.
077*/
078public VFilledOnChoice anyFilled(boolean val)
079  {
080  anyFilledOK = val;  
081  return this;
082  }
083
084public 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
117public 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/**
161Sets whether validation will occur if the choice is
162selected by the user or not. By default, validation
163occurs 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*/
168public void onSelected(boolean val)
169  {
170  onSelect = val;
171  }
172
173}          //~class ValidatorConditionalFilled
174