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    /**
020    Validates that a group of fields is filled by the user. By default, every
021    field must be filled. However, optionally it can be specified that every
022    field in the group is not filled (all empty), only 1 field is filled or
023    1 or more fields (greater than zero) are filled.
024    
025    @author hursh jain
026    **/
027    public final class VFilledGroup extends FormValidator
028    {
029    Field[] fields;
030    
031    boolean allFilledOrEmpty;
032    boolean onlyOneEmpty;
033    boolean onlyOneFilled;
034    boolean oneOrMoreFilled;
035    
036    static final boolean dbg = false;
037    
038    
039    /** 
040    @param  fields  a non-empty list containting fields to be 
041            checked. 
042    **/
043    public VFilledGroup(Form f, String name, String errorMessage, List fields)
044      {
045      //we must make a copy of the fields because the caller
046      //can change the list behind our back (by re-using the
047      //list variable during form creation)
048      
049      this(f, name, errorMessage, 
050          (Field[]) fields.toArray(new Field[0]));
051      }
052    
053    /** 
054    @param  fields  a non-empty array containting fields to be 
055            checked. 
056    **/
057    public VFilledGroup(Form f,
058     String name, String errorMessage, Field[] fields)
059      {
060      super(f, name, errorMessage);
061      Argcheck.istrue(fields.length > 0, "specified field list was empty");
062      this.fields = fields;
063      allFilledOrEmpty = true;
064      onlyOneEmpty = false;
065      onlyOneFilled = false;
066      oneOrMoreFilled = false;
067      }
068    
069    /**
070    Calling this method will result in requiring that all fields
071    must be filled except for any one empty field. Calling 
072    this method overrides any other methods that were called 
073    previously.
074    */
075    public VFilledGroup onlyOneEmpty()
076      {
077      allFilledOrEmpty = false;
078      onlyOneEmpty = true;
079      onlyOneFilled = false;
080      oneOrMoreFilled = false;
081    
082      return this;
083      }
084    
085    /**
086    Calling this method will result in requiring that all fields be
087    empty except for exactly one filled field (any field). Calling
088    this method overrides any other methods that were called
089    previously.
090    */
091    public VFilledGroup onlyOneFilled()
092      {
093      allFilledOrEmpty = false;
094      onlyOneEmpty = false;
095      onlyOneFilled = true;
096      oneOrMoreFilled = false;
097    
098      return this;
099      }
100    
101    /**
102    Calling this method will result in requiring that one or more
103    fields by filled (all the fields cannot be empty). Calling 
104    this method overrides any other methods that were called 
105    previously.
106    */
107    public VFilledGroup oneOrMoreFilled()
108      {
109      allFilledOrEmpty = false;
110      onlyOneEmpty = false;
111      onlyOneFilled = false;
112      oneOrMoreFilled = true;
113    
114      return this;
115      }
116    
117    /**
118    This is the default mode. Requires that all fields must be
119    filled. Calling this method overrides any other methods that were
120    called previously.
121    */
122    public VFilledGroup allFilledOrEmpty()
123      {
124      allFilledOrEmpty = true;
125      onlyOneEmpty = false;
126      onlyOneFilled = false;
127      oneOrMoreFilled = false;
128      
129      return this;
130      }
131    
132    public boolean validate(FormData fd, HttpServletRequest req) 
133      {
134      if (oneOrMoreFilled)
135        return v_oneOrMoreFilled(fd);
136      else if (onlyOneEmpty)
137        return v_onlyOneEmpty(fd);  
138      else if (onlyOneFilled)
139        return v_onlyOneFilled(fd);
140      else 
141        return v_allFilledOrEmpty(fd);  
142      }
143      
144    private boolean v_oneOrMoreFilled(FormData fd)
145      {
146      int count = fields.length;
147      for (int n = 0; n < count; n++) 
148        {
149        Field f = fields[n];
150        if (f.isFilled(fd))
151          return true;
152        }
153        
154      return false;
155      }
156        
157    
158    private boolean v_onlyOneFilled(FormData fd)
159      {
160      int count = fields.length;
161      boolean one_filled = false;
162        
163      for (int n = 0; n < count; n++) 
164        {
165        Field f = fields[n];
166        if (dbg) System.out.println("field " + f.name + " isFilled()=" + f.isFilled(fd));
167        if (f.isFilled(fd)) 
168          {  
169          if (one_filled)
170            return false;
171          one_filled = true; //latch
172          }
173        } 
174        
175      return true;
176      } 
177    
178    
179    private boolean v_onlyOneEmpty(FormData fd)
180      {
181      int count = fields.length;
182      boolean one_empty = false;
183        
184      for (int n = 0; n < count; n++) 
185        {
186        Field f = fields[n];
187        if (dbg) System.out.println("field " + f.name + " isFilled()=" + f.isFilled(fd));
188        if (! f.isFilled(fd)) 
189          {  
190          if (one_empty)
191            return false;
192          one_empty = true; //latch
193          }
194        } 
195        
196      return true;  
197      } 
198    
199    
200    private boolean v_allFilledOrEmpty(FormData fd)
201      {
202      int count = fields.length;
203      boolean allempty = true;
204      boolean allfilled = true;
205      
206      boolean result = true;
207      
208      for (int n = 0; n < count; n++) 
209        {
210        Field f = fields[n];
211        if (dbg) System.out.println("field " + f.name + " isFilled()=" + f.isFilled(fd));
212        if (f.isFilled(fd)) { //field is filled 
213          allempty = false; //latch
214          }
215        else{ //field is not filled
216          //all othe fields must also be empty (we have to 
217          //go thru the entire list)
218          allfilled = false;   //latch   
219          }
220        }
221      
222      return (allempty || allfilled);
223      } 
224    
225    
226    }