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.simpleforms;
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/**
019Utility methods for common validation needs.
020
021@author hursh jain
022**/
023public final class Valid
024{
025final   static boolean     dbg = false; //internal debugging
026    static boolean     trim = true;
027private static final String  intOnlyRE_str    = "\\s*\\d*\\s*";
028private static final Pattern intOnlyRE      = Pattern.compile(intOnlyRE_str); 
029private static final String  isFloatOnlyRE_str  = "\\s*-?\\d*\\.?\\d*\\s*";
030private static final Pattern isFloatOnlyRE    = Pattern.compile(isFloatOnlyRE_str);
031    
032/**
033If set to <tt>true</tt>, methods in this class will trim the string 
034entered by the user before attempting to run further validation on it,
035else strings will not be trimmed automatically. Defaults to 
036<tt>true</tt>.
037*/
038public static void setTrimSpaces(boolean val)
039  {
040  trim = val;
041  }
042
043/**
044Ensures that the string is composed of only an digits [0-9] with
045optional leading/trailing blanks. (floating point/real numbers are
046not allowed because they contain a ".")
047*/
048public static boolean isIntegerOnly(String str) 
049  {
050  if (str == null)
051    return false;
052    
053  if (trim) {
054    str = str.trim();
055    }
056    
057  return intOnlyRE.matcher(str).matches();
058  }
059
060/**
061Ensures that the string is composed of only floating point
062numbers (digits [0-9] and maybe a  "."), with optional 
063leading/trailing blanks. Negative numbers (with a leading "-")
064are also allowed.
065*/
066public static boolean isFloatOnly(String str) 
067  {
068  if (str == null)
069    return false;
070    
071  if (trim) {
072    str = str.trim();
073    }
074    
075  return isFloatOnlyRE.matcher(str).matches();
076  }
077
078
079public static boolean isEmpty(String str) 
080  {
081  if (str == null) {
082    return false;
083    }
084  
085  if (trim) {
086    str = str.trim();
087    }
088  
089  if (str.length() == 0) {
090    return true;
091    }
092    
093  return false;
094  }
095
096/**
097Returns <tt>true</tt> is the specified string is not <tt>null</tt> <b>and</b> 
098not empty (<tt>""</tt>).
099*/
100public static boolean isNotEmpty(String str) 
101  {
102  if (str == null) {
103    return false;
104    }
105  
106  if (trim) {
107    str = str.trim();
108    }
109  
110  if (str.length() == 0) {
111    return false;
112    }
113
114  return true;
115  }
116
117/**
118Returns true if the string is non-empty and it's length
119is between the specified min and max lengths (both inclusive).
120*/
121public static boolean length(String str, final int min, final int max) 
122  {
123  if (str == null) {
124    return false;
125    }
126
127  if (trim) {
128    str = str.trim();
129    }
130    
131  final int len = str.length();
132  if (len < min || len > max) {
133    return false;
134    }
135
136  return true;
137  }
138
139/**
140Returns <tt>true</tt> if the specified string only contains the
141allowed characters. If the string contains any other characters
142that are not allowed, returns <tt>false</tt>
143*/
144public static boolean isAllowed(String str, final String allowedChars)
145  {
146  if (str == null)
147    return false;
148
149  if (trim) {
150    str = str.trim();
151    }
152  
153  for (int n = 0; n < str.length(); n++) 
154    {
155    char c = str.charAt(n);
156    boolean found = false;
157    for (int k = 0; k < allowedChars.length(); k++) 
158      {
159      char mchar = allowedChars.charAt(k);
160      if (c == mchar) {
161        found = true;
162        }
163      }
164    if (! found) {
165      return false;
166      }
167    }
168  
169  return true;
170  }
171
172/**
173Returns <tt>true</tt> if the specified string has no unallowed
174characters. If the string contains any unallowed characters, returns
175<tt>false</tt>
176*/
177public static boolean isNotAllowed(String str, final String unallowedChars)
178  {
179  if (str == null)
180    return false;
181
182  if (trim) {
183    str = str.trim();
184    }
185  
186  for (int n = 0; n < str.length(); n++) 
187    {
188    char c = str.charAt(n);
189    boolean passed = true;
190    for (int k = 0; k < unallowedChars.length(); k++) 
191      {
192      char mchar = unallowedChars.charAt(k);
193      if (c == mchar) {
194        passed = false;
195        }
196      }
197    if (! passed) {
198      return false;
199      }
200    }
201  
202  return true;
203  }
204
205public static void main (String args[])
206  {
207  p("Valid.isIntegerOnly(\" 3243 \")", Valid.isIntegerOnly(" 3243 "), true );  //trim
208  p("Valid.isIntegerOnly(\" 3243. \")",  Valid.isIntegerOnly(" 3243. "), false );
209  
210  p( "Valid.isFloatOnly(\" 3243. \")", Valid.isFloatOnly(" 3243. "), true );
211  p( "Valid.isFloatOnly(\" -3243. \")", Valid.isFloatOnly(" -3243. "), true );
212  p( "Valid.isFloatOnly(\" -3243.003 \")", Valid.isFloatOnly(" -3243.003 "), true );
213  p( "Valid.isFloatOnly(\".3243.0\")", Valid.isFloatOnly(".3243.0"), false );
214  p( "Valid.isFloatOnly(\"-32dd43.003\")", Valid.isFloatOnly("-32dd43.003"), false );
215  
216  p( "Valid.isEmpty(\"  \")", Valid.isEmpty("  "), true); //if trim
217  p( "Valid.isEmpty(\"\")", Valid.isEmpty(""), true);
218  
219  p( "Valid.length(\" abc  \", 1, 3)", Valid.length(" abc  ", 1, 3), true ); //trim
220  Valid.setTrimSpaces(false);
221  p( "Valid.length(\" abc  \", 1, 3)", Valid.length(" abc  ", 1, 3), false ); 
222  Valid.setTrimSpaces(true);
223    
224  p( "Valid.isAllowed\"abc\", \"abc\")", Valid.isAllowed("abc", "abc"), true );
225  p( "Valid.isAllowed(\"abc\", \"abcdef\")", Valid.isAllowed("abc", "abcdef"), true );
226  p( "Valid.isAllowed(\"abc\", \"ab\")", Valid.isAllowed("abc", "ab"), false );
227  p( "Valid.isAllowed(\"abc\", \"\")", Valid.isAllowed("abc", ""), false );
228  
229  p( "Valid.isNotAllowed(\"abc\", \"4\")", Valid.isNotAllowed("abc", "4"), true ); 
230  p( "Valid.isNotAllowed(\"abc\", \"#!@9\")", Valid.isNotAllowed("abc", "#!@9"), true ); 
231  p( "Valid.isNotAllowed(\"abc4\", \"\")", Valid.isNotAllowed("abc4", ""), true ); 
232  p( "Valid.isNotAllowed(\"abc4\", \"a\")", Valid.isNotAllowed("abc4", "a"), false ); 
233  
234  if (_badcount == 0)
235    System.out.println("All internal tests were successful..");
236  else
237    System.out.println(_badcount + " tests failed..");
238  }
239  
240private static int _badcount = 0;
241private static void p(String s, boolean a, boolean b)
242  {
243  if (a != b) {
244    _badcount++;
245    System.out.println("FAILED: " + s);
246    }
247  }
248}          //~class Valid