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
019/**
020Validates that a group of fields is filled by the user. By default, every
021field must be filled. However, optionally it can be specified that every
022field in the group is not filled (all empty), only 1 field is filled or
0231 or more fields (greater than zero) are filled.
024
025@author hursh jain
026**/
027public final class VFilledGroup extends FormValidator
028{
029Field[] fields;
030
031boolean allFilledOrEmpty;
032boolean onlyOneEmpty;
033boolean onlyOneFilled;
034boolean oneOrMoreFilled;
035
036static final boolean dbg = false;
037
038
039/** 
040@param  fields  a non-empty list containting fields to be 
041        checked. 
042**/
043public 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**/
057public 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/**
070Calling this method will result in requiring that all fields
071must be filled except for any one empty field. Calling 
072this method overrides any other methods that were called 
073previously.
074*/
075public VFilledGroup onlyOneEmpty()
076  {
077  allFilledOrEmpty = false;
078  onlyOneEmpty = true;
079  onlyOneFilled = false;
080  oneOrMoreFilled = false;
081
082  return this;
083  }
084
085/**
086Calling this method will result in requiring that all fields be
087empty except for exactly one filled field (any field). Calling
088this method overrides any other methods that were called
089previously.
090*/
091public VFilledGroup onlyOneFilled()
092  {
093  allFilledOrEmpty = false;
094  onlyOneEmpty = false;
095  onlyOneFilled = true;
096  oneOrMoreFilled = false;
097
098  return this;
099  }
100
101/**
102Calling this method will result in requiring that one or more
103fields by filled (all the fields cannot be empty). Calling 
104this method overrides any other methods that were called 
105previously.
106*/
107public VFilledGroup oneOrMoreFilled()
108  {
109  allFilledOrEmpty = false;
110  onlyOneEmpty = false;
111  onlyOneFilled = false;
112  oneOrMoreFilled = true;
113
114  return this;
115  }
116
117/**
118This is the default mode. Requires that all fields must be
119filled. Calling this method overrides any other methods that were
120called previously.
121*/
122public VFilledGroup allFilledOrEmpty()
123  {
124  allFilledOrEmpty = true;
125  onlyOneEmpty = false;
126  onlyOneFilled = false;
127  oneOrMoreFilled = false;
128  
129  return this;
130  }
131
132public 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  
144private 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
158private 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
179private 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
200private 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}