001    package hirondelle.web4j.util;
002    
003    import java.util.regex.*;
004    
005    /**
006     Utility methods for common argument validations.
007    
008    <P>Replaces <tt>if</tt> statements at the start of a method with 
009     more compact method calls.
010     
011     <P>Example use case.
012     <P>Instead of :
013     <PRE>
014     public void doThis(String aText){
015       if (!Util.textHasContent(aText)){
016         throw new IllegalArgumentException();
017       }
018       //..main body elided
019     }
020     </PRE>
021     <P>One may instead write :
022     <PRE>
023     public void doThis(String aText){
024       Args.checkForContent(aText);
025       //..main body elided
026     }
027     </PRE>
028    */
029    public final class Args {
030      
031      /**
032       If <code>aText</code> does not satisfy {@link Util#textHasContent}, then 
033       throw an <code>IllegalArgumentException</code>.
034      
035       <P>Most text used in an application is meaningful only if it has visible content.
036      */
037      public static void checkForContent(String aText){
038        if( ! Util.textHasContent(aText) ){
039          throw new IllegalArgumentException("Text has no visible content");
040        }
041      }
042    
043      /**
044       If {@link Util#isInRange} returns <code>false</code>, then 
045       throw an <code>IllegalArgumentException</code>. 
046      
047       @param aLow is less than or equal to <code>aHigh</code>.
048      */
049      public static void checkForRange(int aNumber, int aLow, int aHigh) {
050        if ( ! Util.isInRange(aNumber, aLow, aHigh) ) {
051          throw new IllegalArgumentException(aNumber + " not in range " + aLow + ".." + aHigh);
052        }
053      }
054    
055      /**
056       If <tt>aNumber</tt> is less than <tt>1</tt>, then throw an 
057       <tt>IllegalArgumentException</tt>.
058      */
059      public static void checkForPositive(int aNumber) {
060        if (aNumber < 1) {
061          throw new IllegalArgumentException(aNumber + " is less than 1");
062        }
063      }
064    
065      /**
066       If {@link Util#matches} returns <tt>false</tt>, then 
067       throw an <code>IllegalArgumentException</code>. 
068      */
069      public static void checkForMatch(Pattern aPattern, String aText){
070        if (! Util.matches(aPattern, aText)){
071          throw new IllegalArgumentException(
072            "Text " + Util.quote(aText) + " does not match '" +aPattern.pattern()+ "'"
073          );
074        }
075      }
076      
077      /**
078       If <code>aObject</code> is null, then throw a <code>NullPointerException</code>.
079      
080       <P>Use cases :
081      <pre>
082       doSomething( Football aBall ){
083         //1. call some method on the argument : 
084         //if aBall is null, then exception is automatically thrown, so 
085         //there is no need for an explicit check for null.
086         aBall.inflate();
087        
088         //2. assign to a corresponding field (common in constructors): 
089         //if aBall is null, no exception is immediately thrown, so 
090         //an explicit check for null may be useful here
091         Args.checkForNull( aBall );
092         fBall = aBall;
093         
094         //3. pass on to some other method as parameter : 
095         //it may or may not be appropriate to have an explicit check 
096         //for null here, according the needs of the problem
097         Args.checkForNull( aBall ); //??
098         fReferee.verify( aBall );
099       }
100       </pre>
101      */
102      public static void checkForNull(Object aObject) {
103        if (aObject == null) {
104          throw new NullPointerException();
105        }
106      }
107      
108      // PRIVATE 
109      private Args(){
110        //empty - prevent construction
111      }
112    }