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.simpleforms;
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    Utility methods for common validation needs.
020    
021    @author hursh jain
022    **/
023    public final class Valid
024    {
025    final   static boolean     dbg = false; //internal debugging
026        static boolean     trim = true;
027    private static final String  intOnlyRE_str    = "\\s*\\d*\\s*";
028    private static final Pattern intOnlyRE      = Pattern.compile(intOnlyRE_str); 
029    private static final String  isFloatOnlyRE_str  = "\\s*-?\\d*\\.?\\d*\\s*";
030    private static final Pattern isFloatOnlyRE    = Pattern.compile(isFloatOnlyRE_str);
031        
032    /**
033    If set to <tt>true</tt>, methods in this class will trim the string 
034    entered by the user before attempting to run further validation on it,
035    else strings will not be trimmed automatically. Defaults to 
036    <tt>true</tt>.
037    */
038    public static void setTrimSpaces(boolean val)
039      {
040      trim = val;
041      }
042    
043    /**
044    Ensures that the string is composed of only an digits [0-9] with
045    optional leading/trailing blanks. (floating point/real numbers are
046    not allowed because they contain a ".")
047    */
048    public 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    /**
061    Ensures that the string is composed of only floating point
062    numbers (digits [0-9] and maybe a  "."), with optional 
063    leading/trailing blanks. Negative numbers (with a leading "-")
064    are also allowed.
065    */
066    public 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    
079    public 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    /**
097    Returns <tt>true</tt> is the specified string is not <tt>null</tt> <b>and</b> 
098    not empty (<tt>""</tt>).
099    */
100    public 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    /**
118    Returns true if the string is non-empty and it's length
119    is between the specified min and max lengths (both inclusive).
120    */
121    public 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    /**
140    Returns <tt>true</tt> if the specified string only contains the
141    allowed characters. If the string contains any other characters
142    that are not allowed, returns <tt>false</tt>
143    */
144    public 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    /**
173    Returns <tt>true</tt> if the specified string has no unallowed
174    characters. If the string contains any unallowed characters, returns
175    <tt>false</tt>
176    */
177    public 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    
205    public 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      
240    private static int _badcount = 0;
241    private 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